diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -305,7 +305,6 @@ mlx.4 \ mlx4en.4 \ mlx5en.4 \ - mly.4 \ mmc.4 \ mmcsd.4 \ mod_cc.4 \ diff --git a/share/man/man4/mly.4 b/share/man/man4/mly.4 deleted file mode 100644 --- a/share/man/man4/mly.4 +++ /dev/null @@ -1,275 +0,0 @@ -.\" -.\" Copyright (c) 2000 Michael Smith -.\" Copyright (c) 2000 BSDi -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. 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 August 10, 2004 -.Dt MLY 4 -.Os -.Sh NAME -.Nm mly -.Nd Mylex AcceleRAID/eXtremeRAID family 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 da" -.Cd "device mly" -.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 -mly_load="YES" -.Ed -.Sh DEPRECATION NOTICE -The -.Nm -driver is not present in -.Fx 13.0 . -.Sh DESCRIPTION -The -.Nm -driver provides support for Mylex AcceleRAID and eXtremeRAID-family -PCI to SCSI RAID controllers with version 6.00 and later -firmware. -.Pp -Logical devices (array drives) attached to the controller are presented -to the SCSI subsystem as though they were direct-access devices on a -virtual SCSI bus. -Physical devices which are not claimed by a logical -device are presented on SCSI channels which match the physical channels -on the controller. -.Sh HARDWARE -Controllers supported by the -.Nm -driver include: -.Pp -.Bl -bullet -compact -.It -Mylex AcceleRAID 160 -.It -Mylex AcceleRAID 170 -.It -Mylex AcceleRAID 352 -.It -Mylex eXtremeRAID 2000 -.It -Mylex eXtremeRAID 3000 -.El -.Pp -Compatible Mylex controllers not listed should work, but have not been -verified. -.Sh DIAGNOSTICS -.Ss Controller initialisation phase -.Bl -diag -.It "mly%d: controller initialisation started" -.It "mly%d: initialisation complete" -.Pp -The controller firmware has started initialisation. -Normally this process is performed by the controller BIOS, -but the driver may need -to do this in cases where the BIOS has failed, or is not compatible -(e.g.\& on non-x86 systems). -.It "mly%d: drive spinup in progress" -.Pp -Drive startup is in progress; this may take several minutes. -.It "mly%d: mirror race recovery failed, one or more drives offline" -.It "mly%d: mirror race recovery in progress" -.It "mly%d: mirror race recovery on a critical drive" -.Pp -These error codes are undocumented. -.It "mly%d: FATAL MEMORY PARITY ERROR" -.Pp -Firmware detected a fatal memory error; the driver will not attempt to -attach to this controller. -.It "mly%d: unknown initialisation code %x" -.Pp -An unknown error occurred during initialisation; it will be ignored. -.El -.Ss Driver initialisation/shutdown phase -.Bl -diag -.It "mly%d: can't enable busmaster feature" -.It "mly%d: memory window not available" -.It "mly%d: can't allocate register window" -.It "mly%d: can't allocate interrupt" -.It "mly%d: can't set up interrupt" -.Pp -The system's PCI BIOS has not correctly configured the controller's -PCI interface; initialisation has failed and the driver will not -attach to this controller. -.It "mly%d: can't allocate parent DMA tag" -.It "mly%d: can't allocate buffer DMA tag" -.It "mly%d: can't allocate command packet DMA tag" -.It "mly%d: can't allocate scatter/gather DMA tag" -.It "mly%d: can't allocate s/g table" -.It "mly%d: can't allocate memory mailbox DMA tag" -.It "mly%d: can't allocate memory mailbox" -.Pp -A resource allocation error occurred while initialising the driver; -initialisation has failed and the driver will not attach to this -controller. -.It "mly%d: BTL rescan result corrupted" -.Pp -The results of a scan for an attached device were corrupted. -One or more devices may not be correctly reported. -.It "mly%d: flushing cache..." -.Pp -The controller cache is being flushed prior to detach or shutdown. -.El -.Ss Operational diagnostics -.Bl -diag -.It "mly%d: physical device %d:%d online" -.It "mly%d: physical device %d:%d standby" -.It "mly%d: physical device %d:%d automatic rebuild started" -.It "mly%d: physical device %d:%d manual rebuild started" -.It "mly%d: physical device %d:%d rebuild completed" -.It "mly%d: physical device %d:%d rebuild cancelled" -.It "mly%d: physical device %d:%d rebuild failed for unknown reasons" -.It "mly%d: physical device %d:%d rebuild failed due to new physical device" -.It "mly%d: physical device %d:%d rebuild failed due to logical drive failure" -.It "mly%d: physical device %d:%d found" -.It "mly%d: physical device %d:%d gone" -.It "mly%d: physical device %d:%d unconfigured" -.It "mly%d: physical device %d:%d expand capacity started" -.It "mly%d: physical device %d:%d expand capacity completed" -.It "mly%d: physical device %d:%d expand capacity failed" -.It "mly%d: physical device %d:%d parity error" -.It "mly%d: physical device %d:%d soft error" -.It "mly%d: physical device %d:%d miscellaneous error" -.It "mly%d: physical device %d:%d reset" -.It "mly%d: physical device %d:%d active spare found" -.It "mly%d: physical device %d:%d warm spare found" -.It "mly%d: physical device %d:%d initialization started" -.It "mly%d: physical device %d:%d initialization completed" -.It "mly%d: physical device %d:%d initialization failed" -.It "mly%d: physical device %d:%d initialization cancelled" -.It "mly%d: physical device %d:%d write recovery failed" -.It "mly%d: physical device %d:%d scsi bus reset failed" -.It "mly%d: physical device %d:%d double check condition" -.It "mly%d: physical device %d:%d device cannot be accessed" -.It "mly%d: physical device %d:%d gross error on scsi processor" -.It "mly%d: physical device %d:%d bad tag from device" -.It "mly%d: physical device %d:%d command timeout" -.It "mly%d: physical device %d:%d system reset" -.It "mly%d: physical device %d:%d busy status or parity error" -.It "mly%d: physical device %d:%d host set device to failed state" -.It "mly%d: physical device %d:%d selection timeout" -.It "mly%d: physical device %d:%d scsi bus phase error" -.It "mly%d: physical device %d:%d device returned unknown status" -.It "mly%d: physical device %d:%d device not ready" -.It "mly%d: physical device %d:%d device not found at startup" -.It "mly%d: physical device %d:%d COD write operation failed" -.It "mly%d: physical device %d:%d BDT write operation failed" -.It "mly%d: physical device %d:%d missing at startup" -.It "mly%d: physical device %d:%d start rebuild failed due to physical drive too small" -.It "mly%d: physical device %d:%d sense data received" -.It "mly%d: sense key %d asc %02x ascq %02x" -.It "mly%d: info %4D csi %4D" -.It "mly%d: physical device %d:%d offline" -.It "mly%d: sense key %d asc %02x ascq %02x" -.It "mly%d: info %4D csi %4D" -.Pp -The reported event refers to the physical device at the given channel:target -address. -.It "mly%d: logical device %d (%s) consistency check started" -.It "mly%d: logical device %d (%s) consistency check completed" -.It "mly%d: logical device %d (%s) consistency check cancelled" -.It "mly%d: logical device %d (%s) consistency check completed with errors" -.It "mly%d: logical device %d (%s) consistency check failed due to logical drive failure" -.It "mly%d: logical device %d (%s) consistency check failed due to physical device failure" -.It "mly%d: logical device %d (%s) automatic rebuild started" -.It "mly%d: logical device %d (%s) manual rebuild started" -.It "mly%d: logical device %d (%s) rebuild completed" -.It "mly%d: logical device %d (%s) rebuild cancelled" -.It "mly%d: logical device %d (%s) rebuild failed for unknown reasons" -.It "mly%d: logical device %d (%s) rebuild failed due to new physical device" -.It "mly%d: logical device %d (%s) rebuild failed due to logical drive failure" -.It "mly%d: logical device %d (%s) offline" -.It "mly%d: logical device %d (%s) critical" -.It "mly%d: logical device %d (%s) online" -.It "mly%d: logical device %d (%s) initialization started" -.It "mly%d: logical device %d (%s) initialization completed" -.It "mly%d: logical device %d (%s) initialization cancelled" -.It "mly%d: logical device %d (%s) initialization failed" -.It "mly%d: logical device %d (%s) found" -.It "mly%d: logical device %d (%s) gone" -.It "mly%d: logical device %d (%s) expand capacity started" -.It "mly%d: logical device %d (%s) expand capacity completed" -.It "mly%d: logical device %d (%s) expand capacity failed" -.It "mly%d: logical device %d (%s) bad block found" -.It "mly%d: logical device %d (%s) size changed" -.It "mly%d: logical device %d (%s) type changed" -.It "mly%d: logical device %d (%s) bad data block found" -.It "mly%d: logical device %d (%s) read of data block in bdt" -.It "mly%d: logical device %d (%s) write back data for disk block lost" -.Pp -The event report will include the name of the SCSI device which has -attached to the device if possible. -.It "mly%d: enclosure %d fan %d failed" -.It "mly%d: enclosure %d fan %d ok" -.It "mly%d: enclosure %d fan %d not present" -.It "mly%d: enclosure %d power supply %d failed" -.It "mly%d: enclosure %d power supply %d ok" -.It "mly%d: enclosure %d power supply %d not present" -.It "mly%d: enclosure %d temperature sensor %d failed" -.It "mly%d: enclosure %d temperature sensor %d critical" -.It "mly%d: enclosure %d temperature sensor %d ok" -.It "mly%d: enclosure %d temperature sensor %d not present" -.It "mly%d: enclosure %d unit %d access critical" -.It "mly%d: enclosure %d unit %d access ok" -.It "mly%d: enclosure %d unit %d access offline" -.Pp -These events refer to external enclosures by number. -The driver does not attempt to name the enclosures. -.It "mly%d: controller cache write back error" -.It "mly%d: controller battery backup unit found" -.It "mly%d: controller battery backup unit charge level low" -.It "mly%d: controller battery backup unit charge level ok" -.It "mly%d: controller installation aborted" -.It "mly%d: controller mirror race recovery in progress" -.It "mly%d: controller mirror race on critical drive" -.It "mly%d: controller memory soft ecc error" -.It "mly%d: controller memory hard ecc error" -.It "mly%d: controller battery backup unit failed" -.Pp -These events report controller status changes. -.El -.Sh AUTHORS -.An -nosplit -The -.Nm -driver was written by -.An Michael Smith Aq Mt msmith@FreeBSD.org . -.Pp -This manual page was written by -.An Michael Smith Aq Mt msmith@FreeBSD.org . -.Sh BUGS -The driver does not yet provide an external management interface. -.Pp -Enclosures are not named or otherwise identified in event messages. diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -185,7 +185,6 @@ device ciss # Compaq Smart RAID 5* device iir # Intel Integrated RAID device ips # IBM (Adaptec) ServeRAID -device mly # Mylex AcceleRAID/eXtremeRAID device twa # 3ware 9000 series PATA/SATA RAID device smartpqi # Microsemi smartpqi driver device tws # LSI 3ware 9750 SATA+SAS 6Gb/s RAID controller diff --git a/sys/conf/NOTES b/sys/conf/NOTES --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1644,13 +1644,6 @@ # device iir -# -# Mylex AcceleRAID and eXtremeRAID controllers with v6 and later -# firmware. These controllers have a SCSI-like interface, and require -# the CAM infrastructure. -# -device mly - # # Compaq Smart RAID, Mylex DAC960 and AMI MegaRAID controllers. Only # one entry is needed; the code will find and configure all supported diff --git a/sys/conf/files b/sys/conf/files --- a/sys/conf/files +++ b/sys/conf/files @@ -2459,7 +2459,6 @@ dev/mlx/mlx.c optional mlx dev/mlx/mlx_disk.c optional mlx dev/mlx/mlx_pci.c optional mlx pci -dev/mly/mly.c optional mly dev/mmc/mmc_subr.c optional mmc | mmcsd !mmccam dev/mmc/mmc.c optional mmc !mmccam dev/mmc/mmcbr_if.m standard diff --git a/sys/dev/mly/mly.c b/sys/dev/mly/mly.c deleted file mode 100644 --- a/sys/dev/mly/mly.c +++ /dev/null @@ -1,3003 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2000, 2001 Michael Smith - * Copyright (c) 2000 BSDi - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -static int mly_probe(device_t dev); -static int mly_attach(device_t dev); -static int mly_pci_attach(struct mly_softc *sc); -static int mly_detach(device_t dev); -static int mly_shutdown(device_t dev); -static void mly_intr(void *arg); - -static int mly_sg_map(struct mly_softc *sc); -static void mly_sg_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error); -static int mly_mmbox_map(struct mly_softc *sc); -static void mly_mmbox_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error); -static void mly_free(struct mly_softc *sc); - -static int mly_get_controllerinfo(struct mly_softc *sc); -static void mly_scan_devices(struct mly_softc *sc); -static void mly_rescan_btl(struct mly_softc *sc, int bus, int target); -static void mly_complete_rescan(struct mly_command *mc); -static int mly_get_eventstatus(struct mly_softc *sc); -static int mly_enable_mmbox(struct mly_softc *sc); -static int mly_flush(struct mly_softc *sc); -static int mly_ioctl(struct mly_softc *sc, struct mly_command_ioctl *ioctl, void **data, - size_t datasize, u_int8_t *status, void *sense_buffer, size_t *sense_length); -static void mly_check_event(struct mly_softc *sc); -static void mly_fetch_event(struct mly_softc *sc); -static void mly_complete_event(struct mly_command *mc); -static void mly_process_event(struct mly_softc *sc, struct mly_event *me); -static void mly_periodic(void *data); - -static int mly_immediate_command(struct mly_command *mc); -static int mly_start(struct mly_command *mc); -static void mly_done(struct mly_softc *sc); -static void mly_complete(struct mly_softc *sc); -static void mly_complete_handler(void *context, int pending); - -static int mly_alloc_command(struct mly_softc *sc, struct mly_command **mcp); -static void mly_release_command(struct mly_command *mc); -static void mly_alloc_commands_map(void *arg, bus_dma_segment_t *segs, int nseg, int error); -static int mly_alloc_commands(struct mly_softc *sc); -static void mly_release_commands(struct mly_softc *sc); -static void mly_map_command(struct mly_command *mc); -static void mly_unmap_command(struct mly_command *mc); - -static int mly_cam_attach(struct mly_softc *sc); -static void mly_cam_detach(struct mly_softc *sc); -static void mly_cam_rescan_btl(struct mly_softc *sc, int bus, int target); -static void mly_cam_action(struct cam_sim *sim, union ccb *ccb); -static int mly_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio); -static void mly_cam_poll(struct cam_sim *sim); -static void mly_cam_complete(struct mly_command *mc); -static struct cam_periph *mly_find_periph(struct mly_softc *sc, int bus, int target); -static int mly_name_device(struct mly_softc *sc, int bus, int target); - -static int mly_fwhandshake(struct mly_softc *sc); - -static void mly_describe_controller(struct mly_softc *sc); -#ifdef MLY_DEBUG -static void mly_printstate(struct mly_softc *sc); -static void mly_print_command(struct mly_command *mc); -static void mly_print_packet(struct mly_command *mc); -static void mly_panic(struct mly_softc *sc, char *reason); -static void mly_timeout(void *arg); -#endif -void mly_print_controller(int controller); - -static d_open_t mly_user_open; -static d_close_t mly_user_close; -static d_ioctl_t mly_user_ioctl; -static int mly_user_command(struct mly_softc *sc, struct mly_user_command *uc); -static int mly_user_health(struct mly_softc *sc, struct mly_user_health *uh); - -#define MLY_CMD_TIMEOUT 20 - -static device_method_t mly_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, mly_probe), - DEVMETHOD(device_attach, mly_attach), - DEVMETHOD(device_detach, mly_detach), - DEVMETHOD(device_shutdown, mly_shutdown), - { 0, 0 } -}; - -static driver_t mly_pci_driver = { - "mly", - mly_methods, - sizeof(struct mly_softc) -}; - -static devclass_t mly_devclass; -DRIVER_MODULE(mly, pci, mly_pci_driver, mly_devclass, 0, 0); -MODULE_DEPEND(mly, pci, 1, 1, 1); -MODULE_DEPEND(mly, cam, 1, 1, 1); - -static struct cdevsw mly_cdevsw = { - .d_version = D_VERSION, - .d_open = mly_user_open, - .d_close = mly_user_close, - .d_ioctl = mly_user_ioctl, - .d_name = "mly", -}; - -/******************************************************************************** - ******************************************************************************** - Device Interface - ******************************************************************************** - ********************************************************************************/ - -static struct mly_ident -{ - u_int16_t vendor; - u_int16_t device; - u_int16_t subvendor; - u_int16_t subdevice; - int hwif; - char *desc; -} mly_identifiers[] = { - {0x1069, 0xba56, 0x1069, 0x0040, MLY_HWIF_STRONGARM, "Mylex eXtremeRAID 2000"}, - {0x1069, 0xba56, 0x1069, 0x0030, MLY_HWIF_STRONGARM, "Mylex eXtremeRAID 3000"}, - {0x1069, 0x0050, 0x1069, 0x0050, MLY_HWIF_I960RX, "Mylex AcceleRAID 352"}, - {0x1069, 0x0050, 0x1069, 0x0052, MLY_HWIF_I960RX, "Mylex AcceleRAID 170"}, - {0x1069, 0x0050, 0x1069, 0x0054, MLY_HWIF_I960RX, "Mylex AcceleRAID 160"}, - {0, 0, 0, 0, 0, 0} -}; - -/******************************************************************************** - * Compare the provided PCI device with the list we support. - */ -static int -mly_probe(device_t dev) -{ - struct mly_ident *m; - - debug_called(1); - - for (m = mly_identifiers; m->vendor != 0; m++) { - if ((m->vendor == pci_get_vendor(dev)) && - (m->device == pci_get_device(dev)) && - ((m->subvendor == 0) || ((m->subvendor == pci_get_subvendor(dev)) && - (m->subdevice == pci_get_subdevice(dev))))) { - - device_set_desc(dev, m->desc); - return(BUS_PROBE_DEFAULT); /* allow room to be overridden */ - } - } - return(ENXIO); -} - -/******************************************************************************** - * Initialise the controller and softc - */ -static int -mly_attach(device_t dev) -{ - struct mly_softc *sc = device_get_softc(dev); - int error; - - debug_called(1); - - sc->mly_dev = dev; - mtx_init(&sc->mly_lock, "mly", NULL, MTX_DEF); - callout_init_mtx(&sc->mly_periodic, &sc->mly_lock, 0); - -#ifdef MLY_DEBUG - callout_init_mtx(&sc->mly_timeout, &sc->mly_lock, 0); - if (device_get_unit(sc->mly_dev) == 0) - mly_softc0 = sc; -#endif - - /* - * Do PCI-specific initialisation. - */ - if ((error = mly_pci_attach(sc)) != 0) - goto out; - - /* - * Initialise per-controller queues. - */ - mly_initq_free(sc); - mly_initq_busy(sc); - mly_initq_complete(sc); - - /* - * Initialise command-completion task. - */ - TASK_INIT(&sc->mly_task_complete, 0, mly_complete_handler, sc); - - /* disable interrupts before we start talking to the controller */ - MLY_MASK_INTERRUPTS(sc); - - /* - * Wait for the controller to come ready, handshake with the firmware if required. - * This is typically only necessary on platforms where the controller BIOS does not - * run. - */ - if ((error = mly_fwhandshake(sc))) - goto out; - - /* - * Allocate initial command buffers. - */ - if ((error = mly_alloc_commands(sc))) - goto out; - - /* - * Obtain controller feature information - */ - MLY_LOCK(sc); - error = mly_get_controllerinfo(sc); - MLY_UNLOCK(sc); - if (error) - goto out; - - /* - * Reallocate command buffers now we know how many we want. - */ - mly_release_commands(sc); - if ((error = mly_alloc_commands(sc))) - goto out; - - /* - * Get the current event counter for health purposes, populate the initial - * health status buffer. - */ - MLY_LOCK(sc); - error = mly_get_eventstatus(sc); - - /* - * Enable memory-mailbox mode. - */ - if (error == 0) - error = mly_enable_mmbox(sc); - MLY_UNLOCK(sc); - if (error) - goto out; - - /* - * Attach to CAM. - */ - if ((error = mly_cam_attach(sc))) - goto out; - - /* - * Print a little information about the controller - */ - mly_describe_controller(sc); - - /* - * Mark all attached devices for rescan. - */ - MLY_LOCK(sc); - mly_scan_devices(sc); - - /* - * Instigate the first status poll immediately. Rescan completions won't - * happen until interrupts are enabled, which should still be before - * the SCSI subsystem gets to us, courtesy of the "SCSI settling delay". - */ - mly_periodic((void *)sc); - MLY_UNLOCK(sc); - - /* - * Create the control device. - */ - sc->mly_dev_t = make_dev(&mly_cdevsw, 0, UID_ROOT, GID_OPERATOR, - S_IRUSR | S_IWUSR, "mly%d", device_get_unit(sc->mly_dev)); - sc->mly_dev_t->si_drv1 = sc; - - /* enable interrupts now */ - MLY_UNMASK_INTERRUPTS(sc); - -#ifdef MLY_DEBUG - callout_reset(&sc->mly_timeout, MLY_CMD_TIMEOUT * hz, mly_timeout, sc); -#endif - - out: - if (error != 0) - mly_free(sc); - else - gone_in_dev(dev, 13, "mly(4) removed"); - return(error); -} - -/******************************************************************************** - * Perform PCI-specific initialisation. - */ -static int -mly_pci_attach(struct mly_softc *sc) -{ - int i, error; - - debug_called(1); - - /* assume failure is 'not configured' */ - error = ENXIO; - - /* - * Verify that the adapter is correctly set up in PCI space. - */ - pci_enable_busmaster(sc->mly_dev); - - /* - * Allocate the PCI register window. - */ - sc->mly_regs_rid = PCIR_BAR(0); /* first base address register */ - if ((sc->mly_regs_resource = bus_alloc_resource_any(sc->mly_dev, - SYS_RES_MEMORY, &sc->mly_regs_rid, RF_ACTIVE)) == NULL) { - mly_printf(sc, "can't allocate register window\n"); - goto fail; - } - - /* - * Allocate and connect our interrupt. - */ - sc->mly_irq_rid = 0; - if ((sc->mly_irq = bus_alloc_resource_any(sc->mly_dev, SYS_RES_IRQ, - &sc->mly_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { - mly_printf(sc, "can't allocate interrupt\n"); - goto fail; - } - if (bus_setup_intr(sc->mly_dev, sc->mly_irq, INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE, NULL, mly_intr, sc, &sc->mly_intr)) { - mly_printf(sc, "can't set up interrupt\n"); - goto fail; - } - - /* assume failure is 'out of memory' */ - error = ENOMEM; - - /* - * Allocate the parent bus DMA tag appropriate for our PCI interface. - * - * Note that all of these controllers are 64-bit capable. - */ - if (bus_dma_tag_create(bus_get_dma_tag(sc->mly_dev),/* PCI parent */ - 1, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ - BUS_SPACE_UNRESTRICTED, /* nsegments */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ - NULL, /* lockfunc */ - NULL, /* lockarg */ - &sc->mly_parent_dmat)) { - mly_printf(sc, "can't allocate parent DMA tag\n"); - goto fail; - } - - /* - * Create DMA tag for mapping buffers into controller-addressable space. - */ - if (bus_dma_tag_create(sc->mly_parent_dmat, /* parent */ - 1, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - DFLTPHYS, /* maxsize */ - MLY_MAX_SGENTRIES, /* nsegments */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ - 0, /* flags */ - busdma_lock_mutex, /* lockfunc */ - &sc->mly_lock, /* lockarg */ - &sc->mly_buffer_dmat)) { - mly_printf(sc, "can't allocate buffer DMA tag\n"); - goto fail; - } - - /* - * Initialise the DMA tag for command packets. - */ - if (bus_dma_tag_create(sc->mly_parent_dmat, /* parent */ - 1, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - sizeof(union mly_command_packet) * MLY_MAX_COMMANDS, 1, /* maxsize, nsegments */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->mly_packet_dmat)) { - mly_printf(sc, "can't allocate command packet DMA tag\n"); - goto fail; - } - - /* - * Detect the hardware interface version - */ - for (i = 0; mly_identifiers[i].vendor != 0; i++) { - if ((mly_identifiers[i].vendor == pci_get_vendor(sc->mly_dev)) && - (mly_identifiers[i].device == pci_get_device(sc->mly_dev))) { - sc->mly_hwif = mly_identifiers[i].hwif; - switch(sc->mly_hwif) { - case MLY_HWIF_I960RX: - debug(1, "set hardware up for i960RX"); - sc->mly_doorbell_true = 0x00; - sc->mly_command_mailbox = MLY_I960RX_COMMAND_MAILBOX; - sc->mly_status_mailbox = MLY_I960RX_STATUS_MAILBOX; - sc->mly_idbr = MLY_I960RX_IDBR; - sc->mly_odbr = MLY_I960RX_ODBR; - sc->mly_error_status = MLY_I960RX_ERROR_STATUS; - sc->mly_interrupt_status = MLY_I960RX_INTERRUPT_STATUS; - sc->mly_interrupt_mask = MLY_I960RX_INTERRUPT_MASK; - break; - case MLY_HWIF_STRONGARM: - debug(1, "set hardware up for StrongARM"); - sc->mly_doorbell_true = 0xff; /* doorbell 'true' is 0 */ - sc->mly_command_mailbox = MLY_STRONGARM_COMMAND_MAILBOX; - sc->mly_status_mailbox = MLY_STRONGARM_STATUS_MAILBOX; - sc->mly_idbr = MLY_STRONGARM_IDBR; - sc->mly_odbr = MLY_STRONGARM_ODBR; - sc->mly_error_status = MLY_STRONGARM_ERROR_STATUS; - sc->mly_interrupt_status = MLY_STRONGARM_INTERRUPT_STATUS; - sc->mly_interrupt_mask = MLY_STRONGARM_INTERRUPT_MASK; - break; - } - break; - } - } - - /* - * Create the scatter/gather mappings. - */ - if ((error = mly_sg_map(sc))) - goto fail; - - /* - * Allocate and map the memory mailbox - */ - if ((error = mly_mmbox_map(sc))) - goto fail; - - error = 0; - -fail: - return(error); -} - -/******************************************************************************** - * Shut the controller down and detach all our resources. - */ -static int -mly_detach(device_t dev) -{ - int error; - - if ((error = mly_shutdown(dev)) != 0) - return(error); - - mly_free(device_get_softc(dev)); - return(0); -} - -/******************************************************************************** - * Bring the controller to a state where it can be safely left alone. - * - * Note that it should not be necessary to wait for any outstanding commands, - * as they should be completed prior to calling here. - * - * XXX this applies for I/O, but not status polls; we should beware of - * the case where a status command is running while we detach. - */ -static int -mly_shutdown(device_t dev) -{ - struct mly_softc *sc = device_get_softc(dev); - - debug_called(1); - - MLY_LOCK(sc); - if (sc->mly_state & MLY_STATE_OPEN) { - MLY_UNLOCK(sc); - return(EBUSY); - } - - /* kill the periodic event */ - callout_stop(&sc->mly_periodic); -#ifdef MLY_DEBUG - callout_stop(&sc->mly_timeout); -#endif - - /* flush controller */ - mly_printf(sc, "flushing cache..."); - printf("%s\n", mly_flush(sc) ? "failed" : "done"); - - MLY_MASK_INTERRUPTS(sc); - MLY_UNLOCK(sc); - - return(0); -} - -/******************************************************************************* - * Take an interrupt, or be poked by other code to look for interrupt-worthy - * status. - */ -static void -mly_intr(void *arg) -{ - struct mly_softc *sc = (struct mly_softc *)arg; - - debug_called(2); - - MLY_LOCK(sc); - mly_done(sc); - MLY_UNLOCK(sc); -}; - -/******************************************************************************** - ******************************************************************************** - Bus-dependant Resource Management - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - * Allocate memory for the scatter/gather tables - */ -static int -mly_sg_map(struct mly_softc *sc) -{ - size_t segsize; - - debug_called(1); - - /* - * Create a single tag describing a region large enough to hold all of - * the s/g lists we will need. - */ - segsize = sizeof(struct mly_sg_entry) * MLY_MAX_COMMANDS *MLY_MAX_SGENTRIES; - if (bus_dma_tag_create(sc->mly_parent_dmat, /* parent */ - 1, 0, /* alignment,boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - segsize, 1, /* maxsize, nsegments */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->mly_sg_dmat)) { - mly_printf(sc, "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. - */ - if (bus_dmamem_alloc(sc->mly_sg_dmat, (void **)&sc->mly_sg_table, - BUS_DMA_NOWAIT, &sc->mly_sg_dmamap)) { - mly_printf(sc, "can't allocate s/g table\n"); - return(ENOMEM); - } - if (bus_dmamap_load(sc->mly_sg_dmat, sc->mly_sg_dmamap, sc->mly_sg_table, - segsize, mly_sg_map_helper, sc, BUS_DMA_NOWAIT) != 0) - return (ENOMEM); - return(0); -} - -/******************************************************************************** - * Save the physical address of the base of the s/g table. - */ -static void -mly_sg_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - struct mly_softc *sc = (struct mly_softc *)arg; - - debug_called(1); - - /* save base of s/g table's address in bus space */ - sc->mly_sg_busaddr = segs->ds_addr; -} - -/******************************************************************************** - * Allocate memory for the memory-mailbox interface - */ -static int -mly_mmbox_map(struct mly_softc *sc) -{ - - /* - * Create a DMA tag for a single contiguous region large enough for the - * memory mailbox structure. - */ - if (bus_dma_tag_create(sc->mly_parent_dmat, /* parent */ - 1, 0, /* alignment,boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - sizeof(struct mly_mmbox), 1, /* maxsize, nsegments */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->mly_mmbox_dmat)) { - mly_printf(sc, "can't allocate memory mailbox DMA tag\n"); - return(ENOMEM); - } - - /* - * Allocate the buffer - */ - if (bus_dmamem_alloc(sc->mly_mmbox_dmat, (void **)&sc->mly_mmbox, BUS_DMA_NOWAIT, &sc->mly_mmbox_dmamap)) { - mly_printf(sc, "can't allocate memory mailbox\n"); - return(ENOMEM); - } - if (bus_dmamap_load(sc->mly_mmbox_dmat, sc->mly_mmbox_dmamap, sc->mly_mmbox, - sizeof(struct mly_mmbox), mly_mmbox_map_helper, sc, - BUS_DMA_NOWAIT) != 0) - return (ENOMEM); - bzero(sc->mly_mmbox, sizeof(*sc->mly_mmbox)); - return(0); - -} - -/******************************************************************************** - * Save the physical address of the memory mailbox - */ -static void -mly_mmbox_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - struct mly_softc *sc = (struct mly_softc *)arg; - - debug_called(1); - - sc->mly_mmbox_busaddr = segs->ds_addr; -} - -/******************************************************************************** - * Free all of the resources associated with (sc) - * - * Should not be called if the controller is active. - */ -static void -mly_free(struct mly_softc *sc) -{ - - debug_called(1); - - /* Remove the management device */ - destroy_dev(sc->mly_dev_t); - - if (sc->mly_intr) - bus_teardown_intr(sc->mly_dev, sc->mly_irq, sc->mly_intr); - callout_drain(&sc->mly_periodic); -#ifdef MLY_DEBUG - callout_drain(&sc->mly_timeout); -#endif - - /* detach from CAM */ - mly_cam_detach(sc); - - /* release command memory */ - mly_release_commands(sc); - - /* throw away the controllerinfo structure */ - if (sc->mly_controllerinfo != NULL) - free(sc->mly_controllerinfo, M_DEVBUF); - - /* throw away the controllerparam structure */ - if (sc->mly_controllerparam != NULL) - free(sc->mly_controllerparam, M_DEVBUF); - - /* destroy data-transfer DMA tag */ - if (sc->mly_buffer_dmat) - bus_dma_tag_destroy(sc->mly_buffer_dmat); - - /* free and destroy DMA memory and tag for s/g lists */ - if (sc->mly_sg_table) { - bus_dmamap_unload(sc->mly_sg_dmat, sc->mly_sg_dmamap); - bus_dmamem_free(sc->mly_sg_dmat, sc->mly_sg_table, sc->mly_sg_dmamap); - } - if (sc->mly_sg_dmat) - bus_dma_tag_destroy(sc->mly_sg_dmat); - - /* free and destroy DMA memory and tag for memory mailbox */ - if (sc->mly_mmbox) { - bus_dmamap_unload(sc->mly_mmbox_dmat, sc->mly_mmbox_dmamap); - bus_dmamem_free(sc->mly_mmbox_dmat, sc->mly_mmbox, sc->mly_mmbox_dmamap); - } - if (sc->mly_mmbox_dmat) - bus_dma_tag_destroy(sc->mly_mmbox_dmat); - - /* disconnect the interrupt handler */ - if (sc->mly_irq != NULL) - bus_release_resource(sc->mly_dev, SYS_RES_IRQ, sc->mly_irq_rid, sc->mly_irq); - - /* destroy the parent DMA tag */ - if (sc->mly_parent_dmat) - bus_dma_tag_destroy(sc->mly_parent_dmat); - - /* release the register window mapping */ - if (sc->mly_regs_resource != NULL) - bus_release_resource(sc->mly_dev, SYS_RES_MEMORY, sc->mly_regs_rid, sc->mly_regs_resource); - - mtx_destroy(&sc->mly_lock); -} - -/******************************************************************************** - ******************************************************************************** - Command Wrappers - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - * Fill in the mly_controllerinfo and mly_controllerparam fields in the softc. - */ -static int -mly_get_controllerinfo(struct mly_softc *sc) -{ - struct mly_command_ioctl mci; - u_int8_t status; - int error; - - debug_called(1); - - if (sc->mly_controllerinfo != NULL) - free(sc->mly_controllerinfo, M_DEVBUF); - - /* build the getcontrollerinfo ioctl and send it */ - bzero(&mci, sizeof(mci)); - sc->mly_controllerinfo = NULL; - mci.sub_ioctl = MDACIOCTL_GETCONTROLLERINFO; - if ((error = mly_ioctl(sc, &mci, (void **)&sc->mly_controllerinfo, sizeof(*sc->mly_controllerinfo), - &status, NULL, NULL))) - return(error); - if (status != 0) - return(EIO); - - if (sc->mly_controllerparam != NULL) - free(sc->mly_controllerparam, M_DEVBUF); - - /* build the getcontrollerparameter ioctl and send it */ - bzero(&mci, sizeof(mci)); - sc->mly_controllerparam = NULL; - mci.sub_ioctl = MDACIOCTL_GETCONTROLLERPARAMETER; - if ((error = mly_ioctl(sc, &mci, (void **)&sc->mly_controllerparam, sizeof(*sc->mly_controllerparam), - &status, NULL, NULL))) - return(error); - if (status != 0) - return(EIO); - - return(0); -} - -/******************************************************************************** - * Schedule all possible devices for a rescan. - * - */ -static void -mly_scan_devices(struct mly_softc *sc) -{ - int bus, target; - - debug_called(1); - - /* - * Clear any previous BTL information. - */ - bzero(&sc->mly_btl, sizeof(sc->mly_btl)); - - /* - * Mark all devices as requiring a rescan, and let the next - * periodic scan collect them. - */ - for (bus = 0; bus < sc->mly_cam_channels; bus++) - if (MLY_BUS_IS_VALID(sc, bus)) - for (target = 0; target < MLY_MAX_TARGETS; target++) - sc->mly_btl[bus][target].mb_flags = MLY_BTL_RESCAN; - -} - -/******************************************************************************** - * Rescan a device, possibly as a consequence of getting an event which suggests - * that it may have changed. - * - * If we suffer resource starvation, we can abandon the rescan as we'll be - * retried. - */ -static void -mly_rescan_btl(struct mly_softc *sc, int bus, int target) -{ - struct mly_command *mc; - struct mly_command_ioctl *mci; - - debug_called(1); - - /* check that this bus is valid */ - if (!MLY_BUS_IS_VALID(sc, bus)) - return; - - /* get a command */ - if (mly_alloc_command(sc, &mc)) - return; - - /* set up the data buffer */ - if ((mc->mc_data = malloc(sizeof(union mly_devinfo), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { - mly_release_command(mc); - return; - } - mc->mc_flags |= MLY_CMD_DATAIN; - mc->mc_complete = mly_complete_rescan; - - /* - * Build the ioctl. - */ - mci = (struct mly_command_ioctl *)&mc->mc_packet->ioctl; - mci->opcode = MDACMD_IOCTL; - mci->addr.phys.controller = 0; - mci->timeout.value = 30; - mci->timeout.scale = MLY_TIMEOUT_SECONDS; - if (MLY_BUS_IS_VIRTUAL(sc, bus)) { - mc->mc_length = mci->data_size = sizeof(struct mly_ioctl_getlogdevinfovalid); - mci->sub_ioctl = MDACIOCTL_GETLOGDEVINFOVALID; - mci->addr.log.logdev = MLY_LOGDEV_ID(sc, bus, target); - debug(1, "logical device %d", mci->addr.log.logdev); - } else { - mc->mc_length = mci->data_size = sizeof(struct mly_ioctl_getphysdevinfovalid); - mci->sub_ioctl = MDACIOCTL_GETPHYSDEVINFOVALID; - mci->addr.phys.lun = 0; - mci->addr.phys.target = target; - mci->addr.phys.channel = bus; - debug(1, "physical device %d:%d", mci->addr.phys.channel, mci->addr.phys.target); - } - - /* - * Dispatch the command. If we successfully send the command, clear the rescan - * bit. - */ - if (mly_start(mc) != 0) { - mly_release_command(mc); - } else { - sc->mly_btl[bus][target].mb_flags &= ~MLY_BTL_RESCAN; /* success */ - } -} - -/******************************************************************************** - * Handle the completion of a rescan operation - */ -static void -mly_complete_rescan(struct mly_command *mc) -{ - struct mly_softc *sc = mc->mc_sc; - struct mly_ioctl_getlogdevinfovalid *ldi; - struct mly_ioctl_getphysdevinfovalid *pdi; - struct mly_command_ioctl *mci; - struct mly_btl btl, *btlp; - int bus, target, rescan; - - debug_called(1); - - /* - * Recover the bus and target from the command. We need these even in - * the case where we don't have a useful response. - */ - mci = (struct mly_command_ioctl *)&mc->mc_packet->ioctl; - if (mci->sub_ioctl == MDACIOCTL_GETLOGDEVINFOVALID) { - bus = MLY_LOGDEV_BUS(sc, mci->addr.log.logdev); - target = MLY_LOGDEV_TARGET(sc, mci->addr.log.logdev); - } else { - bus = mci->addr.phys.channel; - target = mci->addr.phys.target; - } - /* XXX validate bus/target? */ - - /* the default result is 'no device' */ - bzero(&btl, sizeof(btl)); - - /* if the rescan completed OK, we have possibly-new BTL data */ - if (mc->mc_status == 0) { - if (mc->mc_length == sizeof(*ldi)) { - ldi = (struct mly_ioctl_getlogdevinfovalid *)mc->mc_data; - if ((MLY_LOGDEV_BUS(sc, ldi->logical_device_number) != bus) || - (MLY_LOGDEV_TARGET(sc, ldi->logical_device_number) != target)) { - mly_printf(sc, "WARNING: BTL rescan for %d:%d returned data for %d:%d instead\n", - bus, target, MLY_LOGDEV_BUS(sc, ldi->logical_device_number), - MLY_LOGDEV_TARGET(sc, ldi->logical_device_number)); - /* XXX what can we do about this? */ - } - btl.mb_flags = MLY_BTL_LOGICAL; - btl.mb_type = ldi->raid_level; - btl.mb_state = ldi->state; - debug(1, "BTL rescan for %d returns %s, %s", ldi->logical_device_number, - mly_describe_code(mly_table_device_type, ldi->raid_level), - mly_describe_code(mly_table_device_state, ldi->state)); - } else if (mc->mc_length == sizeof(*pdi)) { - pdi = (struct mly_ioctl_getphysdevinfovalid *)mc->mc_data; - if ((pdi->channel != bus) || (pdi->target != target)) { - mly_printf(sc, "WARNING: BTL rescan for %d:%d returned data for %d:%d instead\n", - bus, target, pdi->channel, pdi->target); - /* XXX what can we do about this? */ - } - btl.mb_flags = MLY_BTL_PHYSICAL; - btl.mb_type = MLY_DEVICE_TYPE_PHYSICAL; - btl.mb_state = pdi->state; - btl.mb_speed = pdi->speed; - btl.mb_width = pdi->width; - if (pdi->state != MLY_DEVICE_STATE_UNCONFIGURED) - sc->mly_btl[bus][target].mb_flags |= MLY_BTL_PROTECTED; - debug(1, "BTL rescan for %d:%d returns %s", bus, target, - mly_describe_code(mly_table_device_state, pdi->state)); - } else { - mly_printf(sc, "BTL rescan result invalid\n"); - } - } - - free(mc->mc_data, M_DEVBUF); - mly_release_command(mc); - - /* - * Decide whether we need to rescan the device. - */ - rescan = 0; - - /* device type changes (usually between 'nothing' and 'something') */ - btlp = &sc->mly_btl[bus][target]; - if (btl.mb_flags != btlp->mb_flags) { - debug(1, "flags changed, rescanning"); - rescan = 1; - } - - /* XXX other reasons? */ - - /* - * Update BTL information. - */ - *btlp = btl; - - /* - * Perform CAM rescan if required. - */ - if (rescan) - mly_cam_rescan_btl(sc, bus, target); -} - -/******************************************************************************** - * Get the current health status and set the 'next event' counter to suit. - */ -static int -mly_get_eventstatus(struct mly_softc *sc) -{ - struct mly_command_ioctl mci; - struct mly_health_status *mh; - u_int8_t status; - int error; - - /* build the gethealthstatus ioctl and send it */ - bzero(&mci, sizeof(mci)); - mh = NULL; - mci.sub_ioctl = MDACIOCTL_GETHEALTHSTATUS; - - if ((error = mly_ioctl(sc, &mci, (void **)&mh, sizeof(*mh), &status, NULL, NULL))) - return(error); - if (status != 0) - return(EIO); - - /* get the event counter */ - sc->mly_event_change = mh->change_counter; - sc->mly_event_waiting = mh->next_event; - sc->mly_event_counter = mh->next_event; - - /* save the health status into the memory mailbox */ - bcopy(mh, &sc->mly_mmbox->mmm_health.status, sizeof(*mh)); - - debug(1, "initial change counter %d, event counter %d", mh->change_counter, mh->next_event); - - free(mh, M_DEVBUF); - return(0); -} - -/******************************************************************************** - * Enable the memory mailbox mode. - */ -static int -mly_enable_mmbox(struct mly_softc *sc) -{ - struct mly_command_ioctl mci; - u_int8_t *sp, status; - int error; - - debug_called(1); - - /* build the ioctl and send it */ - bzero(&mci, sizeof(mci)); - mci.sub_ioctl = MDACIOCTL_SETMEMORYMAILBOX; - /* set buffer addresses */ - mci.param.setmemorymailbox.command_mailbox_physaddr = - sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_command); - mci.param.setmemorymailbox.status_mailbox_physaddr = - sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_status); - mci.param.setmemorymailbox.health_buffer_physaddr = - sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_health); - - /* set buffer sizes - abuse of data_size field is revolting */ - sp = (u_int8_t *)&mci.data_size; - sp[0] = ((sizeof(union mly_command_packet) * MLY_MMBOX_COMMANDS) / 1024); - sp[1] = (sizeof(union mly_status_packet) * MLY_MMBOX_STATUS) / 1024; - mci.param.setmemorymailbox.health_buffer_size = sizeof(union mly_health_region) / 1024; - - debug(1, "memory mailbox at %p (0x%llx/%d 0x%llx/%d 0x%llx/%d", sc->mly_mmbox, - mci.param.setmemorymailbox.command_mailbox_physaddr, sp[0], - mci.param.setmemorymailbox.status_mailbox_physaddr, sp[1], - mci.param.setmemorymailbox.health_buffer_physaddr, - mci.param.setmemorymailbox.health_buffer_size); - - if ((error = mly_ioctl(sc, &mci, NULL, 0, &status, NULL, NULL))) - return(error); - if (status != 0) - return(EIO); - sc->mly_state |= MLY_STATE_MMBOX_ACTIVE; - debug(1, "memory mailbox active"); - return(0); -} - -/******************************************************************************** - * Flush all pending I/O from the controller. - */ -static int -mly_flush(struct mly_softc *sc) -{ - struct mly_command_ioctl mci; - u_int8_t status; - int error; - - debug_called(1); - - /* build the ioctl */ - bzero(&mci, sizeof(mci)); - mci.sub_ioctl = MDACIOCTL_FLUSHDEVICEDATA; - mci.param.deviceoperation.operation_device = MLY_OPDEVICE_PHYSICAL_CONTROLLER; - - /* pass it off to the controller */ - if ((error = mly_ioctl(sc, &mci, NULL, 0, &status, NULL, NULL))) - return(error); - - return((status == 0) ? 0 : EIO); -} - -/******************************************************************************** - * Perform an ioctl command. - * - * If (data) is not NULL, the command requires data transfer. If (*data) is NULL - * the command requires data transfer from the controller, and we will allocate - * a buffer for it. If (*data) is not NULL, the command requires data transfer - * to the controller. - * - * XXX passing in the whole ioctl structure is ugly. Better ideas? - * - * XXX we don't even try to handle the case where datasize > 4k. We should. - */ -static int -mly_ioctl(struct mly_softc *sc, struct mly_command_ioctl *ioctl, void **data, size_t datasize, - u_int8_t *status, void *sense_buffer, size_t *sense_length) -{ - struct mly_command *mc; - struct mly_command_ioctl *mci; - int error; - - debug_called(1); - MLY_ASSERT_LOCKED(sc); - - mc = NULL; - if (mly_alloc_command(sc, &mc)) { - error = ENOMEM; - goto out; - } - - /* copy the ioctl structure, but save some important fields and then fixup */ - mci = &mc->mc_packet->ioctl; - ioctl->sense_buffer_address = mci->sense_buffer_address; - ioctl->maximum_sense_size = mci->maximum_sense_size; - *mci = *ioctl; - mci->opcode = MDACMD_IOCTL; - mci->timeout.value = 30; - mci->timeout.scale = MLY_TIMEOUT_SECONDS; - - /* handle the data buffer */ - if (data != NULL) { - if (*data == NULL) { - /* allocate data buffer */ - if ((mc->mc_data = malloc(datasize, M_DEVBUF, M_NOWAIT)) == NULL) { - error = ENOMEM; - goto out; - } - mc->mc_flags |= MLY_CMD_DATAIN; - } else { - mc->mc_data = *data; - mc->mc_flags |= MLY_CMD_DATAOUT; - } - mc->mc_length = datasize; - mc->mc_packet->generic.data_size = datasize; - } - - /* run the command */ - if ((error = mly_immediate_command(mc))) - goto out; - - /* clean up and return any data */ - *status = mc->mc_status; - if ((mc->mc_sense > 0) && (sense_buffer != NULL)) { - bcopy(mc->mc_packet, sense_buffer, mc->mc_sense); - *sense_length = mc->mc_sense; - goto out; - } - - /* should we return a data pointer? */ - if ((data != NULL) && (*data == NULL)) - *data = mc->mc_data; - - /* command completed OK */ - error = 0; - -out: - if (mc != NULL) { - /* do we need to free a data buffer we allocated? */ - if (error && (mc->mc_data != NULL) && (*data == NULL)) - free(mc->mc_data, M_DEVBUF); - mly_release_command(mc); - } - return(error); -} - -/******************************************************************************** - * Check for event(s) outstanding in the controller. - */ -static void -mly_check_event(struct mly_softc *sc) -{ - - /* - * The controller may have updated the health status information, - * so check for it here. Note that the counters are all in host memory, - * so this check is very cheap. Also note that we depend on checking on - * completion - */ - if (sc->mly_mmbox->mmm_health.status.change_counter != sc->mly_event_change) { - sc->mly_event_change = sc->mly_mmbox->mmm_health.status.change_counter; - debug(1, "event change %d, event status update, %d -> %d", sc->mly_event_change, - sc->mly_event_waiting, sc->mly_mmbox->mmm_health.status.next_event); - sc->mly_event_waiting = sc->mly_mmbox->mmm_health.status.next_event; - - /* wake up anyone that might be interested in this */ - wakeup(&sc->mly_event_change); - } - if (sc->mly_event_counter != sc->mly_event_waiting) - mly_fetch_event(sc); -} - -/******************************************************************************** - * Fetch one event from the controller. - * - * If we fail due to resource starvation, we'll be retried the next time a - * command completes. - */ -static void -mly_fetch_event(struct mly_softc *sc) -{ - struct mly_command *mc; - struct mly_command_ioctl *mci; - u_int32_t event; - - debug_called(1); - - /* get a command */ - if (mly_alloc_command(sc, &mc)) - return; - - /* set up the data buffer */ - if ((mc->mc_data = malloc(sizeof(struct mly_event), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) { - mly_release_command(mc); - return; - } - mc->mc_length = sizeof(struct mly_event); - mc->mc_flags |= MLY_CMD_DATAIN; - mc->mc_complete = mly_complete_event; - - /* - * Get an event number to fetch. It's possible that we've raced with another - * context for the last event, in which case there will be no more events. - */ - if (sc->mly_event_counter == sc->mly_event_waiting) { - mly_release_command(mc); - return; - } - event = sc->mly_event_counter++; - - /* - * Build the ioctl. - * - * At this point we are committed to sending this request, as it - * will be the only one constructed for this particular event number. - */ - mci = (struct mly_command_ioctl *)&mc->mc_packet->ioctl; - mci->opcode = MDACMD_IOCTL; - mci->data_size = sizeof(struct mly_event); - mci->addr.phys.lun = (event >> 16) & 0xff; - mci->addr.phys.target = (event >> 24) & 0xff; - mci->addr.phys.channel = 0; - mci->addr.phys.controller = 0; - mci->timeout.value = 30; - mci->timeout.scale = MLY_TIMEOUT_SECONDS; - mci->sub_ioctl = MDACIOCTL_GETEVENT; - mci->param.getevent.sequence_number_low = event & 0xffff; - - debug(1, "fetch event %u", event); - - /* - * Submit the command. - * - * Note that failure of mly_start() will result in this event never being - * fetched. - */ - if (mly_start(mc) != 0) { - mly_printf(sc, "couldn't fetch event %u\n", event); - mly_release_command(mc); - } -} - -/******************************************************************************** - * Handle the completion of an event poll. - */ -static void -mly_complete_event(struct mly_command *mc) -{ - struct mly_softc *sc = mc->mc_sc; - struct mly_event *me = (struct mly_event *)mc->mc_data; - - debug_called(1); - - /* - * If the event was successfully fetched, process it. - */ - if (mc->mc_status == SCSI_STATUS_OK) { - mly_process_event(sc, me); - free(me, M_DEVBUF); - } - mly_release_command(mc); - - /* - * Check for another event. - */ - mly_check_event(sc); -} - -/******************************************************************************** - * Process a controller event. - */ -static void -mly_process_event(struct mly_softc *sc, struct mly_event *me) -{ - struct scsi_sense_data_fixed *ssd; - char *fp, *tp; - int bus, target, event, class, action; - - ssd = (struct scsi_sense_data_fixed *)&me->sense[0]; - - /* - * Errors can be reported using vendor-unique sense data. In this case, the - * event code will be 0x1c (Request sense data present), the sense key will - * be 0x09 (vendor specific), the MSB of the ASC will be set, and the - * actual event code will be a 16-bit value comprised of the ASCQ (low byte) - * and low seven bits of the ASC (low seven bits of the high byte). - */ - if ((me->code == 0x1c) && - ((ssd->flags & SSD_KEY) == SSD_KEY_Vendor_Specific) && - (ssd->add_sense_code & 0x80)) { - event = ((int)(ssd->add_sense_code & ~0x80) << 8) + ssd->add_sense_code_qual; - } else { - event = me->code; - } - - /* look up event, get codes */ - fp = mly_describe_code(mly_table_event, event); - - debug(1, "Event %d code 0x%x", me->sequence_number, me->code); - - /* quiet event? */ - class = fp[0]; - if (isupper(class) && bootverbose) - class = tolower(class); - - /* get action code, text string */ - action = fp[1]; - tp = &fp[2]; - - /* - * Print some information about the event. - * - * This code uses a table derived from the corresponding portion of the Linux - * driver, and thus the parser is very similar. - */ - switch(class) { - case 'p': /* error on physical device */ - mly_printf(sc, "physical device %d:%d %s\n", me->channel, me->target, tp); - if (action == 'r') - sc->mly_btl[me->channel][me->target].mb_flags |= MLY_BTL_RESCAN; - break; - case 'l': /* error on logical unit */ - case 'm': /* message about logical unit */ - bus = MLY_LOGDEV_BUS(sc, me->lun); - target = MLY_LOGDEV_TARGET(sc, me->lun); - mly_name_device(sc, bus, target); - mly_printf(sc, "logical device %d (%s) %s\n", me->lun, sc->mly_btl[bus][target].mb_name, tp); - if (action == 'r') - sc->mly_btl[bus][target].mb_flags |= MLY_BTL_RESCAN; - break; - case 's': /* report of sense data */ - if (((ssd->flags & SSD_KEY) == SSD_KEY_NO_SENSE) || - (((ssd->flags & SSD_KEY) == SSD_KEY_NOT_READY) && - (ssd->add_sense_code == 0x04) && - ((ssd->add_sense_code_qual == 0x01) || (ssd->add_sense_code_qual == 0x02)))) - break; /* ignore NO_SENSE or NOT_READY in one case */ - - mly_printf(sc, "physical device %d:%d %s\n", me->channel, me->target, tp); - mly_printf(sc, " sense key %d asc %02x ascq %02x\n", - ssd->flags & SSD_KEY, ssd->add_sense_code, ssd->add_sense_code_qual); - mly_printf(sc, " info %4D csi %4D\n", ssd->info, "", ssd->cmd_spec_info, ""); - if (action == 'r') - sc->mly_btl[me->channel][me->target].mb_flags |= MLY_BTL_RESCAN; - break; - case 'e': - mly_printf(sc, tp, me->target, me->lun); - printf("\n"); - break; - case 'c': - mly_printf(sc, "controller %s\n", tp); - break; - case '?': - mly_printf(sc, "%s - %d\n", tp, me->code); - break; - default: /* probably a 'noisy' event being ignored */ - break; - } -} - -/******************************************************************************** - * Perform periodic activities. - */ -static void -mly_periodic(void *data) -{ - struct mly_softc *sc = (struct mly_softc *)data; - int bus, target; - - debug_called(2); - MLY_ASSERT_LOCKED(sc); - - /* - * Scan devices. - */ - for (bus = 0; bus < sc->mly_cam_channels; bus++) { - if (MLY_BUS_IS_VALID(sc, bus)) { - for (target = 0; target < MLY_MAX_TARGETS; target++) { - /* ignore the controller in this scan */ - if (target == sc->mly_controllerparam->initiator_id) - continue; - - /* perform device rescan? */ - if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_RESCAN) - mly_rescan_btl(sc, bus, target); - } - } - } - - /* check for controller events */ - mly_check_event(sc); - - /* reschedule ourselves */ - callout_schedule(&sc->mly_periodic, MLY_PERIODIC_INTERVAL * hz); -} - -/******************************************************************************** - ******************************************************************************** - Command Processing - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - * Run a command and wait for it to complete. - * - */ -static int -mly_immediate_command(struct mly_command *mc) -{ - struct mly_softc *sc = mc->mc_sc; - int error; - - debug_called(1); - - MLY_ASSERT_LOCKED(sc); - if ((error = mly_start(mc))) { - return(error); - } - - if (sc->mly_state & MLY_STATE_INTERRUPTS_ON) { - /* sleep on the command */ - while(!(mc->mc_flags & MLY_CMD_COMPLETE)) { - mtx_sleep(mc, &sc->mly_lock, PRIBIO, "mlywait", 0); - } - } else { - /* spin and collect status while we do */ - while(!(mc->mc_flags & MLY_CMD_COMPLETE)) { - mly_done(mc->mc_sc); - } - } - return(0); -} - -/******************************************************************************** - * Deliver a command to the controller. - * - * XXX it would be good to just queue commands that we can't submit immediately - * and send them later, but we probably want a wrapper for that so that - * we don't hang on a failed submission for an immediate command. - */ -static int -mly_start(struct mly_command *mc) -{ - struct mly_softc *sc = mc->mc_sc; - union mly_command_packet *pkt; - - debug_called(2); - MLY_ASSERT_LOCKED(sc); - - /* - * Set the command up for delivery to the controller. - */ - mly_map_command(mc); - mc->mc_packet->generic.command_id = mc->mc_slot; - -#ifdef MLY_DEBUG - mc->mc_timestamp = time_second; -#endif - - /* - * Do we have to use the hardware mailbox? - */ - if (!(sc->mly_state & MLY_STATE_MMBOX_ACTIVE)) { - /* - * Check to see if the controller is ready for us. - */ - if (MLY_IDBR_TRUE(sc, MLY_HM_CMDSENT)) { - return(EBUSY); - } - mc->mc_flags |= MLY_CMD_BUSY; - - /* - * It's ready, send the command. - */ - MLY_SET_MBOX(sc, sc->mly_command_mailbox, &mc->mc_packetphys); - MLY_SET_REG(sc, sc->mly_idbr, MLY_HM_CMDSENT); - - } else { /* use memory-mailbox mode */ - - pkt = &sc->mly_mmbox->mmm_command[sc->mly_mmbox_command_index]; - - /* check to see if the next index is free yet */ - if (pkt->mmbox.flag != 0) { - return(EBUSY); - } - mc->mc_flags |= MLY_CMD_BUSY; - - /* copy in new command */ - bcopy(mc->mc_packet->mmbox.data, pkt->mmbox.data, sizeof(pkt->mmbox.data)); - /* barrier to ensure completion of previous write before we write the flag */ - bus_barrier(sc->mly_regs_resource, 0, 0, BUS_SPACE_BARRIER_WRITE); - /* copy flag last */ - pkt->mmbox.flag = mc->mc_packet->mmbox.flag; - /* barrier to ensure completion of previous write before we notify the controller */ - bus_barrier(sc->mly_regs_resource, 0, 0, BUS_SPACE_BARRIER_WRITE); - - /* signal controller, update index */ - MLY_SET_REG(sc, sc->mly_idbr, MLY_AM_CMDSENT); - sc->mly_mmbox_command_index = (sc->mly_mmbox_command_index + 1) % MLY_MMBOX_COMMANDS; - } - - mly_enqueue_busy(mc); - return(0); -} - -/******************************************************************************** - * Pick up command status from the controller, schedule a completion event - */ -static void -mly_done(struct mly_softc *sc) -{ - struct mly_command *mc; - union mly_status_packet *sp; - u_int16_t slot; - int worked; - - MLY_ASSERT_LOCKED(sc); - worked = 0; - - /* pick up hardware-mailbox commands */ - if (MLY_ODBR_TRUE(sc, MLY_HM_STSREADY)) { - slot = MLY_GET_REG2(sc, sc->mly_status_mailbox); - if (slot < MLY_SLOT_MAX) { - mc = &sc->mly_command[slot - MLY_SLOT_START]; - mc->mc_status = MLY_GET_REG(sc, sc->mly_status_mailbox + 2); - mc->mc_sense = MLY_GET_REG(sc, sc->mly_status_mailbox + 3); - mc->mc_resid = MLY_GET_REG4(sc, sc->mly_status_mailbox + 4); - mly_remove_busy(mc); - mc->mc_flags &= ~MLY_CMD_BUSY; - mly_enqueue_complete(mc); - worked = 1; - } else { - /* slot 0xffff may mean "extremely bogus command" */ - mly_printf(sc, "got HM completion for illegal slot %u\n", slot); - } - /* unconditionally acknowledge status */ - MLY_SET_REG(sc, sc->mly_odbr, MLY_HM_STSREADY); - MLY_SET_REG(sc, sc->mly_idbr, MLY_HM_STSACK); - } - - /* pick up memory-mailbox commands */ - if (MLY_ODBR_TRUE(sc, MLY_AM_STSREADY)) { - for (;;) { - sp = &sc->mly_mmbox->mmm_status[sc->mly_mmbox_status_index]; - - /* check for more status */ - if (sp->mmbox.flag == 0) - break; - - /* get slot number */ - slot = sp->status.command_id; - if (slot < MLY_SLOT_MAX) { - mc = &sc->mly_command[slot - MLY_SLOT_START]; - mc->mc_status = sp->status.status; - mc->mc_sense = sp->status.sense_length; - mc->mc_resid = sp->status.residue; - mly_remove_busy(mc); - mc->mc_flags &= ~MLY_CMD_BUSY; - mly_enqueue_complete(mc); - worked = 1; - } else { - /* slot 0xffff may mean "extremely bogus command" */ - mly_printf(sc, "got AM completion for illegal slot %u at %d\n", - slot, sc->mly_mmbox_status_index); - } - - /* clear and move to next index */ - sp->mmbox.flag = 0; - sc->mly_mmbox_status_index = (sc->mly_mmbox_status_index + 1) % MLY_MMBOX_STATUS; - } - /* acknowledge that we have collected status value(s) */ - MLY_SET_REG(sc, sc->mly_odbr, MLY_AM_STSREADY); - } - - if (worked) { - if (sc->mly_state & MLY_STATE_INTERRUPTS_ON) - taskqueue_enqueue(taskqueue_thread, &sc->mly_task_complete); - else - mly_complete(sc); - } -} - -/******************************************************************************** - * Process completed commands - */ -static void -mly_complete_handler(void *context, int pending) -{ - struct mly_softc *sc = (struct mly_softc *)context; - - MLY_LOCK(sc); - mly_complete(sc); - MLY_UNLOCK(sc); -} - -static void -mly_complete(struct mly_softc *sc) -{ - struct mly_command *mc; - void (* mc_complete)(struct mly_command *mc); - - debug_called(2); - - /* - * Spin pulling commands off the completed queue and processing them. - */ - while ((mc = mly_dequeue_complete(sc)) != NULL) { - /* - * Free controller resources, mark command complete. - * - * Note that as soon as we mark the command complete, it may be freed - * out from under us, so we need to save the mc_complete field in - * order to later avoid dereferencing mc. (We would not expect to - * have a polling/sleeping consumer with mc_complete != NULL). - */ - mly_unmap_command(mc); - mc_complete = mc->mc_complete; - mc->mc_flags |= MLY_CMD_COMPLETE; - - /* - * Call completion handler or wake up sleeping consumer. - */ - if (mc_complete != NULL) { - mc_complete(mc); - } else { - wakeup(mc); - } - } - - /* - * XXX if we are deferring commands due to controller-busy status, we should - * retry submitting them here. - */ -} - -/******************************************************************************** - ******************************************************************************** - Command Buffer Management - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - * Allocate a command. - */ -static int -mly_alloc_command(struct mly_softc *sc, struct mly_command **mcp) -{ - struct mly_command *mc; - - debug_called(3); - - if ((mc = mly_dequeue_free(sc)) == NULL) - return(ENOMEM); - - *mcp = mc; - return(0); -} - -/******************************************************************************** - * Release a command back to the freelist. - */ -static void -mly_release_command(struct mly_command *mc) -{ - debug_called(3); - - /* - * Fill in parts of the command that may cause confusion if - * a consumer doesn't when we are later allocated. - */ - mc->mc_data = NULL; - mc->mc_flags = 0; - mc->mc_complete = NULL; - mc->mc_private = NULL; - - /* - * By default, we set up to overwrite the command packet with - * sense information. - */ - mc->mc_packet->generic.sense_buffer_address = mc->mc_packetphys; - mc->mc_packet->generic.maximum_sense_size = sizeof(union mly_command_packet); - - mly_enqueue_free(mc); -} - -/******************************************************************************** - * Map helper for command allocation. - */ -static void -mly_alloc_commands_map(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - struct mly_softc *sc = (struct mly_softc *)arg; - - debug_called(1); - - sc->mly_packetphys = segs[0].ds_addr; -} - -/******************************************************************************** - * Allocate and initialise command and packet structures. - * - * If the controller supports fewer than MLY_MAX_COMMANDS commands, limit our - * allocation to that number. If we don't yet know how many commands the - * controller supports, allocate a very small set (suitable for initialisation - * purposes only). - */ -static int -mly_alloc_commands(struct mly_softc *sc) -{ - struct mly_command *mc; - int i, ncmd; - - if (sc->mly_controllerinfo == NULL) { - ncmd = 4; - } else { - ncmd = min(MLY_MAX_COMMANDS, sc->mly_controllerinfo->maximum_parallel_commands); - } - - /* - * Allocate enough space for all the command packets in one chunk and - * map them permanently into controller-visible space. - */ - if (bus_dmamem_alloc(sc->mly_packet_dmat, (void **)&sc->mly_packet, - BUS_DMA_NOWAIT, &sc->mly_packetmap)) { - return(ENOMEM); - } - if (bus_dmamap_load(sc->mly_packet_dmat, sc->mly_packetmap, sc->mly_packet, - ncmd * sizeof(union mly_command_packet), - mly_alloc_commands_map, sc, BUS_DMA_NOWAIT) != 0) - return (ENOMEM); - - for (i = 0; i < ncmd; i++) { - mc = &sc->mly_command[i]; - bzero(mc, sizeof(*mc)); - mc->mc_sc = sc; - mc->mc_slot = MLY_SLOT_START + i; - mc->mc_packet = sc->mly_packet + i; - mc->mc_packetphys = sc->mly_packetphys + (i * sizeof(union mly_command_packet)); - if (!bus_dmamap_create(sc->mly_buffer_dmat, 0, &mc->mc_datamap)) - mly_release_command(mc); - } - return(0); -} - -/******************************************************************************** - * Free all the storage held by commands. - * - * Must be called with all commands on the free list. - */ -static void -mly_release_commands(struct mly_softc *sc) -{ - struct mly_command *mc; - - /* throw away command buffer DMA maps */ - while (mly_alloc_command(sc, &mc) == 0) - bus_dmamap_destroy(sc->mly_buffer_dmat, mc->mc_datamap); - - /* release the packet storage */ - if (sc->mly_packet != NULL) { - bus_dmamap_unload(sc->mly_packet_dmat, sc->mly_packetmap); - bus_dmamem_free(sc->mly_packet_dmat, sc->mly_packet, sc->mly_packetmap); - sc->mly_packet = NULL; - } -} - -/******************************************************************************** - * Command-mapping helper function - populate this command's s/g table - * with the s/g entries for its data. - */ -static void -mly_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - struct mly_command *mc = (struct mly_command *)arg; - struct mly_softc *sc = mc->mc_sc; - struct mly_command_generic *gen = &(mc->mc_packet->generic); - struct mly_sg_entry *sg; - int i, tabofs; - - debug_called(2); - - /* can we use the transfer structure directly? */ - if (nseg <= 2) { - sg = &gen->transfer.direct.sg[0]; - gen->command_control.extended_sg_table = 0; - } else { - tabofs = ((mc->mc_slot - MLY_SLOT_START) * MLY_MAX_SGENTRIES); - sg = sc->mly_sg_table + tabofs; - gen->transfer.indirect.entries[0] = nseg; - gen->transfer.indirect.table_physaddr[0] = sc->mly_sg_busaddr + (tabofs * sizeof(struct mly_sg_entry)); - gen->command_control.extended_sg_table = 1; - } - - /* copy the s/g table */ - for (i = 0; i < nseg; i++) { - sg[i].physaddr = segs[i].ds_addr; - sg[i].length = segs[i].ds_len; - } - -} - -#if 0 -/******************************************************************************** - * Command-mapping helper function - save the cdb's physical address. - * - * We don't support 'large' SCSI commands at this time, so this is unused. - */ -static void -mly_map_command_cdb(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - struct mly_command *mc = (struct mly_command *)arg; - - debug_called(2); - - /* XXX can we safely assume that a CDB will never cross a page boundary? */ - if ((segs[0].ds_addr % PAGE_SIZE) > - ((segs[0].ds_addr + mc->mc_packet->scsi_large.cdb_length) % PAGE_SIZE)) - panic("cdb crosses page boundary"); - - /* fix up fields in the command packet */ - mc->mc_packet->scsi_large.cdb_physaddr = segs[0].ds_addr; -} -#endif - -/******************************************************************************** - * Map a command into controller-visible space - */ -static void -mly_map_command(struct mly_command *mc) -{ - struct mly_softc *sc = mc->mc_sc; - - debug_called(2); - - /* don't map more than once */ - if (mc->mc_flags & MLY_CMD_MAPPED) - return; - - /* does the command have a data buffer? */ - if (mc->mc_data != NULL) { - if (mc->mc_flags & MLY_CMD_CCB) - bus_dmamap_load_ccb(sc->mly_buffer_dmat, mc->mc_datamap, - mc->mc_data, mly_map_command_sg, mc, 0); - else - bus_dmamap_load(sc->mly_buffer_dmat, mc->mc_datamap, - mc->mc_data, mc->mc_length, - mly_map_command_sg, mc, 0); - if (mc->mc_flags & MLY_CMD_DATAIN) - bus_dmamap_sync(sc->mly_buffer_dmat, mc->mc_datamap, BUS_DMASYNC_PREREAD); - if (mc->mc_flags & MLY_CMD_DATAOUT) - bus_dmamap_sync(sc->mly_buffer_dmat, mc->mc_datamap, BUS_DMASYNC_PREWRITE); - } - mc->mc_flags |= MLY_CMD_MAPPED; -} - -/******************************************************************************** - * Unmap a command from controller-visible space - */ -static void -mly_unmap_command(struct mly_command *mc) -{ - struct mly_softc *sc = mc->mc_sc; - - debug_called(2); - - if (!(mc->mc_flags & MLY_CMD_MAPPED)) - return; - - /* does the command have a data buffer? */ - if (mc->mc_data != NULL) { - if (mc->mc_flags & MLY_CMD_DATAIN) - bus_dmamap_sync(sc->mly_buffer_dmat, mc->mc_datamap, BUS_DMASYNC_POSTREAD); - if (mc->mc_flags & MLY_CMD_DATAOUT) - bus_dmamap_sync(sc->mly_buffer_dmat, mc->mc_datamap, BUS_DMASYNC_POSTWRITE); - - bus_dmamap_unload(sc->mly_buffer_dmat, mc->mc_datamap); - } - mc->mc_flags &= ~MLY_CMD_MAPPED; -} - -/******************************************************************************** - ******************************************************************************** - CAM interface - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - * Attach the physical and virtual SCSI busses to CAM. - * - * Physical bus numbering starts from 0, virtual bus numbering from one greater - * than the highest physical bus. Physical busses are only registered if - * the kernel environment variable "hw.mly.register_physical_channels" is set. - * - * When we refer to a "bus", we are referring to the bus number registered with - * the SIM, whereas a "channel" is a channel number given to the adapter. In order - * to keep things simple, we map these 1:1, so "bus" and "channel" may be used - * interchangeably. - */ -static int -mly_cam_attach(struct mly_softc *sc) -{ - struct cam_devq *devq; - int chn, i; - - debug_called(1); - - /* - * Allocate a devq for all our channels combined. - */ - if ((devq = cam_simq_alloc(sc->mly_controllerinfo->maximum_parallel_commands)) == NULL) { - mly_printf(sc, "can't allocate CAM SIM queue\n"); - return(ENOMEM); - } - - /* - * If physical channel registration has been requested, register these first. - * Note that we enable tagged command queueing for physical channels. - */ - if (testenv("hw.mly.register_physical_channels")) { - chn = 0; - for (i = 0; i < sc->mly_controllerinfo->physical_channels_present; i++, chn++) { - if ((sc->mly_cam_sim[chn] = cam_sim_alloc(mly_cam_action, mly_cam_poll, "mly", sc, - device_get_unit(sc->mly_dev), - &sc->mly_lock, - sc->mly_controllerinfo->maximum_parallel_commands, - 1, devq)) == NULL) { - return(ENOMEM); - } - MLY_LOCK(sc); - if (xpt_bus_register(sc->mly_cam_sim[chn], sc->mly_dev, chn)) { - MLY_UNLOCK(sc); - mly_printf(sc, "CAM XPT phsyical channel registration failed\n"); - return(ENXIO); - } - MLY_UNLOCK(sc); - debug(1, "registered physical channel %d", chn); - } - } - - /* - * Register our virtual channels, with bus numbers matching channel numbers. - */ - chn = sc->mly_controllerinfo->physical_channels_present; - for (i = 0; i < sc->mly_controllerinfo->virtual_channels_present; i++, chn++) { - if ((sc->mly_cam_sim[chn] = cam_sim_alloc(mly_cam_action, mly_cam_poll, "mly", sc, - device_get_unit(sc->mly_dev), - &sc->mly_lock, - sc->mly_controllerinfo->maximum_parallel_commands, - 0, devq)) == NULL) { - return(ENOMEM); - } - MLY_LOCK(sc); - if (xpt_bus_register(sc->mly_cam_sim[chn], sc->mly_dev, chn)) { - MLY_UNLOCK(sc); - mly_printf(sc, "CAM XPT virtual channel registration failed\n"); - return(ENXIO); - } - MLY_UNLOCK(sc); - debug(1, "registered virtual channel %d", chn); - } - - /* - * This is the total number of channels that (might have been) registered with - * CAM. Some may not have been; check the mly_cam_sim array to be certain. - */ - sc->mly_cam_channels = sc->mly_controllerinfo->physical_channels_present + - sc->mly_controllerinfo->virtual_channels_present; - - return(0); -} - -/******************************************************************************** - * Detach from CAM - */ -static void -mly_cam_detach(struct mly_softc *sc) -{ - int i; - - debug_called(1); - - MLY_LOCK(sc); - for (i = 0; i < sc->mly_cam_channels; i++) { - if (sc->mly_cam_sim[i] != NULL) { - xpt_bus_deregister(cam_sim_path(sc->mly_cam_sim[i])); - cam_sim_free(sc->mly_cam_sim[i], 0); - } - } - MLY_UNLOCK(sc); - if (sc->mly_cam_devq != NULL) - cam_simq_free(sc->mly_cam_devq); -} - -/************************************************************************ - * Rescan a device. - */ -static void -mly_cam_rescan_btl(struct mly_softc *sc, int bus, int target) -{ - union ccb *ccb; - - debug_called(1); - - if ((ccb = xpt_alloc_ccb()) == NULL) { - mly_printf(sc, "rescan failed (can't allocate CCB)\n"); - return; - } - if (xpt_create_path(&ccb->ccb_h.path, NULL, - cam_sim_path(sc->mly_cam_sim[bus]), target, 0) != CAM_REQ_CMP) { - mly_printf(sc, "rescan failed (can't create path)\n"); - xpt_free_ccb(ccb); - return; - } - debug(1, "rescan target %d:%d", bus, target); - xpt_rescan(ccb); -} - -/******************************************************************************** - * Handle an action requested by CAM - */ -static void -mly_cam_action(struct cam_sim *sim, union ccb *ccb) -{ - struct mly_softc *sc = cam_sim_softc(sim); - - debug_called(2); - MLY_ASSERT_LOCKED(sc); - - switch (ccb->ccb_h.func_code) { - /* perform SCSI I/O */ - case XPT_SCSI_IO: - if (!mly_cam_action_io(sim, (struct ccb_scsiio *)&ccb->csio)) - return; - break; - - /* perform geometry calculations */ - case XPT_CALC_GEOMETRY: - { - struct ccb_calc_geometry *ccg = &ccb->ccg; - u_int32_t secs_per_cylinder; - - debug(2, "XPT_CALC_GEOMETRY %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun); - - if (sc->mly_controllerparam->bios_geometry == MLY_BIOSGEOM_8G) { - ccg->heads = 255; - ccg->secs_per_track = 63; - } else { /* MLY_BIOSGEOM_2G */ - ccg->heads = 128; - ccg->secs_per_track = 32; - } - secs_per_cylinder = ccg->heads * ccg->secs_per_track; - ccg->cylinders = ccg->volume_size / secs_per_cylinder; - ccb->ccb_h.status = CAM_REQ_CMP; - break; - } - - /* handle path attribute inquiry */ - case XPT_PATH_INQ: - { - struct ccb_pathinq *cpi = &ccb->cpi; - - debug(2, "XPT_PATH_INQ %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun); - - cpi->version_num = 1; - cpi->hba_inquiry = PI_TAG_ABLE; /* XXX extra flags for physical channels? */ - cpi->target_sprt = 0; - cpi->hba_misc = 0; - cpi->max_target = MLY_MAX_TARGETS - 1; - cpi->max_lun = MLY_MAX_LUNS - 1; - cpi->initiator_id = sc->mly_controllerparam->initiator_id; - strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strlcpy(cpi->hba_vid, "Mylex", 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 what to set this to? */ - cpi->transport = XPORT_SPI; - cpi->transport_version = 2; - cpi->protocol = PROTO_SCSI; - cpi->protocol_version = SCSI_REV_2; - ccb->ccb_h.status = CAM_REQ_CMP; - break; - } - - case XPT_GET_TRAN_SETTINGS: - { - struct ccb_trans_settings *cts = &ccb->cts; - int bus, target; - struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi; - struct ccb_trans_settings_spi *spi = &cts->xport_specific.spi; - - cts->protocol = PROTO_SCSI; - cts->protocol_version = SCSI_REV_2; - cts->transport = XPORT_SPI; - cts->transport_version = 2; - - scsi->flags = 0; - scsi->valid = 0; - spi->flags = 0; - spi->valid = 0; - - bus = cam_sim_bus(sim); - target = cts->ccb_h.target_id; - debug(2, "XPT_GET_TRAN_SETTINGS %d:%d", bus, target); - /* logical device? */ - if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_LOGICAL) { - /* nothing special for these */ - /* physical device? */ - } else if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_PHYSICAL) { - /* allow CAM to try tagged transactions */ - scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; - scsi->valid |= CTS_SCSI_VALID_TQ; - - /* convert speed (MHz) to usec */ - if (sc->mly_btl[bus][target].mb_speed == 0) { - spi->sync_period = 1000000 / 5; - } else { - spi->sync_period = 1000000 / sc->mly_btl[bus][target].mb_speed; - } - - /* convert bus width to CAM internal encoding */ - switch (sc->mly_btl[bus][target].mb_width) { - case 32: - spi->bus_width = MSG_EXT_WDTR_BUS_32_BIT; - break; - case 16: - spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; - break; - case 8: - default: - spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; - break; - } - spi->valid |= CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_BUS_WIDTH; - - /* not a device, bail out */ - } else { - cts->ccb_h.status = CAM_REQ_CMP_ERR; - break; - } - - /* disconnect always OK */ - spi->flags |= CTS_SPI_FLAGS_DISC_ENB; - spi->valid |= CTS_SPI_VALID_DISC; - - cts->ccb_h.status = CAM_REQ_CMP; - break; - } - - default: /* we can't do this */ - debug(2, "unspported func_code = 0x%x", ccb->ccb_h.func_code); - ccb->ccb_h.status = CAM_REQ_INVALID; - break; - } - - xpt_done(ccb); -} - -/******************************************************************************** - * Handle an I/O operation requested by CAM - */ -static int -mly_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio) -{ - struct mly_softc *sc = cam_sim_softc(sim); - struct mly_command *mc; - struct mly_command_scsi_small *ss; - int bus, target; - int error; - - bus = cam_sim_bus(sim); - target = csio->ccb_h.target_id; - - debug(2, "XPT_SCSI_IO %d:%d:%d", bus, target, csio->ccb_h.target_lun); - - /* validate bus number */ - if (!MLY_BUS_IS_VALID(sc, bus)) { - debug(0, " invalid bus %d", bus); - csio->ccb_h.status = CAM_REQ_CMP_ERR; - } - - /* check for I/O attempt to a protected device */ - if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_PROTECTED) { - debug(2, " device protected"); - csio->ccb_h.status = CAM_REQ_CMP_ERR; - } - - /* check for I/O attempt to nonexistent device */ - if (!(sc->mly_btl[bus][target].mb_flags & (MLY_BTL_LOGICAL | MLY_BTL_PHYSICAL))) { - debug(2, " device %d:%d does not exist", bus, target); - csio->ccb_h.status = CAM_REQ_CMP_ERR; - } - - /* XXX increase if/when we support large SCSI commands */ - if (csio->cdb_len > MLY_CMD_SCSI_SMALL_CDB) { - debug(0, " command too large (%d > %d)", csio->cdb_len, MLY_CMD_SCSI_SMALL_CDB); - csio->ccb_h.status = CAM_REQ_CMP_ERR; - } - - /* check that the CDB pointer is not to a physical address */ - if ((csio->ccb_h.flags & CAM_CDB_POINTER) && (csio->ccb_h.flags & CAM_CDB_PHYS)) { - debug(0, " CDB pointer is to physical address"); - csio->ccb_h.status = CAM_REQ_CMP_ERR; - } - - /* abandon aborted ccbs or those that have failed validation */ - if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { - debug(2, "abandoning CCB due to abort/validation failure"); - return(EINVAL); - } - - /* - * Get a command, or push the ccb back to CAM and freeze the queue. - */ - if ((error = mly_alloc_command(sc, &mc))) { - xpt_freeze_simq(sim, 1); - csio->ccb_h.status |= CAM_REQUEUE_REQ; - sc->mly_qfrzn_cnt++; - return(error); - } - - /* build the command */ - mc->mc_data = csio; - mc->mc_length = csio->dxfer_len; - mc->mc_complete = mly_cam_complete; - mc->mc_private = csio; - mc->mc_flags |= MLY_CMD_CCB; - /* XXX This code doesn't set the data direction in mc_flags. */ - - /* save the bus number in the ccb for later recovery XXX should be a better way */ - csio->ccb_h.sim_priv.entries[0].field = bus; - - /* build the packet for the controller */ - ss = &mc->mc_packet->scsi_small; - ss->opcode = MDACMD_SCSI; - if (csio->ccb_h.flags & CAM_DIS_DISCONNECT) - ss->command_control.disable_disconnect = 1; - if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) - ss->command_control.data_direction = MLY_CCB_WRITE; - ss->data_size = csio->dxfer_len; - ss->addr.phys.lun = csio->ccb_h.target_lun; - ss->addr.phys.target = csio->ccb_h.target_id; - ss->addr.phys.channel = bus; - if (csio->ccb_h.timeout < (60 * 1000)) { - ss->timeout.value = csio->ccb_h.timeout / 1000; - ss->timeout.scale = MLY_TIMEOUT_SECONDS; - } else if (csio->ccb_h.timeout < (60 * 60 * 1000)) { - ss->timeout.value = csio->ccb_h.timeout / (60 * 1000); - ss->timeout.scale = MLY_TIMEOUT_MINUTES; - } else { - ss->timeout.value = csio->ccb_h.timeout / (60 * 60 * 1000); /* overflow? */ - ss->timeout.scale = MLY_TIMEOUT_HOURS; - } - ss->maximum_sense_size = csio->sense_len; - ss->cdb_length = csio->cdb_len; - if (csio->ccb_h.flags & CAM_CDB_POINTER) { - bcopy(csio->cdb_io.cdb_ptr, ss->cdb, csio->cdb_len); - } else { - bcopy(csio->cdb_io.cdb_bytes, ss->cdb, csio->cdb_len); - } - - /* give the command to the controller */ - if ((error = mly_start(mc))) { - xpt_freeze_simq(sim, 1); - csio->ccb_h.status |= CAM_REQUEUE_REQ; - sc->mly_qfrzn_cnt++; - return(error); - } - - return(0); -} - -/******************************************************************************** - * Check for possibly-completed commands. - */ -static void -mly_cam_poll(struct cam_sim *sim) -{ - struct mly_softc *sc = cam_sim_softc(sim); - - debug_called(2); - - mly_done(sc); -} - -/******************************************************************************** - * Handle completion of a command - pass results back through the CCB - */ -static void -mly_cam_complete(struct mly_command *mc) -{ - struct mly_softc *sc = mc->mc_sc; - struct ccb_scsiio *csio = (struct ccb_scsiio *)mc->mc_private; - struct scsi_inquiry_data *inq = (struct scsi_inquiry_data *)csio->data_ptr; - struct mly_btl *btl; - u_int8_t cmd; - int bus, target; - - debug_called(2); - - csio->scsi_status = mc->mc_status; - switch(mc->mc_status) { - case SCSI_STATUS_OK: - /* - * In order to report logical device type and status, we overwrite - * the result of the INQUIRY command to logical devices. - */ - bus = csio->ccb_h.sim_priv.entries[0].field; - target = csio->ccb_h.target_id; - /* XXX validate bus/target? */ - if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_LOGICAL) { - if (csio->ccb_h.flags & CAM_CDB_POINTER) { - cmd = *csio->cdb_io.cdb_ptr; - } else { - cmd = csio->cdb_io.cdb_bytes[0]; - } - if (cmd == INQUIRY) { - btl = &sc->mly_btl[bus][target]; - padstr(inq->vendor, mly_describe_code(mly_table_device_type, btl->mb_type), 8); - padstr(inq->product, mly_describe_code(mly_table_device_state, btl->mb_state), 16); - padstr(inq->revision, "", 4); - } - } - - debug(2, "SCSI_STATUS_OK"); - csio->ccb_h.status = CAM_REQ_CMP; - break; - - case SCSI_STATUS_CHECK_COND: - debug(1, "SCSI_STATUS_CHECK_COND sense %d resid %d", mc->mc_sense, mc->mc_resid); - csio->ccb_h.status = CAM_SCSI_STATUS_ERROR; - bzero(&csio->sense_data, SSD_FULL_SIZE); - bcopy(mc->mc_packet, &csio->sense_data, mc->mc_sense); - csio->sense_len = mc->mc_sense; - csio->ccb_h.status |= CAM_AUTOSNS_VALID; - csio->resid = mc->mc_resid; /* XXX this is a signed value... */ - break; - - case SCSI_STATUS_BUSY: - debug(1, "SCSI_STATUS_BUSY"); - csio->ccb_h.status = CAM_SCSI_BUSY; - break; - - default: - debug(1, "unknown status 0x%x", csio->scsi_status); - csio->ccb_h.status = CAM_REQ_CMP_ERR; - break; - } - - if (sc->mly_qfrzn_cnt) { - csio->ccb_h.status |= CAM_RELEASE_SIMQ; - sc->mly_qfrzn_cnt--; - } - - xpt_done((union ccb *)csio); - mly_release_command(mc); -} - -/******************************************************************************** - * Find a peripheral attahed at (bus),(target) - */ -static struct cam_periph * -mly_find_periph(struct mly_softc *sc, int bus, int target) -{ - struct cam_periph *periph; - struct cam_path *path; - int status; - - status = xpt_create_path(&path, NULL, cam_sim_path(sc->mly_cam_sim[bus]), target, 0); - if (status == CAM_REQ_CMP) { - periph = cam_periph_find(path, NULL); - xpt_free_path(path); - } else { - periph = NULL; - } - return(periph); -} - -/******************************************************************************** - * Name the device at (bus)(target) - */ -static int -mly_name_device(struct mly_softc *sc, int bus, int target) -{ - struct cam_periph *periph; - - if ((periph = mly_find_periph(sc, bus, target)) != NULL) { - sprintf(sc->mly_btl[bus][target].mb_name, "%s%d", periph->periph_name, periph->unit_number); - return(0); - } - sc->mly_btl[bus][target].mb_name[0] = 0; - return(ENOENT); -} - -/******************************************************************************** - ******************************************************************************** - Hardware Control - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - * Handshake with the firmware while the card is being initialised. - */ -static int -mly_fwhandshake(struct mly_softc *sc) -{ - u_int8_t error, param0, param1; - int spinup = 0; - - debug_called(1); - - /* set HM_STSACK and let the firmware initialise */ - MLY_SET_REG(sc, sc->mly_idbr, MLY_HM_STSACK); - DELAY(1000); /* too short? */ - - /* if HM_STSACK is still true, the controller is initialising */ - if (!MLY_IDBR_TRUE(sc, MLY_HM_STSACK)) - return(0); - mly_printf(sc, "controller initialisation started\n"); - - /* spin waiting for initialisation to finish, or for a message to be delivered */ - while (MLY_IDBR_TRUE(sc, MLY_HM_STSACK)) { - /* check for a message */ - if (MLY_ERROR_VALID(sc)) { - error = MLY_GET_REG(sc, sc->mly_error_status) & ~MLY_MSG_EMPTY; - param0 = MLY_GET_REG(sc, sc->mly_command_mailbox); - param1 = MLY_GET_REG(sc, sc->mly_command_mailbox + 1); - - switch(error) { - case MLY_MSG_SPINUP: - if (!spinup) { - mly_printf(sc, "drive spinup in progress\n"); - spinup = 1; /* only print this once (should print drive being spun?) */ - } - break; - case MLY_MSG_RACE_RECOVERY_FAIL: - mly_printf(sc, "mirror race recovery failed, one or more drives offline\n"); - break; - case MLY_MSG_RACE_IN_PROGRESS: - mly_printf(sc, "mirror race recovery in progress\n"); - break; - case MLY_MSG_RACE_ON_CRITICAL: - mly_printf(sc, "mirror race recovery on a critical drive\n"); - break; - case MLY_MSG_PARITY_ERROR: - mly_printf(sc, "FATAL MEMORY PARITY ERROR\n"); - return(ENXIO); - default: - mly_printf(sc, "unknown initialisation code 0x%x\n", error); - } - } - } - return(0); -} - -/******************************************************************************** - ******************************************************************************** - Debugging and Diagnostics - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - * Print some information about the controller. - */ -static void -mly_describe_controller(struct mly_softc *sc) -{ - struct mly_ioctl_getcontrollerinfo *mi = sc->mly_controllerinfo; - - mly_printf(sc, "%16s, %d channel%s, firmware %d.%02d-%d-%02d (%02d%02d%02d%02d), %dMB RAM\n", - mi->controller_name, mi->physical_channels_present, (mi->physical_channels_present) > 1 ? "s" : "", - mi->fw_major, mi->fw_minor, mi->fw_turn, mi->fw_build, /* XXX turn encoding? */ - mi->fw_century, mi->fw_year, mi->fw_month, mi->fw_day, - mi->memory_size); - - if (bootverbose) { - mly_printf(sc, "%s %s (%x), %dMHz %d-bit %.16s\n", - mly_describe_code(mly_table_oemname, mi->oem_information), - mly_describe_code(mly_table_controllertype, mi->controller_type), mi->controller_type, - mi->interface_speed, mi->interface_width, mi->interface_name); - mly_printf(sc, "%dMB %dMHz %d-bit %s%s%s, cache %dMB\n", - mi->memory_size, mi->memory_speed, mi->memory_width, - mly_describe_code(mly_table_memorytype, mi->memory_type), - mi->memory_parity ? "+parity": "",mi->memory_ecc ? "+ECC": "", - mi->cache_size); - mly_printf(sc, "CPU: %s @ %dMHz\n", - mly_describe_code(mly_table_cputype, mi->cpu[0].type), mi->cpu[0].speed); - if (mi->l2cache_size != 0) - mly_printf(sc, "%dKB L2 cache\n", mi->l2cache_size); - if (mi->exmemory_size != 0) - mly_printf(sc, "%dMB %dMHz %d-bit private %s%s%s\n", - mi->exmemory_size, mi->exmemory_speed, mi->exmemory_width, - mly_describe_code(mly_table_memorytype, mi->exmemory_type), - mi->exmemory_parity ? "+parity": "",mi->exmemory_ecc ? "+ECC": ""); - mly_printf(sc, "battery backup %s\n", mi->bbu_present ? "present" : "not installed"); - mly_printf(sc, "maximum data transfer %d blocks, maximum sg entries/command %d\n", - mi->maximum_block_count, mi->maximum_sg_entries); - mly_printf(sc, "logical devices present/critical/offline %d/%d/%d\n", - mi->logical_devices_present, mi->logical_devices_critical, mi->logical_devices_offline); - mly_printf(sc, "physical devices present %d\n", - mi->physical_devices_present); - mly_printf(sc, "physical disks present/offline %d/%d\n", - mi->physical_disks_present, mi->physical_disks_offline); - mly_printf(sc, "%d physical channel%s, %d virtual channel%s of %d possible\n", - mi->physical_channels_present, mi->physical_channels_present == 1 ? "" : "s", - mi->virtual_channels_present, mi->virtual_channels_present == 1 ? "" : "s", - mi->virtual_channels_possible); - mly_printf(sc, "%d parallel commands supported\n", mi->maximum_parallel_commands); - mly_printf(sc, "%dMB flash ROM, %d of %d maximum cycles\n", - mi->flash_size, mi->flash_age, mi->flash_maximum_age); - } -} - -#ifdef MLY_DEBUG -/******************************************************************************** - * Print some controller state - */ -static void -mly_printstate(struct mly_softc *sc) -{ - mly_printf(sc, "IDBR %02x ODBR %02x ERROR %02x (%x %x %x)\n", - MLY_GET_REG(sc, sc->mly_idbr), - MLY_GET_REG(sc, sc->mly_odbr), - MLY_GET_REG(sc, sc->mly_error_status), - sc->mly_idbr, - sc->mly_odbr, - sc->mly_error_status); - mly_printf(sc, "IMASK %02x ISTATUS %02x\n", - MLY_GET_REG(sc, sc->mly_interrupt_mask), - MLY_GET_REG(sc, sc->mly_interrupt_status)); - mly_printf(sc, "COMMAND %02x %02x %02x %02x %02x %02x %02x %02x\n", - MLY_GET_REG(sc, sc->mly_command_mailbox), - MLY_GET_REG(sc, sc->mly_command_mailbox + 1), - MLY_GET_REG(sc, sc->mly_command_mailbox + 2), - MLY_GET_REG(sc, sc->mly_command_mailbox + 3), - MLY_GET_REG(sc, sc->mly_command_mailbox + 4), - MLY_GET_REG(sc, sc->mly_command_mailbox + 5), - MLY_GET_REG(sc, sc->mly_command_mailbox + 6), - MLY_GET_REG(sc, sc->mly_command_mailbox + 7)); - mly_printf(sc, "STATUS %02x %02x %02x %02x %02x %02x %02x %02x\n", - MLY_GET_REG(sc, sc->mly_status_mailbox), - MLY_GET_REG(sc, sc->mly_status_mailbox + 1), - MLY_GET_REG(sc, sc->mly_status_mailbox + 2), - MLY_GET_REG(sc, sc->mly_status_mailbox + 3), - MLY_GET_REG(sc, sc->mly_status_mailbox + 4), - MLY_GET_REG(sc, sc->mly_status_mailbox + 5), - MLY_GET_REG(sc, sc->mly_status_mailbox + 6), - MLY_GET_REG(sc, sc->mly_status_mailbox + 7)); - mly_printf(sc, " %04x %08x\n", - MLY_GET_REG2(sc, sc->mly_status_mailbox), - MLY_GET_REG4(sc, sc->mly_status_mailbox + 4)); -} - -struct mly_softc *mly_softc0 = NULL; -void -mly_printstate0(void) -{ - if (mly_softc0 != NULL) - mly_printstate(mly_softc0); -} - -/******************************************************************************** - * Print a command - */ -static void -mly_print_command(struct mly_command *mc) -{ - struct mly_softc *sc = mc->mc_sc; - - mly_printf(sc, "COMMAND @ %p\n", mc); - mly_printf(sc, " slot %d\n", mc->mc_slot); - mly_printf(sc, " status 0x%x\n", mc->mc_status); - mly_printf(sc, " sense len %d\n", mc->mc_sense); - mly_printf(sc, " resid %d\n", mc->mc_resid); - mly_printf(sc, " packet %p/0x%llx\n", mc->mc_packet, mc->mc_packetphys); - if (mc->mc_packet != NULL) - mly_print_packet(mc); - mly_printf(sc, " data %p/%d\n", mc->mc_data, mc->mc_length); - mly_printf(sc, " flags %b\n", mc->mc_flags, "\20\1busy\2complete\3slotted\4mapped\5datain\6dataout\n"); - mly_printf(sc, " complete %p\n", mc->mc_complete); - mly_printf(sc, " private %p\n", mc->mc_private); -} - -/******************************************************************************** - * Print a command packet - */ -static void -mly_print_packet(struct mly_command *mc) -{ - struct mly_softc *sc = mc->mc_sc; - struct mly_command_generic *ge = (struct mly_command_generic *)mc->mc_packet; - struct mly_command_scsi_small *ss = (struct mly_command_scsi_small *)mc->mc_packet; - struct mly_command_scsi_large *sl = (struct mly_command_scsi_large *)mc->mc_packet; - struct mly_command_ioctl *io = (struct mly_command_ioctl *)mc->mc_packet; - int transfer; - - mly_printf(sc, " command_id %d\n", ge->command_id); - mly_printf(sc, " opcode %d\n", ge->opcode); - mly_printf(sc, " command_control fua %d dpo %d est %d dd %s nas %d ddis %d\n", - ge->command_control.force_unit_access, - ge->command_control.disable_page_out, - ge->command_control.extended_sg_table, - (ge->command_control.data_direction == MLY_CCB_WRITE) ? "WRITE" : "READ", - ge->command_control.no_auto_sense, - ge->command_control.disable_disconnect); - mly_printf(sc, " data_size %d\n", ge->data_size); - mly_printf(sc, " sense_buffer_address 0x%llx\n", ge->sense_buffer_address); - mly_printf(sc, " lun %d\n", ge->addr.phys.lun); - mly_printf(sc, " target %d\n", ge->addr.phys.target); - mly_printf(sc, " channel %d\n", ge->addr.phys.channel); - mly_printf(sc, " logical device %d\n", ge->addr.log.logdev); - mly_printf(sc, " controller %d\n", ge->addr.phys.controller); - mly_printf(sc, " timeout %d %s\n", - ge->timeout.value, - (ge->timeout.scale == MLY_TIMEOUT_SECONDS) ? "seconds" : - ((ge->timeout.scale == MLY_TIMEOUT_MINUTES) ? "minutes" : "hours")); - mly_printf(sc, " maximum_sense_size %d\n", ge->maximum_sense_size); - switch(ge->opcode) { - case MDACMD_SCSIPT: - case MDACMD_SCSI: - mly_printf(sc, " cdb length %d\n", ss->cdb_length); - mly_printf(sc, " cdb %*D\n", ss->cdb_length, ss->cdb, " "); - transfer = 1; - break; - case MDACMD_SCSILC: - case MDACMD_SCSILCPT: - mly_printf(sc, " cdb length %d\n", sl->cdb_length); - mly_printf(sc, " cdb 0x%llx\n", sl->cdb_physaddr); - transfer = 1; - break; - case MDACMD_IOCTL: - mly_printf(sc, " sub_ioctl 0x%x\n", io->sub_ioctl); - switch(io->sub_ioctl) { - case MDACIOCTL_SETMEMORYMAILBOX: - mly_printf(sc, " health_buffer_size %d\n", - io->param.setmemorymailbox.health_buffer_size); - mly_printf(sc, " health_buffer_phys 0x%llx\n", - io->param.setmemorymailbox.health_buffer_physaddr); - mly_printf(sc, " command_mailbox 0x%llx\n", - io->param.setmemorymailbox.command_mailbox_physaddr); - mly_printf(sc, " status_mailbox 0x%llx\n", - io->param.setmemorymailbox.status_mailbox_physaddr); - transfer = 0; - break; - - case MDACIOCTL_SETREALTIMECLOCK: - case MDACIOCTL_GETHEALTHSTATUS: - case MDACIOCTL_GETCONTROLLERINFO: - case MDACIOCTL_GETLOGDEVINFOVALID: - case MDACIOCTL_GETPHYSDEVINFOVALID: - case MDACIOCTL_GETPHYSDEVSTATISTICS: - case MDACIOCTL_GETLOGDEVSTATISTICS: - case MDACIOCTL_GETCONTROLLERSTATISTICS: - case MDACIOCTL_GETBDT_FOR_SYSDRIVE: - case MDACIOCTL_CREATENEWCONF: - case MDACIOCTL_ADDNEWCONF: - case MDACIOCTL_GETDEVCONFINFO: - case MDACIOCTL_GETFREESPACELIST: - case MDACIOCTL_MORE: - case MDACIOCTL_SETPHYSDEVPARAMETER: - case MDACIOCTL_GETPHYSDEVPARAMETER: - case MDACIOCTL_GETLOGDEVPARAMETER: - case MDACIOCTL_SETLOGDEVPARAMETER: - mly_printf(sc, " param %10D\n", io->param.data.param, " "); - transfer = 1; - break; - - case MDACIOCTL_GETEVENT: - mly_printf(sc, " event %d\n", - io->param.getevent.sequence_number_low + ((u_int32_t)io->addr.log.logdev << 16)); - transfer = 1; - break; - - case MDACIOCTL_SETRAIDDEVSTATE: - mly_printf(sc, " state %d\n", io->param.setraiddevstate.state); - transfer = 0; - break; - - case MDACIOCTL_XLATEPHYSDEVTORAIDDEV: - mly_printf(sc, " raid_device %d\n", io->param.xlatephysdevtoraiddev.raid_device); - mly_printf(sc, " controller %d\n", io->param.xlatephysdevtoraiddev.controller); - mly_printf(sc, " channel %d\n", io->param.xlatephysdevtoraiddev.channel); - mly_printf(sc, " target %d\n", io->param.xlatephysdevtoraiddev.target); - mly_printf(sc, " lun %d\n", io->param.xlatephysdevtoraiddev.lun); - transfer = 0; - break; - - case MDACIOCTL_GETGROUPCONFINFO: - mly_printf(sc, " group %d\n", io->param.getgroupconfinfo.group); - transfer = 1; - break; - - case MDACIOCTL_GET_SUBSYSTEM_DATA: - case MDACIOCTL_SET_SUBSYSTEM_DATA: - case MDACIOCTL_STARTDISOCVERY: - case MDACIOCTL_INITPHYSDEVSTART: - case MDACIOCTL_INITPHYSDEVSTOP: - case MDACIOCTL_INITRAIDDEVSTART: - case MDACIOCTL_INITRAIDDEVSTOP: - case MDACIOCTL_REBUILDRAIDDEVSTART: - case MDACIOCTL_REBUILDRAIDDEVSTOP: - case MDACIOCTL_MAKECONSISTENTDATASTART: - case MDACIOCTL_MAKECONSISTENTDATASTOP: - case MDACIOCTL_CONSISTENCYCHECKSTART: - case MDACIOCTL_CONSISTENCYCHECKSTOP: - case MDACIOCTL_RESETDEVICE: - case MDACIOCTL_FLUSHDEVICEDATA: - case MDACIOCTL_PAUSEDEVICE: - case MDACIOCTL_UNPAUSEDEVICE: - case MDACIOCTL_LOCATEDEVICE: - case MDACIOCTL_SETMASTERSLAVEMODE: - case MDACIOCTL_DELETERAIDDEV: - case MDACIOCTL_REPLACEINTERNALDEV: - case MDACIOCTL_CLEARCONF: - case MDACIOCTL_GETCONTROLLERPARAMETER: - case MDACIOCTL_SETCONTRLLERPARAMETER: - case MDACIOCTL_CLEARCONFSUSPMODE: - case MDACIOCTL_STOREIMAGE: - case MDACIOCTL_READIMAGE: - case MDACIOCTL_FLASHIMAGES: - case MDACIOCTL_RENAMERAIDDEV: - default: /* no idea what to print */ - transfer = 0; - break; - } - break; - - case MDACMD_IOCTLCHECK: - case MDACMD_MEMCOPY: - default: - transfer = 0; - break; /* print nothing */ - } - if (transfer) { - if (ge->command_control.extended_sg_table) { - mly_printf(sc, " sg table 0x%llx/%d\n", - ge->transfer.indirect.table_physaddr[0], ge->transfer.indirect.entries[0]); - } else { - mly_printf(sc, " 0000 0x%llx/%lld\n", - ge->transfer.direct.sg[0].physaddr, ge->transfer.direct.sg[0].length); - mly_printf(sc, " 0001 0x%llx/%lld\n", - ge->transfer.direct.sg[1].physaddr, ge->transfer.direct.sg[1].length); - } - } -} - -/******************************************************************************** - * Panic in a slightly informative fashion - */ -static void -mly_panic(struct mly_softc *sc, char *reason) -{ - mly_printstate(sc); - panic(reason); -} - -/******************************************************************************** - * Print queue statistics, callable from DDB. - */ -void -mly_print_controller(int controller) -{ - struct mly_softc *sc; - - if ((sc = devclass_get_softc(devclass_find("mly"), controller)) == NULL) { - printf("mly: controller %d invalid\n", controller); - } else { - device_printf(sc->mly_dev, "queue curr max\n"); - device_printf(sc->mly_dev, "free %04d/%04d\n", - sc->mly_qstat[MLYQ_FREE].q_length, sc->mly_qstat[MLYQ_FREE].q_max); - device_printf(sc->mly_dev, "busy %04d/%04d\n", - sc->mly_qstat[MLYQ_BUSY].q_length, sc->mly_qstat[MLYQ_BUSY].q_max); - device_printf(sc->mly_dev, "complete %04d/%04d\n", - sc->mly_qstat[MLYQ_COMPLETE].q_length, sc->mly_qstat[MLYQ_COMPLETE].q_max); - } -} -#endif - -/******************************************************************************** - ******************************************************************************** - Control device interface - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - * Accept an open operation on the control device. - */ -static int -mly_user_open(struct cdev *dev, int flags, int fmt, struct thread *td) -{ - struct mly_softc *sc = dev->si_drv1; - - MLY_LOCK(sc); - sc->mly_state |= MLY_STATE_OPEN; - MLY_UNLOCK(sc); - return(0); -} - -/******************************************************************************** - * Accept the last close on the control device. - */ -static int -mly_user_close(struct cdev *dev, int flags, int fmt, struct thread *td) -{ - struct mly_softc *sc = dev->si_drv1; - - MLY_LOCK(sc); - sc->mly_state &= ~MLY_STATE_OPEN; - MLY_UNLOCK(sc); - return (0); -} - -/******************************************************************************** - * Handle controller-specific control operations. - */ -static int -mly_user_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, - int32_t flag, struct thread *td) -{ - struct mly_softc *sc = (struct mly_softc *)dev->si_drv1; - struct mly_user_command *uc = (struct mly_user_command *)addr; - struct mly_user_health *uh = (struct mly_user_health *)addr; - - switch(cmd) { - case MLYIO_COMMAND: - return(mly_user_command(sc, uc)); - case MLYIO_HEALTH: - return(mly_user_health(sc, uh)); - default: - return(ENOIOCTL); - } -} - -/******************************************************************************** - * Execute a command passed in from userspace. - * - * The control structure contains the actual command for the controller, as well - * as the user-space data pointer and data size, and an optional sense buffer - * size/pointer. On completion, the data size is adjusted to the command - * residual, and the sense buffer size to the size of the returned sense data. - * - */ -static int -mly_user_command(struct mly_softc *sc, struct mly_user_command *uc) -{ - struct mly_command *mc; - int error; - - /* allocate a command */ - MLY_LOCK(sc); - if (mly_alloc_command(sc, &mc)) { - MLY_UNLOCK(sc); - return (ENOMEM); /* XXX Linux version will wait for a command */ - } - MLY_UNLOCK(sc); - - /* handle data size/direction */ - mc->mc_length = (uc->DataTransferLength >= 0) ? uc->DataTransferLength : -uc->DataTransferLength; - if (mc->mc_length > 0) { - if ((mc->mc_data = malloc(mc->mc_length, M_DEVBUF, M_NOWAIT)) == NULL) { - error = ENOMEM; - goto out; - } - } - if (uc->DataTransferLength > 0) { - mc->mc_flags |= MLY_CMD_DATAIN; - bzero(mc->mc_data, mc->mc_length); - } - if (uc->DataTransferLength < 0) { - mc->mc_flags |= MLY_CMD_DATAOUT; - if ((error = copyin(uc->DataTransferBuffer, mc->mc_data, mc->mc_length)) != 0) - goto out; - } - - /* copy the controller command */ - bcopy(&uc->CommandMailbox, mc->mc_packet, sizeof(uc->CommandMailbox)); - - /* clear command completion handler so that we get woken up */ - mc->mc_complete = NULL; - - /* execute the command */ - MLY_LOCK(sc); - if ((error = mly_start(mc)) != 0) { - MLY_UNLOCK(sc); - goto out; - } - while (!(mc->mc_flags & MLY_CMD_COMPLETE)) - mtx_sleep(mc, &sc->mly_lock, PRIBIO, "mlyioctl", 0); - MLY_UNLOCK(sc); - - /* return the data to userspace */ - if (uc->DataTransferLength > 0) - if ((error = copyout(mc->mc_data, uc->DataTransferBuffer, mc->mc_length)) != 0) - goto out; - - /* return the sense buffer to userspace */ - if ((uc->RequestSenseLength > 0) && (mc->mc_sense > 0)) { - if ((error = copyout(mc->mc_packet, uc->RequestSenseBuffer, - min(uc->RequestSenseLength, mc->mc_sense))) != 0) - goto out; - } - - /* return command results to userspace (caller will copy out) */ - uc->DataTransferLength = mc->mc_resid; - uc->RequestSenseLength = min(uc->RequestSenseLength, mc->mc_sense); - uc->CommandStatus = mc->mc_status; - error = 0; - - out: - if (mc->mc_data != NULL) - free(mc->mc_data, M_DEVBUF); - MLY_LOCK(sc); - mly_release_command(mc); - MLY_UNLOCK(sc); - return(error); -} - -/******************************************************************************** - * Return health status to userspace. If the health change index in the user - * structure does not match that currently exported by the controller, we - * return the current status immediately. Otherwise, we block until either - * interrupted or new status is delivered. - */ -static int -mly_user_health(struct mly_softc *sc, struct mly_user_health *uh) -{ - struct mly_health_status mh; - int error; - - /* fetch the current health status from userspace */ - if ((error = copyin(uh->HealthStatusBuffer, &mh, sizeof(mh))) != 0) - return(error); - - /* spin waiting for a status update */ - MLY_LOCK(sc); - error = EWOULDBLOCK; - while ((error != 0) && (sc->mly_event_change == mh.change_counter)) - error = mtx_sleep(&sc->mly_event_change, &sc->mly_lock, PRIBIO | PCATCH, - "mlyhealth", 0); - mh = sc->mly_mmbox->mmm_health.status; - MLY_UNLOCK(sc); - - /* copy the controller's health status buffer out */ - error = copyout(&mh, uh->HealthStatusBuffer, sizeof(mh)); - return(error); -} - -#ifdef MLY_DEBUG -static void -mly_timeout(void *arg) -{ - struct mly_softc *sc; - struct mly_command *mc; - int deadline; - - sc = arg; - MLY_ASSERT_LOCKED(sc); - deadline = time_second - MLY_CMD_TIMEOUT; - TAILQ_FOREACH(mc, &sc->mly_busy, mc_link) { - if ((mc->mc_timestamp < deadline)) { - device_printf(sc->mly_dev, - "COMMAND %p TIMEOUT AFTER %d SECONDS\n", mc, - (int)(time_second - mc->mc_timestamp)); - } - } - - callout_reset(&sc->mly_timeout, MLY_CMD_TIMEOUT * hz, mly_timeout, sc); -} -#endif diff --git a/sys/dev/mly/mly_tables.h b/sys/dev/mly/mly_tables.h deleted file mode 100644 --- a/sys/dev/mly/mly_tables.h +++ /dev/null @@ -1,325 +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. - * - * $FreeBSD$ - */ - -/* - * Lookup table for code-to-text translations. - */ -struct mly_code_lookup { - char *string; - u_int32_t code; -}; - -static char *mly_describe_code(struct mly_code_lookup *table, u_int32_t code); - -/******************************************************************************** - * Look up a text description of a numeric code and return a pointer to same. - */ -static char * -mly_describe_code(struct mly_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); -} - -#if 0 -static struct mly_code_lookup mly_table_bustype[] = { - {"SCSI", 0x00}, - {"FC-AL", 0x01}, - {"PCI", 0x03}, - {NULL, 0}, - {"unknown bus", 0} -}; -#endif - -static struct mly_code_lookup mly_table_controllertype[] = { -#if 0 /* not supported by this driver */ - {"DAC960E", 0x01}, /* EISA */ - {"DAC960M", 0x08}, /* MCA */ - {"DAC960PD", 0x10}, /* PCI Dual */ - {"DAC960PL", 0x11}, /* PCU low-cost */ - {"DAC960PDU", 0x12}, /* PD Ultra */ - {"DAC960PE", 0x13}, /* Peregrine low-cost */ - {"DAC960PG", 0x14}, /* Peregrine high-performance */ - {"DAC960PJ", 0x15}, /* Road Runner */ - {"DAC960PTL0", 0x16}, /* Jaguar */ - {"DAC960PR", 0x17}, /* Road Runner (again?) */ - {"DAC960PRL", 0x18}, /* Tomcat */ - {"DAC960PT", 0x19}, /* Road Runner (yet again?) */ - {"DAC1164P", 0x1a}, /* Little Apple */ - {"DAC960PTL1", 0x1b}, /* Jaguar+ */ -#endif - {"EXR2000P", 0x1c}, /* Big Apple */ - {"EXR3000P", 0x1d}, /* Fibre Apple */ - {"AcceleRAID 352", 0x1e}, /* Leopard */ - {"AcceleRAID 170", 0x1f}, /* Lynx */ - {"AcceleRAID 160", 0x20}, /* Bobcat */ - {NULL, 0}, - {"unknown adapter", 0} -}; - -static struct mly_code_lookup mly_table_oemname[] = { - {"Mylex", MLY_OEM_MYLEX}, - {"IBM", MLY_OEM_IBM}, - {"Hewlett-Packard", MLY_OEM_HP}, - {"DEC/Compaq", MLY_OEM_DEC}, - {"Siemens", MLY_OEM_SIEMENS}, - {"Intel", MLY_OEM_INTEL}, - {NULL, 0}, - {"unknown OEM", 0} -}; - -static struct mly_code_lookup mly_table_memorytype[] = { - {"DRAM", 0x01}, - {"EDRAM", 0x02}, - {"EDO RAM", 0x03}, - {"SDRAM", 0x04}, - {NULL, 0}, - {"unknown memory", 0} -}; - -static struct mly_code_lookup mly_table_cputype[] = { - {"i960CA", 0x01}, - {"i960RD", 0x02}, - {"i960RN", 0x03}, - {"i960RP", 0x04}, - {"NorthBay(?)", 0x05}, - {"StrongArm", 0x06}, - {"i960RM", 0x07}, - {NULL, 0}, - {"unknown CPU", 0} -}; - -/* - * This table is directly derived from the corresponding table in the - * Linux driver, and uses a derivative encoding for simplicity's sake. - * - * The first character of the string determines the format of the message. - * - * p "physical device : " (physical device status) - * s "physical device : " (scsi message or error) - * " sense key asc ascq " - * " info csi " - * l "logical drive : " (logical device status) - * m "logical drive : " (logical device message) - * - * Messages which are typically suppressed have the first character capitalised. - * These messages will only be printed if bootverbose is set. - * - * The second character in the string indicates an action to be taken as a - * result of the event. - * - * r rescan the device for possible state change - * - */ -static struct mly_code_lookup mly_table_event[] = { - /* physical device events (0x0000 - 0x007f) */ - {"pr online", 0x0001}, - {"pr standby", 0x0002}, - {"p automatic rebuild started", 0x0005}, - {"p manual rebuild started", 0x0006}, - {"pr rebuild completed", 0x0007}, - {"pr rebuild cancelled", 0x0008}, - {"pr rebuild failed for unknown reasons", 0x0009}, - {"pr rebuild failed due to new physical device", 0x000a}, - {"pr rebuild failed due to logical drive failure", 0x000b}, - {"sr offline", 0x000c}, - {"pr found", 0x000d}, - {"pr gone", 0x000e}, - {"p unconfigured", 0x000f}, - {"p expand capacity started", 0x0010}, - {"pr expand capacity completed", 0x0011}, - {"pr expand capacity failed", 0x0012}, - {"p parity error", 0x0016}, - {"p soft error", 0x0017}, - {"p miscellaneous error", 0x0018}, - {"p reset", 0x0019}, - {"p active spare found", 0x001a}, - {"p warm spare found", 0x001b}, - {"s sense data received", 0x001c}, - {"p initialization started", 0x001d}, - {"pr initialization completed", 0x001e}, - {"pr initialization failed", 0x001f}, - {"pr initialization cancelled", 0x0020}, - {"P write recovery failed", 0x0021}, - {"p scsi bus reset failed", 0x0022}, - {"p double check condition", 0x0023}, - {"p device cannot be accessed", 0x0024}, - {"p gross error on scsi processor", 0x0025}, - {"p bad tag from device", 0x0026}, - {"p command timeout", 0x0027}, - {"pr system reset", 0x0028}, - {"p busy status or parity error", 0x0029}, - {"pr host set device to failed state", 0x002a}, - {"pr selection timeout", 0x002b}, - {"p scsi bus phase error", 0x002c}, - {"pr device returned unknown status", 0x002d}, - {"pr device not ready", 0x002e}, - {"p device not found at startup", 0x002f}, - {"p COD write operation failed", 0x0030}, - {"p BDT write operation failed", 0x0031}, - {"p missing at startup", 0x0039}, - {"p start rebuild failed due to physical drive too small", 0x003a}, - /* logical device events (0x0080 - 0x00ff) */ - {"m consistency check started", 0x0080}, - {"mr consistency check completed", 0x0081}, - {"mr consistency check cancelled", 0x0082}, - {"mr consistency check completed with errors", 0x0083}, - {"mr consistency check failed due to logical drive failure", 0x0084}, - {"mr consistency check failed due to physical device failure", 0x0085}, - {"lr offline", 0x0086}, - {"lr critical", 0x0087}, - {"lr online", 0x0088}, - {"m automatic rebuild started", 0x0089}, - {"m manual rebuild started", 0x008a}, - {"mr rebuild completed", 0x008b}, - {"mr rebuild cancelled", 0x008c}, - {"mr rebuild failed for unknown reasons", 0x008d}, - {"mr rebuild failed due to new physical device", 0x008e}, - {"mr rebuild failed due to logical drive failure", 0x008f}, - {"l initialization started", 0x0090}, - {"lr initialization completed", 0x0091}, - {"lr initialization cancelled", 0x0092}, - {"lr initialization failed", 0x0093}, - {"lr found", 0x0094}, - {"lr gone", 0x0095}, - {"l expand capacity started", 0x0096}, - {"lr expand capacity completed", 0x0097}, - {"lr expand capacity failed", 0x0098}, - {"l bad block found", 0x0099}, - {"lr size changed", 0x009a}, - {"lr type changed", 0x009b}, - {"l bad data block found", 0x009c}, - {"l read of data block in bdt", 0x009e}, - {"l write back data for disk block lost", 0x009f}, - /* enclosure management events (0x0100 - 0x017f) */ - {"e enclosure %d fan %d failed", 0x0140}, - {"e enclosure %d fan %d ok", 0x0141}, - {"e enclosure %d fan %d not present", 0x0142}, - {"e enclosure %d power supply %d failed", 0x0143}, - {"e enclosure %d power supply %d ok", 0x0144}, - {"e enclosure %d power supply %d not present", 0x0145}, - {"e enclosure %d temperature sensor %d failed", 0x0146}, - {"e enclosure %d temperature sensor %d critical", 0x0147}, - {"e enclosure %d temperature sensor %d ok", 0x0148}, - {"e enclosure %d temperature sensor %d not present", 0x0149}, - {"e enclosure %d unit %d access critical", 0x014a}, - {"e enclosure %d unit %d access ok", 0x014b}, - {"e enclosure %d unit %d access offline", 0x014c}, - /* controller events (0x0180 - 0x01ff) */ - {"c cache write back error", 0x0181}, - {"c battery backup unit found", 0x0188}, - {"c battery backup unit charge level low", 0x0189}, - {"c battery backup unit charge level ok", 0x018a}, - {"c installation aborted", 0x0193}, - {"c mirror race recovery in progress", 0x0195}, - {"c mirror race on critical drive", 0x0196}, - {"c memory soft ecc error", 0x019e}, - {"c memory hard ecc error", 0x019f}, - {"c battery backup unit failed", 0x01a2}, - {NULL, 0}, - {"? unknown event code", 0} -}; - -/* - * Values here must be 16 characters or less, as they are packed into - * the 'product' field in the SCSI inquiry data. - */ -static struct mly_code_lookup mly_table_device_state[] = { - {"offline", MLY_DEVICE_STATE_OFFLINE}, - {"unconfigured", MLY_DEVICE_STATE_UNCONFIGURED}, - {"online", MLY_DEVICE_STATE_ONLINE}, - {"critical", MLY_DEVICE_STATE_CRITICAL}, - {"writeonly", MLY_DEVICE_STATE_WRITEONLY}, - {"standby", MLY_DEVICE_STATE_STANDBY}, - {"missing", MLY_DEVICE_STATE_MISSING}, - {NULL, 0}, - {"unknown state", 0} -}; - -/* - * Values here must be 8 characters or less, as they are packed into - * the 'vendor' field in the SCSI inquiry data. - */ -static struct mly_code_lookup mly_table_device_type[] = { - {"RAID 0", MLY_DEVICE_TYPE_RAID0}, - {"RAID 1", MLY_DEVICE_TYPE_RAID1}, - {"RAID 3", MLY_DEVICE_TYPE_RAID3}, /* right asymmetric parity */ - {"RAID 5", MLY_DEVICE_TYPE_RAID5}, /* right asymmetric parity */ - {"RAID 6", MLY_DEVICE_TYPE_RAID6}, /* Mylex RAID 6 */ - {"RAID 7", MLY_DEVICE_TYPE_RAID7}, /* JBOD */ - {"SPAN", MLY_DEVICE_TYPE_NEWSPAN}, /* New Mylex SPAN */ - {"RAID 3", MLY_DEVICE_TYPE_RAID3F}, /* fixed parity */ - {"RAID 3", MLY_DEVICE_TYPE_RAID3L}, /* left symmetric parity */ - {"SPAN", MLY_DEVICE_TYPE_SPAN}, /* current spanning implementation */ - {"RAID 5", MLY_DEVICE_TYPE_RAID5L}, /* left symmetric parity */ - {"RAID E", MLY_DEVICE_TYPE_RAIDE}, /* concatenation */ - {"PHYSICAL", MLY_DEVICE_TYPE_PHYSICAL}, /* physical device */ - {NULL, 0}, - {"UNKNOWN", 0} -}; - -#if 0 -static struct mly_code_lookup mly_table_stripe_size[] = { - {"NONE", MLY_STRIPE_ZERO}, - {"512B", MLY_STRIPE_512b}, - {"1k", MLY_STRIPE_1k}, - {"2k", MLY_STRIPE_2k}, - {"4k", MLY_STRIPE_4k}, - {"8k", MLY_STRIPE_8k}, - {"16k", MLY_STRIPE_16k}, - {"32k", MLY_STRIPE_32k}, - {"64k", MLY_STRIPE_64k}, - {"128k", MLY_STRIPE_128k}, - {"256k", MLY_STRIPE_256k}, - {"512k", MLY_STRIPE_512k}, - {"1M", MLY_STRIPE_1m}, - {NULL, 0}, - {"unknown", 0} -}; - -static struct mly_code_lookup mly_table_cacheline_size[] = { - {"NONE", MLY_CACHELINE_ZERO}, - {"512B", MLY_CACHELINE_512b}, - {"1k", MLY_CACHELINE_1k}, - {"2k", MLY_CACHELINE_2k}, - {"4k", MLY_CACHELINE_4k}, - {"8k", MLY_CACHELINE_8k}, - {"16k", MLY_CACHELINE_16k}, - {"32k", MLY_CACHELINE_32k}, - {"64k", MLY_CACHELINE_64k}, - {NULL, 0}, - {"unknown", 0} -}; -#endif diff --git a/sys/dev/mly/mlyio.h b/sys/dev/mly/mlyio.h deleted file mode 100644 --- a/sys/dev/mly/mlyio.h +++ /dev/null @@ -1,72 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2001 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. - * - * $FreeBSD$ - */ - -/******************************************************************************** - * Control structures exchanged through the GAM interface with userland - * management tools. - * - * The member naming here is consistent with the Linux driver, with which this - * interface is basically compatible. - */ -struct mly_user_command -{ - unsigned char ControllerNumber; - union mly_command_packet CommandMailbox; - int DataTransferLength; - int RequestSenseLength; - void *DataTransferBuffer; - void *RequestSenseBuffer; - int CommandStatus; /* not in the Linux structure */ -}; - -#define MLYIO_COMMAND _IOWR('M', 200, struct mly_user_command) - -struct mly_user_health -{ - unsigned char ControllerNumber; - void *HealthStatusBuffer; -}; - -#define MLYIO_HEALTH _IOW('M', 201, struct mly_user_health) - -/* - * Command queue statistics - */ - -#define MLYQ_FREE 0 -#define MLYQ_BUSY 1 -#define MLYQ_COMPLETE 2 -#define MLYQ_COUNT 3 - -struct mly_qstat -{ - u_int32_t q_length; - u_int32_t q_max; -}; diff --git a/sys/dev/mly/mlyreg.h b/sys/dev/mly/mlyreg.h deleted file mode 100644 --- a/sys/dev/mly/mlyreg.h +++ /dev/null @@ -1,1272 +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. - * - * $FreeBSD$ - */ - -/* - * Section numbers in this document refer to the Mylex "Firmware Software Interface" - * document ('FSI'), revision 0.11 04/11/00 unless otherwise qualified. - * - * Reference is made to the Mylex "Programming Guide for 6.x Controllers" document - * ('PG6'), document #771242 revision 0.02, 04/11/00 - * - * Note that fields marked N/A are not supported by the PCI controllers, but are - * defined here to hold place in datastructures that are shared with the SCSI - * controllers. Items not relevant to PCI controllers are not described here. - * - * Ordering of items in this file is a little odd due to the constraints of - * nested declarations. - */ - -/* - * 2.1 (Scatter Gather List Format) - */ -struct mly_sg_entry { - u_int64_t physaddr; - u_int64_t length; -} __packed; - -/* - * 5.2 System Device Access - * - * This is corroborated by the layout of the MDACIOCTL_GETCONTROLLERINFO data - * in 21.8 - */ -#define MLY_MAX_CHANNELS 6 -#define MLY_MAX_TARGETS 16 -#define MLY_MAX_LUNS 1 - -/* - * 8.1 Different Device States - */ -#define MLY_DEVICE_STATE_OFFLINE 0x08 /* DEAD/OFFLINE */ -#define MLY_DEVICE_STATE_UNCONFIGURED 0x00 -#define MLY_DEVICE_STATE_ONLINE 0x01 -#define MLY_DEVICE_STATE_CRITICAL 0x09 -#define MLY_DEVICE_STATE_WRITEONLY 0x03 -#define MLY_DEVICE_STATE_STANDBY 0x21 -#define MLY_DEVICE_STATE_MISSING 0x04 /* or-ed with (ONLINE or WRITEONLY or STANDBY) */ - -/* - * 8.2 Device Type Field definitions - */ -#define MLY_DEVICE_TYPE_RAID0 0x0 /* RAID 0 */ -#define MLY_DEVICE_TYPE_RAID1 0x1 /* RAID 1 */ -#define MLY_DEVICE_TYPE_RAID3 0x3 /* RAID 3 right asymmetric parity */ -#define MLY_DEVICE_TYPE_RAID5 0x5 /* RAID 5 right asymmetric parity */ -#define MLY_DEVICE_TYPE_RAID6 0x6 /* RAID 6 (Mylex RAID 6) */ -#define MLY_DEVICE_TYPE_RAID7 0x7 /* RAID 7 (JBOD) */ -#define MLY_DEVICE_TYPE_NEWSPAN 0x8 /* New Mylex SPAN */ -#define MLY_DEVICE_TYPE_RAID3F 0x9 /* RAID 3 fixed parity */ -#define MLY_DEVICE_TYPE_RAID3L 0xb /* RAID 3 left symmetric parity */ -#define MLY_DEVICE_TYPE_SPAN 0xc /* current spanning implementation */ -#define MLY_DEVICE_TYPE_RAID5L 0xd /* RAID 5 left symmetric parity */ -#define MLY_DEVICE_TYPE_RAIDE 0xe /* RAID E (concatenation) */ -#define MLY_DEVICE_TYPE_PHYSICAL 0xf /* physical device */ - -/* - * 8.3 Stripe Size - */ -#define MLY_STRIPE_ZERO 0x0 /* no stripe (RAID 1, RAID 7, etc) */ -#define MLY_STRIPE_512b 0x1 -#define MLY_STRIPE_1k 0x2 -#define MLY_STRIPE_2k 0x3 -#define MLY_STRIPE_4k 0x4 -#define MLY_STRIPE_8k 0x5 -#define MLY_STRIPE_16k 0x6 -#define MLY_STRIPE_32k 0x7 -#define MLY_STRIPE_64k 0x8 -#define MLY_STRIPE_128k 0x9 -#define MLY_STRIPE_256k 0xa -#define MLY_STRIPE_512k 0xb -#define MLY_STRIPE_1m 0xc - -/* - * 8.4 Cacheline Size - */ -#define MLY_CACHELINE_ZERO 0x0 /* caching cannot be enabled */ -#define MLY_CACHELINE_512b 0x1 -#define MLY_CACHELINE_1k 0x2 -#define MLY_CACHELINE_2k 0x3 -#define MLY_CACHELINE_4k 0x4 -#define MLY_CACHELINE_8k 0x5 -#define MLY_CACHELINE_16k 0x6 -#define MLY_CACHELINE_32k 0x7 -#define MLY_CACHELINE_64k 0x8 - -/* - * 8.5 Read/Write control - */ -#define MLY_RWCtl_INITTED (1<<7) /* if set, the logical device is initialised */ - /* write control */ -#define MLY_RWCtl_WCD (0) /* write cache disabled */ -#define MLY_RWCtl_WDISABLE (1<<3) /* writing disabled */ -#define MLY_RWCtl_WCE (2<<3) /* write cache enabled */ -#define MLY_RWCtl_IWCE (3<<3) /* intelligent write cache enabled */ - /* read control */ -#define MLY_RWCtl_RCD (0) /* read cache is disabled */ -#define MLY_RWCtl_RCE (1) /* read cache enabled */ -#define MLY_RWCtl_RAHEAD (2) /* readahead enabled */ -#define MLY_RWCtl_IRAHEAD (3) /* intelligent readahead enabled */ - -/* - * 9.0 LUN Map Format - */ -struct mly_lun_map { - u_int8_t res1:4; - u_int8_t host_port_mapped:1; /* this system drive visible to host on this controller/port combination */ - u_int8_t tid_valid:1; /* target ID valid */ - u_int8_t hid_valid:1; /* host ID valid */ - u_int8_t lun_valid:1; /* LUN valid */ - u_int8_t res2; - u_int8_t lun; /* LUN */ - u_int8_t tid; /* TID */ - u_int8_t hid[32]; /* HID (one bit for each host) */ -} __packed; - -/* - * 10.1 Controller Parameters - */ -struct mly_param_controller { - u_int8_t rdahen:1; /* N/A */ - u_int8_t bilodly:1; /* N/A */ - u_int8_t fua_disable:1; - u_int8_t reass1s:1; /* N/A */ - u_int8_t truvrfy:1; /* N/A */ - u_int8_t dwtvrfy:1; /* N/A */ - u_int8_t background_initialisation:1; - u_int8_t clustering:1; /* N/A */ - - u_int8_t bios_disable:1; - u_int8_t boot_from_cdrom:1; - u_int8_t drive_coercion:1; - u_int8_t write_same_disable:1; - u_int8_t hba_mode:1; /* N/A */ - u_int8_t bios_geometry:2; -#define MLY_BIOSGEOM_2G 0x0 -#define MLY_BIOSGEOM_8G 0x1 - u_int8_t res1:1; /* N/A */ - - u_int8_t res2[2]; /* N/A */ - - u_int8_t v_dec:1; - u_int8_t safte:1; /* N/A */ - u_int8_t ses:1; /* N/A */ - u_int8_t res3:2; /* N/A */ - u_int8_t v_arm:1; - u_int8_t v_ofm:1; - u_int8_t res4:1; /* N/A */ - - u_int8_t rebuild_check_rate; - u_int8_t cache_line_size; /* see 8.4 */ - u_int8_t oem_code; -#define MLY_OEM_MYLEX 0x00 -#define MLY_OEM_IBM 0x08 -#define MLY_OEM_HP 0x0a -#define MLY_OEM_DEC 0x0c -#define MLY_OEM_SIEMENS 0x10 -#define MLY_OEM_INTEL 0x12 - u_int8_t spinup_mode; -#define MLY_SPIN_AUTO 0 -#define MLY_SPIN_PWRSPIN 1 -#define MLY_SPIN_WSSUSPIN 2 - u_int8_t spinup_devices; - u_int8_t spinup_interval; - u_int8_t spinup_wait_time; - - u_int8_t res5:3; /* N/A */ - u_int8_t vutursns:1; /* N/A */ - u_int8_t dccfil:1; /* N/A */ - u_int8_t nopause:1; /* N/A */ - u_int8_t disqfull:1; /* N/A */ - u_int8_t disbusy:1; /* N/A */ - - u_int8_t res6:2; /* N/A */ - u_int8_t failover_node_name; /* N/A */ - u_int8_t res7:1; /* N/A */ - u_int8_t ftopo:3; /* N/A */ - u_int8_t disable_ups:1; /* N/A */ - - u_int8_t res8:1; /* N/A */ - u_int8_t propagate_reset:1; /* N/A */ - u_int8_t nonstd_mp_reset:1; /* N/A */ - u_int8_t res9:5; /* N/A */ - - u_int8_t res10; /* N/A */ - u_int8_t serial_port_baud_rate; /* N/A */ - u_int8_t serial_port_control; /* N/A */ - u_int8_t change_stripe_ok_developer_flag_only; /* N/A */ - - u_int8_t small_large_host_transfers:2; /* N/A */ - u_int8_t frame_control:2; /* N/A */ - u_int8_t pci_latency_control:2; /* N/A */ - u_int8_t treat_lip_as_reset:1; /* N/A */ - u_int8_t res11:1; /* N/A */ - - u_int8_t ms_autorest:1; /* N/A */ - u_int8_t res12:7; /* N/A */ - - u_int8_t ms_aa_fsim:1; /* N/A */ - u_int8_t ms_aa_ccach:1; /* N/A */ - u_int8_t ms_aa_fault_signals:1; /* N/A */ - u_int8_t ms_aa_c4_faults:1; /* N/A */ - u_int8_t ms_aa_host_reset_delay_mask:4; /* N/A */ - - u_int8_t ms_flg_simplex_no_rstcom:1; /* N/A */ - u_int8_t res13:7; /* N/A */ - - u_int8_t res14; /* N/A */ - u_int8_t hardloopid[2][2]; /* N/A */ - u_int8_t ctrlname[2][16+1]; /* N/A */ - u_int8_t initiator_id; - u_int8_t startup_option; -#define MLY_STARTUP_IF_NO_CHANGE 0x0 -#define MLY_STARTUP_IF_NO_LUN_CHANGE 0x1 -#define MLY_STARTUP_IF_NO_LUN_OFFLINE 0x2 -#define MLY_STARTUP_IF_LUN0_NO_CHANGE 0x3 -#define MLY_STARTUP_IF_LUN0_NOT_OFFLINE 0x4 -#define MLY_STARTUP_ALWAYS 0x5 - - u_int8_t res15[62]; -} __packed; - -/* - * 10.2 Physical Device Parameters - */ -struct mly_param_physical_device { - u_int16_t tags; - u_int16_t speed; - u_int8_t width; - u_int8_t combing:1; - u_int8_t res1:7; - u_int8_t res2[3]; -} __packed; - -/* - * 10.3 Logical Device Parameters - */ -struct mly_param_logical_device { - u_int8_t type; /* see 8.2 */ - u_int8_t state; /* see 8.1 */ - u_int16_t raid_device; - u_int8_t res1; - u_int8_t bios_geometry; /* BIOS control word? */ - u_int8_t stripe_size; /* see 8.3 */ - u_int8_t read_write_control; /* see 8.5 */ - u_int8_t res2[8]; -} __packed; - -/* - * 12.3 Health Status Buffer - * - * Pad to 128 bytes. - */ -struct mly_health_status { - u_int32_t uptime_us; /* N/A */ - u_int32_t uptime_ms; /* N/A */ - u_int32_t realtime; /* N/A */ - u_int32_t res1; /* N/A */ - u_int32_t change_counter; - u_int32_t res2; /* N/A */ - u_int32_t debug_message_index; /* N/A */ - u_int32_t bios_message_index; /* N/A */ - u_int32_t trace_page; /* N/A */ - u_int32_t profiler_page; /* N/A */ - u_int32_t next_event; - u_int8_t res3[4 + 16 + 64]; /* N/A */ -} __packed; - -/* - * 14.2 Timeout Bit Format - */ -struct mly_timeout { - u_int8_t value:6; - u_int8_t scale:2; -#define MLY_TIMEOUT_SECONDS 0x0 -#define MLY_TIMEOUT_MINUTES 0x1 -#define MLY_TIMEOUT_HOURS 0x2 -} __packed; - -/* - * 14.3 Operation Device - */ -#define MLY_OPDEVICE_PHYSICAL_DEVICE 0x0 -#define MLY_OPDEVICE_RAID_DEVICE 0x1 -#define MLY_OPDEVICE_PHYSICAL_CHANNEL 0x2 -#define MLY_OPDEVICE_RAID_CHANNEL 0x3 -#define MLY_OPDEVICE_PHYSICAL_CONTROLLER 0x4 -#define MLY_OPDEVICE_RAID_CONTROLLER 0x5 -#define MLY_OPDEVICE_CONFIGURATION_GROUP 0x10 - -/* - * 14.4 Status Bit Format - * - * AKA Status Mailbox Format - * - * XXX format conflict between FSI and PG6 over the ordering of the - * status and sense length fields. - */ -struct mly_status { - u_int16_t command_id; - u_int8_t status; - u_int8_t sense_length; - int32_t residue; -} __packed; - -/* - * 14.5 Command Control Bit (CCB) format - * - * This byte is unfortunately named. - */ -struct mly_command_control { - u_int8_t force_unit_access:1; - u_int8_t disable_page_out:1; - u_int8_t res1:1; - u_int8_t extended_sg_table:1; - u_int8_t data_direction:1; -#define MLY_CCB_WRITE 1 -#define MLY_CCB_READ 0 - u_int8_t res2:1; - u_int8_t no_auto_sense:1; - u_int8_t disable_disconnect:1; -} __packed; - -/* - * 15.0 Commands - * - * We use the command names as given by Mylex - */ -#define MDACMD_MEMCOPY 0x1 /* memory to memory copy */ -#define MDACMD_SCSIPT 0x2 /* SCSI passthrough (small command) */ -#define MDACMD_SCSILCPT 0x3 /* SCSI passthrough (large command) */ -#define MDACMD_SCSI 0x4 /* SCSI command for logical/phyiscal device (small command) */ -#define MDACMD_SCSILC 0x5 /* SCSI command for logical/phyiscal device (large command) */ -#define MDACMD_IOCTL 0x20 /* Management command */ -#define MDACMD_IOCTLCHECK 0x23 /* Validate management command (not implemented) */ - -/* - * 16.0 IOCTL command - * - * We use the IOCTL names as given by Mylex - * Note that only ioctls supported by the PCI controller family are listed - */ -#define MDACIOCTL_GETCONTROLLERINFO 0x1 -#define MDACIOCTL_GETLOGDEVINFOVALID 0x3 -#define MDACIOCTL_GETPHYSDEVINFOVALID 0x5 -#define MDACIOCTL_GETCONTROLLERSTATISTICS 0xb -#define MDACIOCTL_GETLOGDEVSTATISTICS 0xd -#define MDACIOCTL_GETPHYSDEVSTATISTICS 0xf -#define MDACIOCTL_GETHEALTHSTATUS 0x11 -#define MDACIOCTL_GETEVENT 0x15 -/* flash update */ -#define MDACIOCTL_STOREIMAGE 0x2c -#define MDACIOCTL_READIMAGE 0x2d -#define MDACIOCTL_FLASHIMAGES 0x2e -/* battery backup unit */ -#define MDACIOCTL_GET_SUBSYSTEM_DATA 0x70 -#define MDACIOCTL_SET_SUBSYSTEM_DATA 0x71 -/* non-data commands */ -#define MDACIOCTL_STARTDISOCVERY 0x81 -#define MDACIOCTL_SETRAIDDEVSTATE 0x82 -#define MDACIOCTL_INITPHYSDEVSTART 0x84 -#define MDACIOCTL_INITPHYSDEVSTOP 0x85 -#define MDACIOCTL_INITRAIDDEVSTART 0x86 -#define MDACIOCTL_INITRAIDDEVSTOP 0x87 -#define MDACIOCTL_REBUILDRAIDDEVSTART 0x88 -#define MDACIOCTL_REBUILDRAIDDEVSTOP 0x89 -#define MDACIOCTL_MAKECONSISTENTDATASTART 0x8a -#define MDACIOCTL_MAKECONSISTENTDATASTOP 0x8b -#define MDACIOCTL_CONSISTENCYCHECKSTART 0x8c -#define MDACIOCTL_CONSISTENCYCHECKSTOP 0x8d -#define MDACIOCTL_SETMEMORYMAILBOX 0x8e -#define MDACIOCTL_RESETDEVICE 0x90 -#define MDACIOCTL_FLUSHDEVICEDATA 0x91 -#define MDACIOCTL_PAUSEDEVICE 0x92 -#define MDACIOCTL_UNPAUSEDEVICE 0x93 -#define MDACIOCTL_LOCATEDEVICE 0x94 -#define MDACIOCTL_SETMASTERSLAVEMODE 0x95 -#define MDACIOCTL_SETREALTIMECLOCK 0xac -/* RAID configuration */ -#define MDACIOCTL_CREATENEWCONF 0xc0 -#define MDACIOCTL_DELETERAIDDEV 0xc1 -#define MDACIOCTL_REPLACEINTERNALDEV 0xc2 -#define MDACIOCTL_RENAMERAIDDEV 0xc3 -#define MDACIOCTL_ADDNEWCONF 0xc4 -#define MDACIOCTL_XLATEPHYSDEVTORAIDDEV 0xc5 -#define MDACIOCTL_MORE 0xc6 -#define MDACIOCTL_SETPHYSDEVPARAMETER 0xc8 -#define MDACIOCTL_GETPHYSDEVPARAMETER 0xc9 -#define MDACIOCTL_CLEARCONF 0xca -#define MDACIOCTL_GETDEVCONFINFO 0xcb -#define MDACIOCTL_GETGROUPCONFINFO 0xcc -#define MDACIOCTL_GETFREESPACELIST 0xcd -#define MDACIOCTL_GETLOGDEVPARAMETER 0xce -#define MDACIOCTL_SETLOGDEVPARAMETER 0xcf -#define MDACIOCTL_GETCONTROLLERPARAMETER 0xd0 -#define MDACIOCTL_SETCONTRLLERPARAMETER 0xd1 -#define MDACIOCTL_CLEARCONFSUSPMODE 0xd2 -#define MDACIOCTL_GETBDT_FOR_SYSDRIVE 0xe0 - -/* - * 17.1.4 Data Transfer Memory Address Without SG List - */ -struct mly_short_transfer { - struct mly_sg_entry sg[2]; -} __packed; - -/* - * 17.1.5 Data Transfer Memory Address With SG List - * - * Note that only the first s/g table is currently used. - */ -struct mly_sg_transfer { - u_int16_t entries[3]; - u_int16_t res1; - u_int64_t table_physaddr[3]; -} __packed; - -/* - * 17.1.3 Data Transfer Memory Address Format - */ -union mly_command_transfer { - struct mly_short_transfer direct; - struct mly_sg_transfer indirect; -}; - -/* - * 21.1 MDACIOCTL_SETREALTIMECLOCK - * 21.7 MDACIOCTL_GETHEALTHSTATUS - * 21.8 MDACIOCTL_GETCONTROLLERINFO - * 21.9 MDACIOCTL_GETLOGDEVINFOVALID - * 21.10 MDACIOCTL_GETPHYSDEVINFOVALID - * 21.11 MDACIOCTL_GETPHYSDEVSTATISTICS - * 21.12 MDACIOCTL_GETLOGDEVSTATISTICS - * 21.13 MDACIOCTL_GETCONTROLLERSTATISTICS - * 21.27 MDACIOCTL_GETBDT_FOR_SYSDRIVE - * 23.4 MDACIOCTL_CREATENEWCONF - * 23.5 MDACIOCTL_ADDNEWCONF - * 23.8 MDACIOCTL_GETDEVCONFINFO - * 23.9 MDACIOCTL_GETFREESPACELIST - * 24.1 MDACIOCTL_MORE - * 25.1 MDACIOCTL_GETPHYSDEVPARAMETER - * 25.2 MDACIOCTL_SETPHYSDEVPARAMETER - * 25.3 MDACIOCTL_GETLOGDEVPARAMETER - * 25.4 MDACIOCTL_SETLOGDEVPARAMETER - * 25.5 MDACIOCTL_GETCONTROLLERPARAMETER - * 25.6 MDACIOCTL_SETCONTROLLERPARAMETER - * - * These commands just transfer data - */ -struct mly_ioctl_param_data { - u_int8_t param[10]; - union mly_command_transfer transfer; -} __packed; - -/* - * 21.2 MDACIOCTL_SETMEMORYMAILBOX - */ -struct mly_ioctl_param_setmemorymailbox { - u_int8_t health_buffer_size; - u_int8_t res1; - u_int64_t health_buffer_physaddr; - u_int64_t command_mailbox_physaddr; - u_int64_t status_mailbox_physaddr; - u_int64_t res2[2]; -} __packed; - -/* - * 21.8.2 MDACIOCTL_GETCONTROLLERINFO: Data Format - */ -struct mly_ioctl_getcontrollerinfo { - u_int8_t res1; /* N/A */ - u_int8_t interface_type; - u_int8_t controller_type; - u_int8_t res2; /* N/A */ - u_int16_t interface_speed; - u_int8_t interface_width; - u_int8_t res3[9]; /* N/A */ - char interface_name[16]; - char controller_name[16]; - u_int8_t res4[16]; /* N/A */ - /* firmware release information */ - u_int8_t fw_major; - u_int8_t fw_minor; - u_int8_t fw_turn; - u_int8_t fw_build; - u_int8_t fw_day; - u_int8_t fw_month; - u_int8_t fw_century; - u_int8_t fw_year; - /* hardware release information */ - u_int8_t hw_revision; /* N/A */ - u_int8_t res5[3]; /* N/A */ - u_int8_t hw_release_day; /* N/A */ - u_int8_t hw_release_month; /* N/A */ - u_int8_t hw_release_century; /* N/A */ - u_int8_t hw_release_year; /* N/A */ - /* hardware manufacturing information */ - u_int8_t batch_number; /* N/A */ - u_int8_t res6; /* N/A */ - u_int8_t plant_number; - u_int8_t res7; - u_int8_t hw_manuf_day; - u_int8_t hw_manuf_month; - u_int8_t hw_manuf_century; - u_int8_t hw_manuf_year; - u_int8_t max_pdd_per_xldd; - u_int8_t max_ildd_per_xldd; - u_int16_t nvram_size; - u_int8_t max_number_of_xld; /* N/A */ - u_int8_t res8[3]; /* N/A */ - /* unique information per controller */ - char serial_number[16]; - u_int8_t res9[16]; /* N/A */ - /* vendor information */ - u_int8_t res10[3]; /* N/A */ - u_int8_t oem_information; - char vendor_name[16]; /* N/A */ - /* other physical/controller/operation information */ - u_int8_t bbu_present:1; - u_int8_t active_clustering:1; - u_int8_t res11:6; /* N/A */ - u_int8_t res12[3]; /* N/A */ - /* physical device scan information */ - u_int8_t physical_scan_active:1; - u_int8_t res13:7; /* N/A */ - u_int8_t physical_scan_channel; - u_int8_t physical_scan_target; - u_int8_t physical_scan_lun; - /* maximum command data transfer size */ - u_int16_t maximum_block_count; - u_int16_t maximum_sg_entries; - /* logical/physical device counts */ - u_int16_t logical_devices_present; - u_int16_t logical_devices_critical; - u_int16_t logical_devices_offline; - u_int16_t physical_devices_present; - u_int16_t physical_disks_present; - u_int16_t physical_disks_critical; /* N/A */ - u_int16_t physical_disks_offline; - u_int16_t maximum_parallel_commands; - /* channel and target ID information */ - u_int8_t physical_channels_present; - u_int8_t virtual_channels_present; - u_int8_t physical_channels_possible; - u_int8_t virtual_channels_possible; - u_int8_t maximum_targets_possible[16]; /* N/A (6 and up) */ - u_int8_t res14[12]; /* N/A */ - /* memory/cache information */ - u_int16_t memory_size; - u_int16_t cache_size; - u_int32_t valid_cache_size; /* N/A */ - u_int32_t dirty_cache_size; /* N/A */ - u_int16_t memory_speed; - u_int8_t memory_width; - u_int8_t memory_type:5; - u_int8_t res15:1; /* N/A */ - u_int8_t memory_parity:1; - u_int8_t memory_ecc:1; - char memory_information[16]; /* N/A */ - /* execution memory information */ - u_int16_t exmemory_size; - u_int16_t l2cache_size; /* N/A */ - u_int8_t res16[8]; /* N/A */ - u_int16_t exmemory_speed; - u_int8_t exmemory_width; - u_int8_t exmemory_type:5; - u_int8_t res17:1; /* N/A */ - u_int8_t exmemory_parity:1; - u_int8_t exmemory_ecc:1; - char exmemory_name[16]; /* N/A */ - /* CPU information */ - struct { - u_int16_t speed; - u_int8_t type; - u_int8_t number; - u_int8_t res1[12]; /* N/A */ - char name[16]; /* N/A */ - } cpu[2] __packed; - /* debugging/profiling/command time tracing information */ - u_int16_t profiling_page; /* N/A */ - u_int16_t profiling_programs; /* N/A */ - u_int16_t time_trace_page; /* N/A */ - u_int16_t time_trace_programs; /* N/A */ - u_int8_t res18[8]; /* N/A */ - /* error counters on physical devices */ - u_int16_t physical_device_bus_resets; /* N/A */ - u_int16_t physical_device_parity_errors; /* N/A */ - u_int16_t physical_device_soft_errors; /* N/A */ - u_int16_t physical_device_commands_failed; /* N/A */ - u_int16_t physical_device_miscellaneous_errors; /* N/A */ - u_int16_t physical_device_command_timeouts; /* N/A */ - u_int16_t physical_device_selection_timeouts; /* N/A */ - u_int16_t physical_device_retries; /* N/A */ - u_int16_t physical_device_aborts; /* N/A */ - u_int16_t physical_device_host_command_aborts; /* N/A */ - u_int16_t physical_device_PFAs_detected; /* N/A */ - u_int16_t physical_device_host_commands_failed; /* N/A */ - u_int8_t res19[8]; /* N/A */ - /* error counters on logical devices */ - u_int16_t logical_device_soft_errors; /* N/A */ - u_int16_t logical_device_commands_failed; /* N/A */ - u_int16_t logical_device_host_command_aborts; /* N/A */ - u_int16_t res20; /* N/A */ - /* error counters on controller */ - u_int16_t controller_parity_ecc_errors; - u_int16_t controller_host_command_aborts; /* N/A */ - u_int8_t res21[4]; /* N/A */ - /* long duration activity information */ - u_int16_t background_inits_active; - u_int16_t logical_inits_active; - u_int16_t physical_inits_active; - u_int16_t consistency_checks_active; - u_int16_t rebuilds_active; - u_int16_t MORE_active; - u_int16_t patrol_active; /* N/A */ - u_int8_t long_operation_status; /* N/A */ - u_int8_t res22; /* N/A */ - /* flash ROM information */ - u_int8_t flash_type; /* N/A */ - u_int8_t res23; /* N/A */ - u_int16_t flash_size; - u_int32_t flash_maximum_age; - u_int32_t flash_age; - u_int8_t res24[4]; /* N/A */ - char flash_name[16]; /* N/A */ - /* firmware runtime information */ - u_int8_t rebuild_rate; - u_int8_t background_init_rate; - u_int8_t init_rate; - u_int8_t consistency_check_rate; - u_int8_t res25[4]; /* N/A */ - u_int32_t maximum_dp; - u_int32_t free_dp; - u_int32_t maximum_iop; - u_int32_t free_iop; - u_int16_t maximum_comb_length; - u_int16_t maximum_configuration_groups; - u_int8_t installation_abort:1; - u_int8_t maintenance:1; - u_int8_t res26:6; /* N/A */ - u_int8_t res27[3]; /* N/A */ - u_int8_t res28[32 + 512]; /* N/A */ -} __packed; - -/* - * 21.9.2 MDACIOCTL_GETLOGDEVINFOVALID - */ -struct mly_ioctl_getlogdevinfovalid { - u_int8_t res1; /* N/A */ - u_int8_t channel; - u_int8_t target; - u_int8_t lun; - u_int8_t state; /* see 8.1 */ - u_int8_t raid_level; /* see 8.2 */ - u_int8_t stripe_size; /* see 8.3 */ - u_int8_t cache_line_size; /* see 8.4 */ - u_int8_t read_write_control; /* see 8.5 */ - u_int8_t consistency_check:1; - u_int8_t rebuild:1; - u_int8_t make_consistent:1; - u_int8_t initialisation:1; - u_int8_t migration:1; - u_int8_t patrol:1; - u_int8_t res2:2; /* N/A */ - u_int8_t ar5_limit; - u_int8_t ar5_algo; - u_int16_t logical_device_number; - u_int16_t bios_control; - /* erorr counters */ - u_int16_t soft_errors; /* N/A */ - u_int16_t commands_failed; /* N/A */ - u_int16_t host_command_aborts; /* N/A */ - u_int16_t deferred_write_errors; /* N/A */ - u_int8_t res3[8]; /* N/A */ - /* device size information */ - u_int8_t res4[2]; /* N/A */ - u_int16_t device_block_size; - u_int32_t original_device_size; /* N/A */ - u_int32_t device_size; /* XXX "blocks or MB" Huh? */ - u_int8_t res5[4]; /* N/A */ - char device_name[32]; /* N/A */ - u_int8_t inquiry[36]; - u_int8_t res6[12]; /* N/A */ - u_int64_t last_read_block; /* N/A */ - u_int64_t last_written_block; /* N/A */ - u_int64_t consistency_check_block; - u_int64_t rebuild_block; - u_int64_t make_consistent_block; - u_int64_t initialisation_block; - u_int64_t migration_block; - u_int64_t patrol_block; /* N/A */ - u_int8_t res7[64]; /* N/A */ -} __packed; - -/* - * 21.10.2 MDACIOCTL_GETPHYSDEVINFOVALID: Data Format - */ -struct mly_ioctl_getphysdevinfovalid { - u_int8_t res1; - u_int8_t channel; - u_int8_t target; - u_int8_t lun; - u_int8_t raid_ft:1; /* configuration status */ - u_int8_t res2:1; /* N/A */ - u_int8_t local:1; - u_int8_t res3:5; - u_int8_t host_dead:1; /* multiple host/controller status *//* N/A */ - u_int8_t host_connection_dead:1; /* N/A */ - u_int8_t res4:6; /* N/A */ - u_int8_t state; /* see 8.1 */ - u_int8_t width; - u_int16_t speed; - /* multiported physical device information */ - u_int8_t ports_available; /* N/A */ - u_int8_t ports_inuse; /* N/A */ - u_int8_t res5[4]; - u_int8_t ether_address[16]; /* N/A */ - u_int16_t command_tags; - u_int8_t consistency_check:1; /* N/A */ - u_int8_t rebuild:1; /* N/A */ - u_int8_t make_consistent:1; /* N/A */ - u_int8_t initialisation:1; - u_int8_t migration:1; /* N/A */ - u_int8_t patrol:1; /* N/A */ - u_int8_t res6:2; - u_int8_t long_operation_status; /* N/A */ - u_int8_t parity_errors; - u_int8_t soft_errors; - u_int8_t hard_errors; - u_int8_t miscellaneous_errors; - u_int8_t command_timeouts; /* N/A */ - u_int8_t retries; /* N/A */ - u_int8_t aborts; /* N/A */ - u_int8_t PFAs_detected; /* N/A */ - u_int8_t res7[6]; - u_int16_t block_size; - u_int32_t original_device_size; /* XXX "blocks or MB" Huh? */ - u_int32_t device_size; /* XXX "blocks or MB" Huh? */ - u_int8_t res8[4]; - char name[16]; /* N/A */ - u_int8_t res9[16 + 32]; - u_int8_t inquiry[36]; - u_int8_t res10[12 + 16]; - u_int64_t last_read_block; /* N/A */ - u_int64_t last_written_block; /* N/A */ - u_int64_t consistency_check_block; /* N/A */ - u_int64_t rebuild_block; /* N/A */ - u_int64_t make_consistent_block; /* N/A */ - u_int64_t initialisation_block; /* N/A */ - u_int64_t migration_block; /* N/A */ - u_int64_t patrol_block; /* N/A */ - u_int8_t res11[256]; -} __packed; - -union mly_devinfo { - struct mly_ioctl_getlogdevinfovalid logdev; - struct mly_ioctl_getphysdevinfovalid physdev; -}; - -/* - * 21.11.2 MDACIOCTL_GETPHYSDEVSTATISTICS: Data Format - * 21.12.2 MDACIOCTL_GETLOGDEVSTATISTICS: Data Format - */ -struct mly_ioctl_getdevstatistics { - u_int32_t uptime_ms; /* getphysedevstatistics only */ - u_int8_t res1[5]; /* N/A */ - u_int8_t channel; - u_int8_t target; - u_int8_t lun; - u_int16_t raid_device; /* getlogdevstatistics only */ - u_int8_t res2[2]; /* N/A */ - /* total read/write performance including cache data */ - u_int32_t total_reads; - u_int32_t total_writes; - u_int32_t total_read_size; - u_int32_t total_write_size; - /* cache read/write performance */ - u_int32_t cache_reads; /* N/A */ - u_int32_t cache_writes; /* N/A */ - u_int32_t cache_read_size; /* N/A */ - u_int32_t cache_write_size; /* N/A */ - /* commands active/wait information */ - u_int32_t command_waits_done; /* N/A */ - u_int16_t active_commands; /* N/A */ - u_int16_t waiting_commands; /* N/A */ - u_int8_t res3[8]; /* N/A */ -} __packed; - -/* - * 21.13.2 MDACIOCTL_GETCONTROLLERSTATISTICS: Data Format - */ -struct mly_ioctl_getcontrollerstatistics { - u_int32_t uptime_ms; /* N/A */ - u_int8_t res1[12]; /* N/A */ - /* target physical device performance data information */ - u_int32_t target_physical_device_interrupts; /* N/A */ - u_int32_t target_physical_device_stray_interrupts; /* N/A */ - u_int8_t res2[8]; /* N/A */ - u_int32_t target_physical_device_reads; /* N/A */ - u_int32_t target_physical_device_writes; /* N/A */ - u_int32_t target_physical_device_read_size; /* N/A */ - u_int32_t target_physical_device_write_size; /* N/A */ - /* host system performance data information */ - u_int32_t host_system_interrupts; /* N/A */ - u_int32_t host_system_stray_interrupts; /* N/A */ - u_int32_t host_system_sent_interrupts; /* N/A */ - u_int8_t res3[4]; /* N/A */ - u_int32_t physical_device_reads; /* N/A */ - u_int32_t physical_device_writes; /* N/A */ - u_int32_t physical_device_read_size; /* N/A */ - u_int32_t physical_device_write_size; /* N/A */ - u_int32_t physical_device_cache_reads; /* N/A */ - u_int32_t physical_device_cache_writes; /* N/A */ - u_int32_t physical_device_cache_read_size; /* N/A */ - u_int32_t physical_device_cache_write_size; /* N/A */ - u_int32_t logical_device_reads; /* N/A */ - u_int32_t logical_device_writes; /* N/A */ - u_int32_t logical_device_read_size; /* N/A */ - u_int32_t logical_device_write_size; /* N/A */ - u_int32_t logical_device_cache_reads; /* N/A */ - u_int32_t logical_device_cache_writes; /* N/A */ - u_int32_t logical_device_cache_read_size; /* N/A */ - u_int32_t logical_device_cache_write_size; /* N/A */ - u_int16_t target_physical_device_commands_active; /* N/A */ - u_int16_t target_physical_device_commands_waiting; /* N/A */ - u_int16_t host_system_commands_active; /* N/A */ - u_int16_t host_system_commands_waiting; /* N/A */ - u_int8_t res4[48 + 64]; /* N/A */ -} __packed; - -/* - * 21.2 MDACIOCTL_SETRAIDDEVSTATE - */ -struct mly_ioctl_param_setraiddevstate { - u_int8_t state; -} __packed; - -/* - * 21.27.2 MDACIOCTL_GETBDT_FOR_SYSDRIVE: Data Format - */ -#define MLY_MAX_BDT_ENTRIES 1022 -struct mly_ioctl_getbdt_for_sysdrive { - u_int32_t num_of_bdt_entries; - u_int32_t bad_data_block_address[MLY_MAX_BDT_ENTRIES]; -} __packed; - -/* - * 22.1 Physical Device Definition (PDD) - */ -struct mly_pdd { - u_int8_t type; /* see 8.2 */ - u_int8_t state; /* see 8.1 */ - u_int16_t raid_device; - u_int32_t device_size; /* XXX "block or MB" Huh? */ - u_int8_t controller; - u_int8_t channel; - u_int8_t target; - u_int8_t lun; - u_int32_t start_address; -} __packed; - -/* - * 22.2 RAID Device Use Definition (UDD) - */ -struct mly_udd { - u_int8_t res1; - u_int8_t state; /* see 8.1 */ - u_int16_t raid_device; - u_int32_t start_address; -} __packed; - -/* - * RAID Device Definition (LDD) - */ -struct mly_ldd { - u_int8_t type; /* see 8.2 */ - u_int8_t state; /* see 8.1 */ - u_int16_t raid_device; - u_int32_t device_size; /* XXX "block or MB" Huh? */ - u_int8_t devices_used_count; - u_int8_t stripe_size; /* see 8.3 */ - u_int8_t cache_line_size; /* see 8.4 */ - u_int8_t read_write_control; /* see 8.5 */ - u_int32_t devices_used_size; /* XXX "block or MB" Huh? */ - u_int16_t devices_used[32]; /* XXX actual size of this field unknown! */ -} __packed; - -/* - * Define a datastructure giving the smallest allocation that will hold - * a PDD, UDD or LDD for MDACIOCTL_GETDEVCONFINFO. - */ -struct mly_devconf_hdr { - u_int8_t type; /* see 8.2 */ - u_int8_t state; /* see 8.1 */ - u_int16_t raid_device; -}; - -union mly_ioctl_devconfinfo { - struct mly_pdd pdd; - struct mly_udd udd; - struct mly_ldd ldd; - struct mly_devconf_hdr hdr; -}; - -/* - * 22.3 MDACIOCTL_RENAMERAIDDEV - * - * XXX this command is listed as transferring data, but does not define the data. - */ -struct mly_ioctl_param_renameraiddev { - u_int8_t new_raid_device; -} __packed; - -/* - * 23.6.2 MDACIOCTL_XLATEPHYSDEVTORAIDDEV - * - * XXX documentation suggests this format will change - */ -struct mly_ioctl_param_xlatephysdevtoraiddev { - u_int16_t raid_device; - u_int8_t res1[2]; - u_int8_t controller; - u_int8_t channel; - u_int8_t target; - u_int8_t lun; -} __packed; - -/* - * 23.7 MDACIOCTL_GETGROUPCONFINFO - */ -struct mly_ioctl_param_getgroupconfinfo { - u_int16_t group; - u_int8_t res1[8]; - union mly_command_transfer transfer; -} __packed; - -/* - * 23.9.2 MDACIOCTL_GETFREESPACELIST: Data Format - * - * The controller will populate as much of this structure as is provided, - * or as is required to fully list the free space available. - */ -struct mly_ioctl_getfreespacelist_entry { - u_int16_t raid_device; - u_int8_t res1[6]; - u_int32_t address; /* XXX "blocks or MB" Huh? */ - u_int32_t size; /* XXX "blocks or MB" Huh? */ -} __packed; - -struct mly_ioctl_getfrespacelist { - u_int16_t returned_entries; - u_int16_t total_entries; - u_int8_t res1[12]; - struct mly_ioctl_getfreespacelist_entry space[0]; /* expand to suit */ -} __packed; - -/* - * 27.1 MDACIOCTL_GETSUBSYSTEMDATA - * 27.2 MDACIOCTL_SETSUBSYSTEMDATA - * - * PCI controller only supports a limited subset of the possible operations. - * - * XXX where does the status end up? (the command transfers no data) - */ -struct mly_ioctl_param_subsystemdata { - u_int8_t operation:4; -#define MLY_BBU_GETSTATUS 0x00 -#define MLY_BBU_SET_THRESHOLD 0x00 /* minutes in param[0,1] */ - u_int8_t subsystem:4; -#define MLY_SUBSYSTEM_BBU 0x01 - u_int parameter[3]; /* only for SETSUBSYSTEMDATA */ -} __packed; - -struct mly_ioctl_getsubsystemdata_bbustatus { - u_int16_t current_power; - u_int16_t maximum_power; - u_int16_t power_threshold; - u_int8_t charge_level; - u_int8_t hardware_version; - u_int8_t battery_type; -#define MLY_BBU_TYPE_UNKNOWN 0x00 -#define MLY_BBU_TYPE_NICAD 0x01 -#define MLY_BBU_TYPE_MISSING 0xfe - u_int8_t res1; - u_int8_t operation_status; -#define MLY_BBU_STATUS_NO_SYNC 0x01 -#define MLY_BBU_STATUS_OUT_OF_SYNC 0x02 -#define MLY_BBU_STATUS_FIRST_WARNING 0x04 -#define MLY_BBU_STATUS_SECOND_WARNING 0x08 -#define MLY_BBU_STATUS_RECONDITIONING 0x10 -#define MLY_BBU_STATUS_DISCHARGING 0x20 -#define MLY_BBU_STATUS_FASTCHARGING 0x40 - u_int8_t res2; -} __packed; - -/* - * 28.9 MDACIOCTL_RESETDEVICE - * 28.10 MDACIOCTL_FLUSHDEVICEDATA - * 28.11 MDACIOCTL_PAUSEDEVICE - * 28.12 MDACIOCTL_UNPAUSEDEVICE - */ -struct mly_ioctl_param_deviceoperation { - u_int8_t operation_device; /* see 14.3 */ -} __packed; - -/* - * 31.1 Event Data Format - */ -struct mly_event { - u_int32_t sequence_number; - u_int32_t timestamp; - u_int32_t code; - u_int8_t controller; - u_int8_t channel; - u_int8_t target; /* also enclosure */ - u_int8_t lun; /* also enclosure unit */ - u_int8_t res1[4]; - u_int32_t param; - u_int8_t sense[40]; -} __packed; - -/* - * 31.2 MDACIOCTL_GETEVENT - */ -struct mly_ioctl_param_getevent { - u_int16_t sequence_number_low; - u_int8_t res1[8]; - union mly_command_transfer transfer; -} __packed; - -union mly_ioctl_param { - struct mly_ioctl_param_data data; - struct mly_ioctl_param_setmemorymailbox setmemorymailbox; - struct mly_ioctl_param_setraiddevstate setraiddevstate; - struct mly_ioctl_param_renameraiddev renameraiddev; - struct mly_ioctl_param_xlatephysdevtoraiddev xlatephysdevtoraiddev; - struct mly_ioctl_param_getgroupconfinfo getgroupconfinfo; - struct mly_ioctl_param_subsystemdata subsystemdata; - struct mly_ioctl_param_deviceoperation deviceoperation; - struct mly_ioctl_param_getevent getevent; -}; - -/* - * 19 SCSI Command Format - */ -struct mly_command_address_physical { - u_int8_t lun; - u_int8_t target; - u_int8_t channel:3; - u_int8_t controller:5; -} __packed; - -struct mly_command_address_logical { - u_int16_t logdev; - u_int8_t res1:3; - u_int8_t controller:5; -} __packed; - -union mly_command_address { - struct mly_command_address_physical phys; - struct mly_command_address_logical log; -}; - -struct mly_command_generic { - u_int16_t command_id; - u_int8_t opcode; - struct mly_command_control command_control; - u_int32_t data_size; - u_int64_t sense_buffer_address; - union mly_command_address addr; - struct mly_timeout timeout; - u_int8_t maximum_sense_size; - u_int8_t res1[11]; - union mly_command_transfer transfer; -} __packed; - - -/* - * 19.1 MDACMD_SCSI & MDACMD_SCSIPT - */ -#define MLY_CMD_SCSI_SMALL_CDB 10 -struct mly_command_scsi_small { - u_int16_t command_id; - u_int8_t opcode; - struct mly_command_control command_control; - u_int32_t data_size; - u_int64_t sense_buffer_address; - union mly_command_address addr; - struct mly_timeout timeout; - u_int8_t maximum_sense_size; - u_int8_t cdb_length; - u_int8_t cdb[MLY_CMD_SCSI_SMALL_CDB]; - union mly_command_transfer transfer; -} __packed; - -/* - * 19.2 MDACMD_SCSILC & MDACMD_SCSILCPT - */ -struct mly_command_scsi_large { - u_int16_t command_id; - u_int8_t opcode; - struct mly_command_control command_control; - u_int32_t data_size; - u_int64_t sense_buffer_address; - union mly_command_address addr; - struct mly_timeout timeout; - u_int8_t maximum_sense_size; - u_int8_t cdb_length; - u_int16_t res1; - u_int64_t cdb_physaddr; - union mly_command_transfer transfer; -} __packed; - -/* - * 20.1 IOCTL Command Format: Internal Bus - */ -struct mly_command_ioctl { - u_int16_t command_id; - u_int8_t opcode; - struct mly_command_control command_control; - u_int32_t data_size; - u_int64_t sense_buffer_address; - union mly_command_address addr; - struct mly_timeout timeout; - u_int8_t maximum_sense_size; - u_int8_t sub_ioctl; - union mly_ioctl_param param; -} __packed; - -/* - * PG6: 8.2.2 - */ -struct mly_command_mmbox { - u_int32_t flag; - u_int8_t data[60]; -} __packed; - -union mly_command_packet { - struct mly_command_generic generic; - struct mly_command_scsi_small scsi_small; - struct mly_command_scsi_large scsi_large; - struct mly_command_ioctl ioctl; - struct mly_command_mmbox mmbox; -}; - -/* - * PG6: 5.3 - */ -#define MLY_I960RX_COMMAND_MAILBOX 0x10 -#define MLY_I960RX_STATUS_MAILBOX 0x18 -#define MLY_I960RX_IDBR 0x20 -#define MLY_I960RX_ODBR 0x2c -#define MLY_I960RX_ERROR_STATUS 0x2e -#define MLY_I960RX_INTERRUPT_STATUS 0x30 -#define MLY_I960RX_INTERRUPT_MASK 0x34 - -#define MLY_STRONGARM_COMMAND_MAILBOX 0x50 -#define MLY_STRONGARM_STATUS_MAILBOX 0x58 -#define MLY_STRONGARM_IDBR 0x60 -#define MLY_STRONGARM_ODBR 0x61 -#define MLY_STRONGARM_ERROR_STATUS 0x63 -#define MLY_STRONGARM_INTERRUPT_STATUS 0x30 -#define MLY_STRONGARM_INTERRUPT_MASK 0x34 - -/* - * PG6: 5.4.3 Doorbell 0 - */ -#define MLY_HM_CMDSENT (1<<0) -#define MLY_HM_STSACK (1<<1) -#define MLY_SOFT_RST (1<<3) -#define MLY_AM_CMDSENT (1<<4) - -/* - * PG6: 5.4.4 Doorbell 1 - * - * Note that the documentation claims that these bits are set when the - * status queue(s) are empty, whereas the Linux driver and experience - * suggest they are set when there is status available. - */ -#define MLY_HM_STSREADY (1<<0) -#define MLY_AM_STSREADY (1<<1) - -/* - * PG6: 5.4.6 Doorbell 3 - */ -#define MLY_MSG_EMPTY (1<<3) -#define MLY_MSG_SPINUP 0x08 -#define MLY_MSG_RACE_RECOVERY_FAIL 0x60 -#define MLY_MSG_RACE_IN_PROGRESS 0x70 -#define MLY_MSG_RACE_ON_CRITICAL 0xb0 -#define MLY_MSG_PARITY_ERROR 0xf0 - -/* - * PG6: 5.4.8 Outbound Interrupt Mask - */ -#define MLY_INTERRUPT_MASK_DISABLE 0xff -#define MLY_INTERRUPT_MASK_ENABLE (0xff & ~(1<<2)) - -/* - * PG6: 8.2 Advanced Mailbox Scheme - * - * Note that this must be allocated on a 4k boundary, and all internal - * fields must also reside on a 4k boundary. - * We could dynamically size this structure, but the extra effort - * is probably unjustified. Note that these buffers do not need to be - * adjacent - we just group them to simplify allocation of the bus-visible - * buffer. - * - * XXX Note that for some reason, if MLY_MMBOX_COMMANDS is > 64, the controller - * fails to respond to the command at (MLY_MMBOX_COMMANDS - 64). It's not - * wrapping to 0 at this point (determined by experimentation). This is not - * consistent with the Linux driver's implementation. - * Whilst it's handy to have lots of room for status returns in case we end up - * being slow getting back to completed commands, it seems unlikely that we - * would get 64 commands ahead of the controller on the submissions side, so - * the current workaround is to simply limit the command ring to 64 entries. - */ -union mly_status_packet { - struct mly_status status; - struct { - u_int32_t flag; - u_int8_t data[4]; - } __packed mmbox; -}; -union mly_health_region { - struct mly_health_status status; - u_int8_t pad[1024]; -}; - -#define MLY_MMBOX_COMMANDS 64 -#define MLY_MMBOX_STATUS 512 -struct mly_mmbox { - union mly_command_packet mmm_command[MLY_MMBOX_COMMANDS]; - union mly_status_packet mmm_status[MLY_MMBOX_STATUS]; - union mly_health_region mmm_health; -} __packed; diff --git a/sys/dev/mly/mlyvar.h b/sys/dev/mly/mlyvar.h deleted file mode 100644 --- a/sys/dev/mly/mlyvar.h +++ /dev/null @@ -1,370 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2000, 2001 Michael Smith - * Copyright (c) 2000 BSDi - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ - -/******************************************************************************** - ******************************************************************************** - Driver Parameter Definitions - ******************************************************************************** - ********************************************************************************/ - -/* - * The firmware interface allows for a 16-bit command identifier. A lookup - * table this size (256k) would be too expensive, so we cap ourselves at a - * reasonable limit. - */ -#define MLY_MAX_COMMANDS 256 /* max commands per controller */ - -/* - * The firmware interface allows for a 16-bit s/g list length. We limit - * ourselves to a reasonable maximum and ensure alignment. - */ -#define MLY_MAX_SGENTRIES 64 /* max S/G entries, limit 65535 */ - -/* - * The interval at which we poke the controller for status updates (in seconds). - */ -#define MLY_PERIODIC_INTERVAL 1 - -/******************************************************************************** - ******************************************************************************** - Cross-version Compatibility - ******************************************************************************** - ********************************************************************************/ - -# include - -/******************************************************************************** - ******************************************************************************** - Driver Variable Definitions - ******************************************************************************** - ********************************************************************************/ - -/* - * Debugging levels: - * 0 - quiet, only emit warnings - * 1 - noisy, emit major function points and things done - * 2 - extremely noisy, emit trace items in loops, etc. - */ -#ifdef MLY_DEBUG -# define debug(level, fmt, args...) do { if (level <= MLY_DEBUG) printf("%s: " fmt "\n", __func__ , ##args); } while(0) -# define debug_called(level) do { if (level <= MLY_DEBUG) printf("%s: called\n", __func__); } while(0) -# define debug_struct(s) printf(" SIZE %s: %d\n", #s, sizeof(struct s)) -# define debug_union(s) printf(" SIZE %s: %d\n", #s, sizeof(union s)) -# define debug_field(s, f) printf(" OFFSET %s.%s: %d\n", #s, #f, ((int)&(((struct s *)0)->f))) -extern void mly_printstate0(void); -extern struct mly_softc *mly_softc0; -#else -# define debug(level, fmt, args...) -# define debug_called(level) -# define debug_struct(s) -#endif - -#define mly_printf(sc, fmt, args...) device_printf(sc->mly_dev, fmt , ##args) - -/* - * Per-device structure, used to save persistent state on devices. - * - * Note that this isn't really Bus/Target/Lun since we don't support - * lun != 0 at this time. - */ -struct mly_btl { - int mb_flags; -#define MLY_BTL_PHYSICAL (1<<0) /* physical device */ -#define MLY_BTL_LOGICAL (1<<1) /* logical device */ -#define MLY_BTL_PROTECTED (1<<2) /* device is protected - I/O not allowed */ -#define MLY_BTL_RESCAN (1<<3) /* device needs to be rescanned */ - char mb_name[16]; /* peripheral attached to this device */ - int mb_state; /* see 8.1 */ - int mb_type; /* see 8.2 */ - - /* physical devices only */ - int mb_speed; /* interface transfer rate */ - int mb_width; /* interface width */ -}; - -/* - * Per-command control structure. - */ -struct mly_command { - TAILQ_ENTRY(mly_command) mc_link; /* list linkage */ - - struct mly_softc *mc_sc; /* controller that owns us */ - u_int16_t mc_slot; /* command slot we occupy */ - int mc_flags; -#define MLY_CMD_BUSY (1<<0) /* command is being run, or ready to run, or not completed */ -#define MLY_CMD_COMPLETE (1<<1) /* command has been completed */ -#define MLY_CMD_MAPPED (1<<3) /* command has had its data mapped */ -#define MLY_CMD_DATAIN (1<<4) /* data moves controller->system */ -#define MLY_CMD_DATAOUT (1<<5) /* data moves system->controller */ -#define MLY_CMD_CCB (1<<6) /* data is ccb. */ - u_int16_t mc_status; /* command completion status */ - u_int8_t mc_sense; /* sense data length */ - int32_t mc_resid; /* I/O residual count */ - - union mly_command_packet *mc_packet; /* our controller command */ - u_int64_t mc_packetphys; /* physical address of the mapped packet */ - - void *mc_data; /* data buffer */ - size_t mc_length; /* data length */ - bus_dmamap_t mc_datamap; /* DMA map for data */ - - void (* mc_complete)(struct mly_command *mc); /* completion handler */ - void *mc_private; /* caller-private data */ - - int mc_timestamp; -}; - -/* - * Command slot regulation. - * - * We can't use slot 0 due to the memory mailbox implementation. - */ -#define MLY_SLOT_START 1 -#define MLY_SLOT_MAX (MLY_SLOT_START + MLY_MAX_COMMANDS) - -/* - * Per-controller structure. - */ -struct mly_softc { - /* bus connections */ - device_t mly_dev; - struct cdev *mly_dev_t; - struct resource *mly_regs_resource; /* register interface window */ - int mly_regs_rid; /* resource ID */ - bus_dma_tag_t mly_parent_dmat; /* parent DMA tag */ - bus_dma_tag_t mly_buffer_dmat; /* data buffer/command DMA tag */ - struct resource *mly_irq; /* interrupt */ - int mly_irq_rid; - void *mly_intr; /* interrupt handle */ - - /* scatter/gather lists and their controller-visible mappings */ - struct mly_sg_entry *mly_sg_table; /* s/g lists */ - u_int32_t mly_sg_busaddr; /* s/g table base address in bus space */ - bus_dma_tag_t mly_sg_dmat; /* s/g buffer DMA tag */ - bus_dmamap_t mly_sg_dmamap; /* map for s/g buffers */ - - /* controller hardware interface */ - int mly_hwif; -#define MLY_HWIF_I960RX 0 -#define MLY_HWIF_STRONGARM 1 - u_int8_t mly_doorbell_true; /* xor map to make hardware doorbell 'true' bits into 1s */ - u_int8_t mly_command_mailbox; /* register offsets */ - u_int8_t mly_status_mailbox; - u_int8_t mly_idbr; - u_int8_t mly_odbr; - u_int8_t mly_error_status; - u_int8_t mly_interrupt_status; - u_int8_t mly_interrupt_mask; - struct mly_mmbox *mly_mmbox; /* kernel-space address of memory mailbox */ - u_int64_t mly_mmbox_busaddr; /* bus-space address of memory mailbox */ - bus_dma_tag_t mly_mmbox_dmat; /* memory mailbox DMA tag */ - bus_dmamap_t mly_mmbox_dmamap; /* memory mailbox DMA map */ - u_int32_t mly_mmbox_command_index; /* next index to use */ - u_int32_t mly_mmbox_status_index; /* index we next expect status at */ - - /* controller features, limits and status */ - struct mtx mly_lock; - int mly_state; -#define MLY_STATE_OPEN (1<<1) -#define MLY_STATE_INTERRUPTS_ON (1<<2) -#define MLY_STATE_MMBOX_ACTIVE (1<<3) -#define MLY_STATE_CAM_FROZEN (1<<4) - struct mly_ioctl_getcontrollerinfo *mly_controllerinfo; - struct mly_param_controller *mly_controllerparam; - struct mly_btl mly_btl[MLY_MAX_CHANNELS][MLY_MAX_TARGETS]; - - /* command management */ - struct mly_command mly_command[MLY_MAX_COMMANDS]; /* commands */ - union mly_command_packet *mly_packet; /* command packets */ - bus_dma_tag_t mly_packet_dmat; /* packet DMA tag */ - bus_dmamap_t mly_packetmap; /* packet DMA map */ - u_int64_t mly_packetphys; /* packet array base address */ - TAILQ_HEAD(,mly_command) mly_free; /* commands available for reuse */ - TAILQ_HEAD(,mly_command) mly_busy; - TAILQ_HEAD(,mly_command) mly_complete; /* commands which have been returned by the controller */ - struct mly_qstat mly_qstat[MLYQ_COUNT]; /* queue statistics */ - - /* health monitoring */ - u_int32_t mly_event_change; /* event status change indicator */ - u_int32_t mly_event_counter; /* next event for which we anticpiate status */ - u_int32_t mly_event_waiting; /* next event the controller will post status for */ - struct callout mly_periodic; /* periodic event handling */ - - /* CAM connection */ - struct cam_devq *mly_cam_devq; /* CAM device queue */ - struct cam_sim *mly_cam_sim[MLY_MAX_CHANNELS]; /* CAM SIMs */ - struct cam_path *mly_cam_path; /* rescan path */ - int mly_cam_channels; /* total channel count */ - - /* command-completion task */ - struct task mly_task_complete; /* deferred-completion task */ - int mly_qfrzn_cnt; /* Track simq freezes */ - -#ifdef MLY_DEBUG - struct callout mly_timeout; -#endif -}; - -#define MLY_LOCK(sc) mtx_lock(&(sc)->mly_lock) -#define MLY_UNLOCK(sc) mtx_unlock(&(sc)->mly_lock) -#define MLY_ASSERT_LOCKED(sc) mtx_assert(&(sc)->mly_lock, MA_OWNED) - -/* - * Register access helpers. - */ -#define MLY_SET_REG(sc, reg, val) bus_write_1(sc->mly_regs_resource, reg, val) -#define MLY_GET_REG(sc, reg) bus_read_1 (sc->mly_regs_resource, reg) -#define MLY_GET_REG2(sc, reg) bus_read_2 (sc->mly_regs_resource, reg) -#define MLY_GET_REG4(sc, reg) bus_read_4 (sc->mly_regs_resource, reg) - -#define MLY_SET_MBOX(sc, mbox, ptr) \ - do { \ - bus_write_4(sc->mly_regs_resource, mbox, *((u_int32_t *)ptr)); \ - bus_write_4(sc->mly_regs_resource, mbox + 4, *((u_int32_t *)ptr + 1)); \ - bus_write_4(sc->mly_regs_resource, mbox + 8, *((u_int32_t *)ptr + 2)); \ - bus_write_4(sc->mly_regs_resource, mbox + 12, *((u_int32_t *)ptr + 3)); \ - } while(0); -#define MLY_GET_MBOX(sc, mbox, ptr) \ - do { \ - *((u_int32_t *)ptr) = bus_read_4(sc->mly_regs_resource, mbox); \ - *((u_int32_t *)ptr + 1) = bus_read_4(sc->mly_regs_resource, mbox + 4); \ - *((u_int32_t *)ptr + 2) = bus_read_4(sc->mly_regs_resource, mbox + 8); \ - *((u_int32_t *)ptr + 3) = bus_read_4(sc->mly_regs_resource, mbox + 12); \ - } while(0); - -#define MLY_IDBR_TRUE(sc, mask) \ - ((((MLY_GET_REG((sc), (sc)->mly_idbr)) ^ (sc)->mly_doorbell_true) & (mask)) == (mask)) -#define MLY_ODBR_TRUE(sc, mask) \ - ((MLY_GET_REG((sc), (sc)->mly_odbr) & (mask)) == (mask)) -#define MLY_ERROR_VALID(sc) \ - ((((MLY_GET_REG((sc), (sc)->mly_error_status)) ^ (sc)->mly_doorbell_true) & (MLY_MSG_EMPTY)) == 0) - -#define MLY_MASK_INTERRUPTS(sc) \ - do { \ - MLY_SET_REG((sc), (sc)->mly_interrupt_mask, MLY_INTERRUPT_MASK_DISABLE); \ - sc->mly_state &= ~MLY_STATE_INTERRUPTS_ON; \ - } while(0); -#define MLY_UNMASK_INTERRUPTS(sc) \ - do { \ - MLY_SET_REG((sc), (sc)->mly_interrupt_mask, MLY_INTERRUPT_MASK_ENABLE); \ - sc->mly_state |= MLY_STATE_INTERRUPTS_ON; \ - } while(0); - -/* - * Bus/target/logical ID-related macros. - */ -#define MLY_LOGDEV_ID(sc, bus, target) (((bus) - (sc)->mly_controllerinfo->physical_channels_present) * \ - MLY_MAX_TARGETS + (target)) -#define MLY_LOGDEV_BUS(sc, logdev) (((logdev) / MLY_MAX_TARGETS) + \ - (sc)->mly_controllerinfo->physical_channels_present) -#define MLY_LOGDEV_TARGET(sc, logdev) ((logdev) % MLY_MAX_TARGETS) -#define MLY_BUS_IS_VIRTUAL(sc, bus) ((bus) >= (sc)->mly_controllerinfo->physical_channels_present) -#define MLY_BUS_IS_VALID(sc, bus) (((bus) < (sc)->mly_cam_channels) && ((sc)->mly_cam_sim[(bus)] != NULL)) - -/******************************************************************************** - * Queue primitives - */ - -#define MLYQ_ADD(sc, qname) \ - do { \ - struct mly_qstat *qs = &(sc)->mly_qstat[qname]; \ - \ - qs->q_length++; \ - if (qs->q_length > qs->q_max) \ - qs->q_max = qs->q_length; \ - } while(0) - -#define MLYQ_REMOVE(sc, qname) (sc)->mly_qstat[qname].q_length-- -#define MLYQ_INIT(sc, qname) \ - do { \ - sc->mly_qstat[qname].q_length = 0; \ - sc->mly_qstat[qname].q_max = 0; \ - } while(0) - -#define MLYQ_COMMAND_QUEUE(name, index) \ -static __inline void \ -mly_initq_ ## name (struct mly_softc *sc) \ -{ \ - TAILQ_INIT(&sc->mly_ ## name); \ - MLYQ_INIT(sc, index); \ -} \ -static __inline void \ -mly_enqueue_ ## name (struct mly_command *mc) \ -{ \ - \ - TAILQ_INSERT_TAIL(&mc->mc_sc->mly_ ## name, mc, mc_link); \ - MLYQ_ADD(mc->mc_sc, index); \ -} \ -static __inline void \ -mly_requeue_ ## name (struct mly_command *mc) \ -{ \ - \ - TAILQ_INSERT_HEAD(&mc->mc_sc->mly_ ## name, mc, mc_link); \ - MLYQ_ADD(mc->mc_sc, index); \ -} \ -static __inline struct mly_command * \ -mly_dequeue_ ## name (struct mly_softc *sc) \ -{ \ - struct mly_command *mc; \ - \ - if ((mc = TAILQ_FIRST(&sc->mly_ ## name)) != NULL) { \ - TAILQ_REMOVE(&sc->mly_ ## name, mc, mc_link); \ - MLYQ_REMOVE(sc, index); \ - } \ - return(mc); \ -} \ -static __inline void \ -mly_remove_ ## name (struct mly_command *mc) \ -{ \ - \ - TAILQ_REMOVE(&mc->mc_sc->mly_ ## name, mc, mc_link); \ - MLYQ_REMOVE(mc->mc_sc, index); \ -} \ -struct hack - -MLYQ_COMMAND_QUEUE(free, MLYQ_FREE); -MLYQ_COMMAND_QUEUE(busy, MLYQ_BUSY); -MLYQ_COMMAND_QUEUE(complete, MLYQ_COMPLETE); - -/******************************************************************************** - * space-fill a character string - */ -static __inline void -padstr(char *targ, char *src, int len) -{ - while (len-- > 0) { - if (*src != 0) { - *targ++ = *src++; - } else { - *targ++ = ' '; - } - } -} diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -159,7 +159,6 @@ device ciss # Compaq Smart RAID 5* device iir # Intel Integrated RAID device ips # IBM (Adaptec) ServeRAID -device mly # Mylex AcceleRAID/eXtremeRAID device twa # 3ware 9000 series PATA/SATA RAID device tws # LSI 3ware 9750 SATA+SAS 6Gb/s RAID controller diff --git a/sys/modules/Makefile b/sys/modules/Makefile --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -243,7 +243,6 @@ ${_mlx5} \ ${_mlx5en} \ ${_mlx5ib} \ - ${_mly} \ mmc \ mmcsd \ ${_mpr} \ @@ -710,7 +709,6 @@ _iwmfw= iwmfw _iwnfw= iwnfw .endif -_mly= mly _nfe= nfe _nvd= nvd _nvme= nvme diff --git a/sys/modules/mly/Makefile b/sys/modules/mly/Makefile deleted file mode 100644 --- a/sys/modules/mly/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/mly - -KMOD= mly -SRCS= mly.c -SRCS+= opt_scsi.h opt_cam.h -SRCS+= device_if.h bus_if.h pci_if.h - -#CFLAGS+= -DMLY_DEBUG=1 -CFLAGS+= -DMLY_MODULE - -.include diff --git a/tools/kerneldoc/subsys/Doxyfile-dev_mly b/tools/kerneldoc/subsys/Doxyfile-dev_mly deleted file mode 100644 --- a/tools/kerneldoc/subsys/Doxyfile-dev_mly +++ /dev/null @@ -1,21 +0,0 @@ -# Doxyfile 1.5.2 - -# $FreeBSD$ - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = "FreeBSD kernel MLY device code" -OUTPUT_DIRECTORY = $(DOXYGEN_DEST_PATH)/dev_mly/ -EXTRACT_ALL = YES # for undocumented src, no warnings enabled -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = $(DOXYGEN_SRC_PATH)/dev/mly/ \ - $(NOTREVIEWED) - -GENERATE_TAGFILE = dev_mly/dev_mly.tag - -@INCLUDE_PATH = $(DOXYGEN_INCLUDE_PATH) -@INCLUDE = common-Doxyfile -