amr: remove
Belatedly remove amr(4). It was slated to depart before 13.0 but was overlooked until now. Sponsored by: Netflix Relnotes: yes Reviewed by: scottl Differential Revision: https://reviews.freebsd.org/D33113
This commit is contained in:
parent
399188a2c6
commit
60de2867c9
@ -1,246 +0,0 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2000 Jeroen Ruigrok van der Werven
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 29, 2006
|
||||
.Dt AMR 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm amr
|
||||
.Nd MegaRAID SCSI/ATA/SATA RAID driver
|
||||
.Sh SYNOPSIS
|
||||
To compile this driver into the kernel,
|
||||
place the following lines in your
|
||||
kernel configuration file:
|
||||
.Bd -ragged -offset indent
|
||||
.Cd "device pci"
|
||||
.Cd "device scbus"
|
||||
.Cd "device amr"
|
||||
.Ed
|
||||
.Pp
|
||||
Alternatively, to load the driver as a
|
||||
module at boot time, place the following line in
|
||||
.Xr loader.conf 5 :
|
||||
.Bd -literal -offset indent
|
||||
amr_load="YES"
|
||||
.Ed
|
||||
.Sh DEPRECATION NOTICE
|
||||
The
|
||||
.Nm
|
||||
driver is not present in
|
||||
.Fx 13.0 .
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
driver provides support for LSI Logic MegaRAID SCSI, ATA and SATA
|
||||
RAID controllers and legacy American Megatrends MegaRAID
|
||||
SCSI RAID controllers, including models relabeled
|
||||
and sold by Dell and Hewlett-Packard.
|
||||
.Pp
|
||||
LSI MegaRAID SAS controllers are supported by
|
||||
.Xr mfi 4
|
||||
and will not work with this driver.
|
||||
.Sh HARDWARE
|
||||
Controllers supported by the
|
||||
.Nm
|
||||
driver include:
|
||||
.Pp
|
||||
.Bl -bullet -compact
|
||||
.It
|
||||
MegaRAID SATA 150-4
|
||||
.It
|
||||
MegaRAID SATA 150-6
|
||||
.It
|
||||
MegaRAID SATA 300-4X
|
||||
.It
|
||||
MegaRAID SATA 300-8X
|
||||
.It
|
||||
MegaRAID SCSI 320-1E
|
||||
.It
|
||||
MegaRAID SCSI 320-2E
|
||||
.It
|
||||
MegaRAID SCSI 320-4E
|
||||
.It
|
||||
MegaRAID SCSI 320-0X
|
||||
.It
|
||||
MegaRAID SCSI 320-2X
|
||||
.It
|
||||
MegaRAID SCSI 320-4X
|
||||
.It
|
||||
MegaRAID SCSI 320-0
|
||||
.It
|
||||
MegaRAID SCSI 320-1
|
||||
.It
|
||||
MegaRAID SCSI 320-2
|
||||
.It
|
||||
MegaRAID SCSI 320-4
|
||||
.It
|
||||
MegaRAID Series 418
|
||||
.It
|
||||
MegaRAID i4 133 RAID
|
||||
.It
|
||||
MegaRAID Elite 1500 (Series 467)
|
||||
.It
|
||||
MegaRAID Elite 1600 (Series 493)
|
||||
.It
|
||||
MegaRAID Elite 1650 (Series 4xx)
|
||||
.It
|
||||
MegaRAID Enterprise 1200 (Series 428)
|
||||
.It
|
||||
MegaRAID Enterprise 1300 (Series 434)
|
||||
.It
|
||||
MegaRAID Enterprise 1400 (Series 438)
|
||||
.It
|
||||
MegaRAID Enterprise 1500 (Series 467)
|
||||
.It
|
||||
MegaRAID Enterprise 1600 (Series 471)
|
||||
.It
|
||||
MegaRAID Express 100 (Series 466WS)
|
||||
.It
|
||||
MegaRAID Express 200 (Series 466)
|
||||
.It
|
||||
MegaRAID Express 300 (Series 490)
|
||||
.It
|
||||
MegaRAID Express 500 (Series 475)
|
||||
.It
|
||||
Dell PERC
|
||||
.It
|
||||
Dell PERC 2/SC
|
||||
.It
|
||||
Dell PERC 2/DC
|
||||
.It
|
||||
Dell PERC 3/DCL
|
||||
.It
|
||||
Dell PERC 3/QC
|
||||
.It
|
||||
Dell PERC 4/DC
|
||||
.It
|
||||
Dell PERC 4/IM
|
||||
.It
|
||||
Dell PERC 4/SC
|
||||
.It
|
||||
Dell PERC 4/Di
|
||||
.It
|
||||
Dell PERC 4e/DC
|
||||
.It
|
||||
Dell PERC 4e/Di
|
||||
.It
|
||||
Dell PERC 4e/Si
|
||||
.It
|
||||
Dell PERC 4ei
|
||||
.It
|
||||
HP NetRAID-1/Si
|
||||
.It
|
||||
HP NetRAID-3/Si (D4943A)
|
||||
.It
|
||||
HP Embedded NetRAID
|
||||
.It
|
||||
Intel RAID Controller SRCS16
|
||||
.It
|
||||
Intel RAID Controller SRCU42X
|
||||
.El
|
||||
.Sh DIAGNOSTICS
|
||||
.Ss Driver initialisation/shutdown phase
|
||||
.Bl -diag
|
||||
.It amr%d: memory window not available
|
||||
.It amr%d: I/O window not available
|
||||
.Pp
|
||||
The PCI BIOS did not allocate resources necessary for the correct operation of
|
||||
the controller.
|
||||
The driver cannot attach to this controller.
|
||||
.It amr%d: busmaster bit not set, enabling
|
||||
.Pp
|
||||
The PCI BIOS did not enable busmaster DMA,
|
||||
which is required for the correct operation of the controller.
|
||||
The driver has enabled this bit and initialisation will proceed.
|
||||
.It amr%d: can't allocate register window
|
||||
.It amr%d: can't allocate interrupt
|
||||
.It amr%d: can't set up interrupt
|
||||
.It amr%d: can't allocate parent DMA tag
|
||||
.It amr%d: can't allocate buffer DMA tag
|
||||
.It amr%d: can't allocate scatter/gather DMA tag
|
||||
.It amr%d: can't allocate s/g table
|
||||
.It amr%d: can't allocate mailbox tag
|
||||
.It amr%d: can't allocate mailbox memory
|
||||
.Pp
|
||||
A resource allocation error occurred while initialising the driver;
|
||||
initialisation has failed and the driver will not attach to this controller.
|
||||
.It amr%d: can't obtain configuration data from controller
|
||||
.It amr%d: can't obtain product data from controller
|
||||
.Pp
|
||||
The driver was unable to obtain vital configuration data from the controller.
|
||||
Initialisation has failed and the driver will not attach to this controller.
|
||||
.It amr%d: can't establish configuration hook
|
||||
.It amr%d: can't scan controller for drives
|
||||
.Pp
|
||||
The scan for logical drives managed by the controller failed.
|
||||
No drives will be attached.
|
||||
.It amr%d: device_add_child failed
|
||||
.It amr%d: bus_generic_attach returned %d
|
||||
.Pp
|
||||
Creation of the logical drive instances failed;
|
||||
attachment of one or more logical drives may have been aborted.
|
||||
.It amr%d: flushing cache...
|
||||
.Pp
|
||||
The controller cache is being flushed prior to shutdown or detach.
|
||||
.El
|
||||
.Ss Operational diagnostics
|
||||
.Bl -diag
|
||||
.It amr%d: I/O beyond end of unit (%u,%d > %u)
|
||||
.Pp
|
||||
A partitioning error or disk corruption has caused an I/O request
|
||||
beyond the end of the logical drive.
|
||||
This may also occur if FlexRAID Virtual Sizing is enabled and
|
||||
an I/O operation is attempted on a portion of the virtual drive
|
||||
beyond the actual capacity available.
|
||||
.It amr%d: polled command timeout
|
||||
.Pp
|
||||
An initialisation command timed out.
|
||||
The initialisation process may fail as a result.
|
||||
.It amr%d: bad slot %d completed
|
||||
.Pp
|
||||
The controller reported completion of a command that the driver did not issue.
|
||||
This may result in data corruption,
|
||||
and suggests a hardware or firmware problem with the system or controller.
|
||||
.It amr%d: I/O error - %x
|
||||
.Pp
|
||||
An I/O error has occurred.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr cd 4 ,
|
||||
.Xr da 4 ,
|
||||
.Xr mfi 4 ,
|
||||
.Xr sa 4 ,
|
||||
.Xr scsi 4
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
.Nm
|
||||
driver was written by
|
||||
.An Mike Smith Aq Mt msmith@FreeBSD.org .
|
||||
.Pp
|
||||
This manual page was written by
|
||||
.An Mike Smith Aq Mt msmith@FreeBSD.org
|
||||
and
|
||||
.An Jeroen Ruigrok van der Werven Aq Mt asmodai@FreeBSD.org .
|
@ -180,7 +180,6 @@ device ses # Enclosure Services (SES and SAF-TE)
|
||||
#device ctl # CAM Target Layer
|
||||
|
||||
# RAID controllers interfaced to the SCSI subsystem
|
||||
device amr # AMI MegaRAID
|
||||
device arcmsr # Areca SATA II RAID
|
||||
device ciss # Compaq Smart RAID 5*
|
||||
device ips # IBM (Adaptec) ServeRAID
|
||||
|
@ -1642,8 +1642,6 @@ device ciss
|
||||
#
|
||||
device ida # Compaq Smart RAID
|
||||
device mlx # Mylex DAC960
|
||||
device amr # AMI MegaRAID
|
||||
device amrp # SCSI Passthrough interface (optional, CAM req.)
|
||||
device mfi # LSI MegaRAID SAS
|
||||
device mfip # LSI MegaRAID SAS passthrough, requires CAM
|
||||
options MFI_DEBUG
|
||||
|
@ -890,10 +890,6 @@ dev/altera/pio/pio.c optional altera_pio
|
||||
dev/altera/pio/pio_if.m optional altera_pio
|
||||
dev/amdpm/amdpm.c optional amdpm pci | nfpm pci
|
||||
dev/amdsmb/amdsmb.c optional amdsmb pci
|
||||
dev/amr/amr.c optional amr
|
||||
dev/amr/amr_cam.c optional amrp amr
|
||||
dev/amr/amr_disk.c optional amr
|
||||
dev/amr/amr_pci.c optional amr pci
|
||||
#
|
||||
dev/ata/ata_if.m optional ata | atacore
|
||||
dev/ata/ata-all.c optional ata | atacore
|
||||
|
2446
sys/dev/amr/amr.c
2446
sys/dev/amr/amr.c
File diff suppressed because it is too large
Load Diff
@ -1,627 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2000 Michael Smith
|
||||
* Copyright (c) 2000 BSDi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 2002 Eric Moore
|
||||
* Copyright (c) 2002 LSI Logic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The party using or redistributing the source code and binary forms
|
||||
* agrees to the disclaimer below and the terms and conditions set forth
|
||||
* herein.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <sys/bio.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <cam/cam.h>
|
||||
#include <cam/cam_ccb.h>
|
||||
#include <cam/cam_sim.h>
|
||||
#include <cam/cam_xpt.h>
|
||||
#include <cam/cam_xpt_sim.h>
|
||||
#include <cam/cam_debug.h>
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
#include <cam/scsi/scsi_message.h>
|
||||
|
||||
#include <machine/resource.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/amr/amrreg.h>
|
||||
#include <dev/amr/amrvar.h>
|
||||
|
||||
static int amr_cam_probe(device_t dev);
|
||||
static int amr_cam_attach(device_t dev);
|
||||
static int amr_cam_detach(device_t dev);
|
||||
static void amr_cam_action(struct cam_sim *sim, union ccb *ccb);
|
||||
static void amr_cam_poll(struct cam_sim *sim);
|
||||
static void amr_cam_complete(struct amr_command *ac);
|
||||
static int amr_cam_command(struct amr_softc *sc, struct amr_command **acp);
|
||||
|
||||
static devclass_t amr_pass_devclass;
|
||||
|
||||
static device_method_t amr_pass_methods[] = {
|
||||
DEVMETHOD(device_probe, amr_cam_probe),
|
||||
DEVMETHOD(device_attach, amr_cam_attach),
|
||||
DEVMETHOD(device_detach, amr_cam_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t amr_pass_driver = {
|
||||
"amrp",
|
||||
amr_pass_methods,
|
||||
0
|
||||
};
|
||||
|
||||
DRIVER_MODULE(amrp, amr, amr_pass_driver, amr_pass_devclass, 0, 0);
|
||||
MODULE_DEPEND(amrp, cam, 1, 1, 1);
|
||||
|
||||
static MALLOC_DEFINE(M_AMRCAM, "amrcam", "AMR CAM memory");
|
||||
|
||||
/***********************************************************************
|
||||
* Enqueue/dequeue functions
|
||||
*/
|
||||
static __inline void
|
||||
amr_enqueue_ccb(struct amr_softc *sc, union ccb *ccb)
|
||||
{
|
||||
|
||||
TAILQ_INSERT_TAIL(&sc->amr_cam_ccbq, &ccb->ccb_h, sim_links.tqe);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
amr_requeue_ccb(struct amr_softc *sc, union ccb *ccb)
|
||||
{
|
||||
|
||||
TAILQ_INSERT_HEAD(&sc->amr_cam_ccbq, &ccb->ccb_h, sim_links.tqe);
|
||||
}
|
||||
|
||||
static __inline union ccb *
|
||||
amr_dequeue_ccb(struct amr_softc *sc)
|
||||
{
|
||||
union ccb *ccb;
|
||||
|
||||
if ((ccb = (union ccb *)TAILQ_FIRST(&sc->amr_cam_ccbq)) != NULL)
|
||||
TAILQ_REMOVE(&sc->amr_cam_ccbq, &ccb->ccb_h, sim_links.tqe);
|
||||
return(ccb);
|
||||
}
|
||||
|
||||
static int
|
||||
amr_cam_probe(device_t dev)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Attach our 'real' SCSI channels to CAM
|
||||
*/
|
||||
static int
|
||||
amr_cam_attach(device_t dev)
|
||||
{
|
||||
struct amr_softc *sc;
|
||||
struct cam_devq *devq;
|
||||
int chn, error;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
/* initialise the ccb queue */
|
||||
TAILQ_INIT(&sc->amr_cam_ccbq);
|
||||
|
||||
/*
|
||||
* Allocate a devq for all our channels combined. This should
|
||||
* allow for the maximum number of SCSI commands we will accept
|
||||
* at one time. Save the pointer in the softc so we can find it later
|
||||
* during detach.
|
||||
*/
|
||||
if ((devq = cam_simq_alloc(AMR_MAX_SCSI_CMDS)) == NULL)
|
||||
return(ENOMEM);
|
||||
sc->amr_cam_devq = devq;
|
||||
|
||||
/*
|
||||
* Iterate over our channels, registering them with CAM
|
||||
*/
|
||||
for (chn = 0; chn < sc->amr_maxchan; chn++) {
|
||||
/* allocate a sim */
|
||||
if ((sc->amr_cam_sim[chn] = cam_sim_alloc(amr_cam_action,
|
||||
amr_cam_poll, "amr", sc, device_get_unit(sc->amr_dev),
|
||||
&sc->amr_list_lock, 1, AMR_MAX_SCSI_CMDS, devq)) == NULL) {
|
||||
cam_simq_free(devq);
|
||||
device_printf(sc->amr_dev, "CAM SIM attach failed\n");
|
||||
return(ENOMEM);
|
||||
}
|
||||
|
||||
/* register the bus ID so we can get it later */
|
||||
mtx_lock(&sc->amr_list_lock);
|
||||
error = xpt_bus_register(sc->amr_cam_sim[chn], sc->amr_dev,chn);
|
||||
mtx_unlock(&sc->amr_list_lock);
|
||||
if (error) {
|
||||
device_printf(sc->amr_dev,
|
||||
"CAM XPT bus registration failed\n");
|
||||
return(ENXIO);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* XXX we should scan the config and work out which devices are
|
||||
* actually protected.
|
||||
*/
|
||||
sc->amr_cam_command = amr_cam_command;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Disconnect ourselves from CAM
|
||||
*/
|
||||
static int
|
||||
amr_cam_detach(device_t dev)
|
||||
{
|
||||
struct amr_softc *sc;
|
||||
int chn;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
mtx_lock(&sc->amr_list_lock);
|
||||
for (chn = 0; chn < sc->amr_maxchan; chn++) {
|
||||
/*
|
||||
* If a sim was allocated for this channel, free it
|
||||
*/
|
||||
if (sc->amr_cam_sim[chn] != NULL) {
|
||||
xpt_bus_deregister(cam_sim_path(sc->amr_cam_sim[chn]));
|
||||
cam_sim_free(sc->amr_cam_sim[chn], FALSE);
|
||||
}
|
||||
}
|
||||
mtx_unlock(&sc->amr_list_lock);
|
||||
|
||||
/* Now free the devq */
|
||||
if (sc->amr_cam_devq != NULL)
|
||||
cam_simq_free(sc->amr_cam_devq);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
***********************************************************************
|
||||
CAM passthrough interface
|
||||
***********************************************************************
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
* Handle a request for action from CAM
|
||||
*/
|
||||
static void
|
||||
amr_cam_action(struct cam_sim *sim, union ccb *ccb)
|
||||
{
|
||||
struct amr_softc *sc = cam_sim_softc(sim);
|
||||
|
||||
switch(ccb->ccb_h.func_code) {
|
||||
/*
|
||||
* Perform SCSI I/O to a physical device.
|
||||
*/
|
||||
case XPT_SCSI_IO:
|
||||
{
|
||||
struct ccb_hdr *ccbh = &ccb->ccb_h;
|
||||
struct ccb_scsiio *csio = &ccb->csio;
|
||||
|
||||
/* Validate the CCB */
|
||||
ccbh->status = CAM_REQ_INPROG;
|
||||
|
||||
/* check the CDB length */
|
||||
if (csio->cdb_len > AMR_MAX_EXTCDB_LEN)
|
||||
ccbh->status = CAM_REQ_INVALID;
|
||||
|
||||
if ((csio->cdb_len > AMR_MAX_CDB_LEN) &&
|
||||
(sc->support_ext_cdb == 0))
|
||||
ccbh->status = CAM_REQ_INVALID;
|
||||
|
||||
/* check that the CDB pointer is not to a physical address */
|
||||
if ((ccbh->flags & CAM_CDB_POINTER) &&
|
||||
(ccbh->flags & CAM_CDB_PHYS))
|
||||
ccbh->status = CAM_REQ_INVALID;
|
||||
/*
|
||||
* if there is data transfer, it must be to/from a virtual
|
||||
* address
|
||||
*/
|
||||
if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
|
||||
if ((ccbh->flags & CAM_DATA_MASK) != CAM_DATA_VADDR)
|
||||
/* we can't map it */
|
||||
ccbh->status = CAM_REQ_INVALID;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the command is to a LUN other than 0, fail it.
|
||||
* This is probably incorrect, but during testing the
|
||||
* firmware did not seem to respect the LUN field, and thus
|
||||
* devices appear echoed.
|
||||
*/
|
||||
if (csio->ccb_h.target_lun != 0)
|
||||
ccbh->status = CAM_DEV_NOT_THERE;
|
||||
|
||||
/* if we're happy with the request, queue it for attention */
|
||||
if (ccbh->status == CAM_REQ_INPROG) {
|
||||
/* save the channel number in the ccb */
|
||||
csio->ccb_h.sim_priv.entries[0].field= cam_sim_bus(sim);
|
||||
|
||||
amr_enqueue_ccb(sc, ccb);
|
||||
amr_startio(sc);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case XPT_CALC_GEOMETRY:
|
||||
{
|
||||
cam_calc_geometry(&ccb->ccg, /*extended*/1);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return path stats. Some of these should probably be amended.
|
||||
*/
|
||||
case XPT_PATH_INQ:
|
||||
{
|
||||
struct ccb_pathinq *cpi = & ccb->cpi;
|
||||
|
||||
debug(3, "XPT_PATH_INQ");
|
||||
cpi->version_num = 1; /* XXX??? */
|
||||
cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
|
||||
cpi->target_sprt = 0;
|
||||
cpi->hba_misc = PIM_NOBUSRESET|PIM_SEQSCAN;
|
||||
cpi->hba_eng_cnt = 0;
|
||||
cpi->max_target = AMR_MAX_TARGETS;
|
||||
cpi->max_lun = 0 /* AMR_MAX_LUNS*/;
|
||||
cpi->initiator_id = 7; /* XXX variable? */
|
||||
strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
|
||||
strlcpy(cpi->hba_vid, "LSI", HBA_IDLEN);
|
||||
strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
|
||||
cpi->unit_number = cam_sim_unit(sim);
|
||||
cpi->bus_id = cam_sim_bus(sim);
|
||||
cpi->base_transfer_speed = 132 * 1024; /* XXX */
|
||||
cpi->transport = XPORT_SPI;
|
||||
cpi->transport_version = 2;
|
||||
cpi->protocol = PROTO_SCSI;
|
||||
cpi->protocol_version = SCSI_REV_2;
|
||||
cpi->ccb_h.status = CAM_REQ_CMP;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case XPT_RESET_BUS:
|
||||
{
|
||||
struct ccb_pathinq *cpi = & ccb->cpi;
|
||||
|
||||
debug(1, "XPT_RESET_BUS");
|
||||
cpi->ccb_h.status = CAM_REQ_CMP;
|
||||
break;
|
||||
}
|
||||
|
||||
case XPT_RESET_DEV:
|
||||
{
|
||||
debug(1, "XPT_RESET_DEV");
|
||||
ccb->ccb_h.status = CAM_REQ_CMP;
|
||||
break;
|
||||
}
|
||||
|
||||
case XPT_GET_TRAN_SETTINGS:
|
||||
{
|
||||
struct ccb_trans_settings *cts = &(ccb->cts);
|
||||
|
||||
debug(3, "XPT_GET_TRAN_SETTINGS");
|
||||
|
||||
struct ccb_trans_settings_scsi *scsi;
|
||||
struct ccb_trans_settings_spi *spi;
|
||||
|
||||
scsi = &cts->proto_specific.scsi;
|
||||
spi = &cts->xport_specific.spi;
|
||||
|
||||
cts->protocol = PROTO_SCSI;
|
||||
cts->protocol_version = SCSI_REV_2;
|
||||
cts->transport = XPORT_SPI;
|
||||
cts->transport_version = 2;
|
||||
|
||||
if (cts->type == CTS_TYPE_USER_SETTINGS) {
|
||||
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
spi->flags = CTS_SPI_FLAGS_DISC_ENB;
|
||||
spi->bus_width = MSG_EXT_WDTR_BUS_32_BIT;
|
||||
spi->sync_period = 6; /* 40MHz how wide is this bus? */
|
||||
spi->sync_offset = 31; /* How to extract this from board? */
|
||||
|
||||
spi->valid = CTS_SPI_VALID_SYNC_RATE
|
||||
| CTS_SPI_VALID_SYNC_OFFSET
|
||||
| CTS_SPI_VALID_BUS_WIDTH
|
||||
| CTS_SPI_VALID_DISC;
|
||||
scsi->valid = CTS_SCSI_VALID_TQ;
|
||||
ccb->ccb_h.status = CAM_REQ_CMP;
|
||||
break;
|
||||
}
|
||||
|
||||
case XPT_SET_TRAN_SETTINGS:
|
||||
debug(3, "XPT_SET_TRAN_SETTINGS");
|
||||
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Reject anything else as unsupported.
|
||||
*/
|
||||
default:
|
||||
/* we can't do this */
|
||||
ccb->ccb_h.status = CAM_REQ_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
mtx_assert(&sc->amr_list_lock, MA_OWNED);
|
||||
xpt_done(ccb);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Convert a CAM CCB off the top of the CCB queue to a passthrough SCSI
|
||||
* command.
|
||||
*/
|
||||
static int
|
||||
amr_cam_command(struct amr_softc *sc, struct amr_command **acp)
|
||||
{
|
||||
struct amr_command *ac;
|
||||
struct amr_passthrough *ap;
|
||||
struct amr_ext_passthrough *aep;
|
||||
struct ccb_scsiio *csio;
|
||||
int bus, target, error;
|
||||
|
||||
error = 0;
|
||||
ac = NULL;
|
||||
ap = NULL;
|
||||
aep = NULL;
|
||||
|
||||
/* check to see if there is a ccb for us to work with */
|
||||
if ((csio = (struct ccb_scsiio *)amr_dequeue_ccb(sc)) == NULL)
|
||||
goto out;
|
||||
|
||||
/* get bus/target, XXX validate against protected devices? */
|
||||
bus = csio->ccb_h.sim_priv.entries[0].field;
|
||||
target = csio->ccb_h.target_id;
|
||||
|
||||
/*
|
||||
* Build a passthrough command.
|
||||
*/
|
||||
|
||||
/* construct command */
|
||||
if ((ac = amr_alloccmd(sc)) == NULL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* construct passthrough */
|
||||
if (sc->support_ext_cdb ) {
|
||||
aep = &ac->ac_ccb->ccb_epthru;
|
||||
aep->ap_timeout = 2;
|
||||
aep->ap_ars = 1;
|
||||
aep->ap_request_sense_length = 14;
|
||||
aep->ap_islogical = 0;
|
||||
aep->ap_channel = bus;
|
||||
aep->ap_scsi_id = target;
|
||||
aep->ap_logical_drive_no = csio->ccb_h.target_lun;
|
||||
aep->ap_cdb_length = csio->cdb_len;
|
||||
aep->ap_data_transfer_length = csio->dxfer_len;
|
||||
if (csio->ccb_h.flags & CAM_CDB_POINTER) {
|
||||
bcopy(csio->cdb_io.cdb_ptr, aep->ap_cdb, csio->cdb_len);
|
||||
} else {
|
||||
bcopy(csio->cdb_io.cdb_bytes, aep->ap_cdb,
|
||||
csio->cdb_len);
|
||||
}
|
||||
/*
|
||||
* we leave the data s/g list and s/g count to the map routine
|
||||
* later
|
||||
*/
|
||||
|
||||
debug(2, " COMMAND %x/%d+%d to %d:%d:%d", aep->ap_cdb[0],
|
||||
aep->ap_cdb_length, csio->dxfer_len, aep->ap_channel,
|
||||
aep->ap_scsi_id, aep->ap_logical_drive_no);
|
||||
|
||||
} else {
|
||||
ap = &ac->ac_ccb->ccb_pthru;
|
||||
ap->ap_timeout = 0;
|
||||
ap->ap_ars = 1;
|
||||
ap->ap_request_sense_length = 14;
|
||||
ap->ap_islogical = 0;
|
||||
ap->ap_channel = bus;
|
||||
ap->ap_scsi_id = target;
|
||||
ap->ap_logical_drive_no = csio->ccb_h.target_lun;
|
||||
ap->ap_cdb_length = csio->cdb_len;
|
||||
ap->ap_data_transfer_length = csio->dxfer_len;
|
||||
if (csio->ccb_h.flags & CAM_CDB_POINTER) {
|
||||
bcopy(csio->cdb_io.cdb_ptr, ap->ap_cdb, csio->cdb_len);
|
||||
} else {
|
||||
bcopy(csio->cdb_io.cdb_bytes, ap->ap_cdb,
|
||||
csio->cdb_len);
|
||||
}
|
||||
/*
|
||||
* we leave the data s/g list and s/g count to the map routine
|
||||
* later
|
||||
*/
|
||||
|
||||
debug(2, " COMMAND %x/%d+%d to %d:%d:%d", ap->ap_cdb[0],
|
||||
ap->ap_cdb_length, csio->dxfer_len, ap->ap_channel,
|
||||
ap->ap_scsi_id, ap->ap_logical_drive_no);
|
||||
}
|
||||
|
||||
ac->ac_flags |= AMR_CMD_CCB;
|
||||
|
||||
ac->ac_data = csio->data_ptr;
|
||||
ac->ac_length = csio->dxfer_len;
|
||||
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
|
||||
ac->ac_flags |= AMR_CMD_DATAIN;
|
||||
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
|
||||
ac->ac_flags |= AMR_CMD_DATAOUT;
|
||||
|
||||
ac->ac_private = csio;
|
||||
ac->ac_complete = amr_cam_complete;
|
||||
if ( sc->support_ext_cdb ) {
|
||||
ac->ac_mailbox.mb_command = AMR_CMD_EXTPASS;
|
||||
} else {
|
||||
ac->ac_mailbox.mb_command = AMR_CMD_PASS;
|
||||
}
|
||||
|
||||
out:
|
||||
if (error != 0) {
|
||||
if (ac != NULL)
|
||||
amr_releasecmd(ac);
|
||||
if (csio != NULL)
|
||||
/* put it back and try again later */
|
||||
amr_requeue_ccb(sc, (union ccb *)csio);
|
||||
}
|
||||
*acp = ac;
|
||||
return(error);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* Check for interrupt status
|
||||
*/
|
||||
static void
|
||||
amr_cam_poll(struct cam_sim *sim)
|
||||
{
|
||||
|
||||
amr_done(cam_sim_softc(sim));
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Handle completion of a command submitted via CAM.
|
||||
*/
|
||||
static void
|
||||
amr_cam_complete(struct amr_command *ac)
|
||||
{
|
||||
struct amr_passthrough *ap;
|
||||
struct amr_ext_passthrough *aep;
|
||||
struct ccb_scsiio *csio;
|
||||
struct scsi_inquiry_data *inq;
|
||||
int scsi_status, cdb0;
|
||||
|
||||
ap = &ac->ac_ccb->ccb_pthru;
|
||||
aep = &ac->ac_ccb->ccb_epthru;
|
||||
csio = (struct ccb_scsiio *)ac->ac_private;
|
||||
inq = (struct scsi_inquiry_data *)csio->data_ptr;
|
||||
|
||||
if (ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS)
|
||||
scsi_status = aep->ap_scsi_status;
|
||||
else
|
||||
scsi_status = ap->ap_scsi_status;
|
||||
debug(1, "status 0x%x AP scsi_status 0x%x", ac->ac_status,
|
||||
scsi_status);
|
||||
|
||||
/* Make sure the status is sane */
|
||||
if ((ac->ac_status != AMR_STATUS_SUCCESS) && (scsi_status == 0)) {
|
||||
csio->ccb_h.status = CAM_REQ_CMP_ERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hide disks from CAM so that they're not picked up and treated as
|
||||
* 'normal' disks.
|
||||
*
|
||||
* If the configuration provides a mechanism to mark a disk a "not
|
||||
* managed", we could add handling for that to allow disks to be
|
||||
* selectively visible.
|
||||
*/
|
||||
|
||||
/* handle passthrough SCSI status */
|
||||
switch(scsi_status) {
|
||||
case 0: /* completed OK */
|
||||
if (ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS)
|
||||
cdb0 = aep->ap_cdb[0];
|
||||
else
|
||||
cdb0 = ap->ap_cdb[0];
|
||||
if ((cdb0 == INQUIRY) && (SID_TYPE(inq) == T_DIRECT))
|
||||
inq->device = (inq->device & 0xe0) | T_NODEVICE;
|
||||
csio->ccb_h.status = CAM_REQ_CMP;
|
||||
break;
|
||||
|
||||
case 0x02:
|
||||
csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
|
||||
csio->scsi_status = SCSI_STATUS_CHECK_COND;
|
||||
if (ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS)
|
||||
bcopy(aep->ap_request_sense_area, &csio->sense_data,
|
||||
AMR_MAX_REQ_SENSE_LEN);
|
||||
else
|
||||
bcopy(ap->ap_request_sense_area, &csio->sense_data,
|
||||
AMR_MAX_REQ_SENSE_LEN);
|
||||
csio->sense_len = AMR_MAX_REQ_SENSE_LEN;
|
||||
csio->ccb_h.status |= CAM_AUTOSNS_VALID;
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
csio->ccb_h.status = CAM_SCSI_BUSY;
|
||||
break;
|
||||
|
||||
case 0xf0:
|
||||
case 0xf4:
|
||||
default:
|
||||
/*
|
||||
* Non-zero LUNs are already filtered, so there's no need
|
||||
* to return CAM_DEV_NOT_THERE.
|
||||
*/
|
||||
csio->ccb_h.status = CAM_SEL_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
|
||||
debug(2, "%*D\n", imin(csio->dxfer_len, 16), csio->data_ptr,
|
||||
" ");
|
||||
|
||||
mtx_lock(&ac->ac_sc->amr_list_lock);
|
||||
xpt_done((union ccb *)csio);
|
||||
amr_releasecmd(ac);
|
||||
mtx_unlock(&ac->ac_sc->amr_list_lock);
|
||||
}
|
@ -1,267 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 1999 Jonathan Lemon
|
||||
* Copyright (c) 1999, 2000 Michael Smith
|
||||
* Copyright (c) 2000 BSDi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 2002 Eric Moore
|
||||
* Copyright (c) 2002 LSI Logic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The party using or redistributing the source code and binary forms
|
||||
* agrees to the disclaimer below and the terms and conditions set forth
|
||||
* herein.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* Disk driver for AMI MegaRaid controllers
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <sys/bio.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/amr/amrio.h>
|
||||
#include <dev/amr/amrreg.h>
|
||||
#include <dev/amr/amrvar.h>
|
||||
#include <dev/amr/amr_tables.h>
|
||||
|
||||
/* prototypes */
|
||||
static int amrd_probe(device_t dev);
|
||||
static int amrd_attach(device_t dev);
|
||||
static int amrd_detach(device_t dev);
|
||||
|
||||
static disk_open_t amrd_open;
|
||||
static disk_strategy_t amrd_strategy;
|
||||
|
||||
static devclass_t amrd_devclass;
|
||||
#ifdef FREEBSD_4
|
||||
int amr_disks_registered = 0;
|
||||
#endif
|
||||
|
||||
static device_method_t amrd_methods[] = {
|
||||
DEVMETHOD(device_probe, amrd_probe),
|
||||
DEVMETHOD(device_attach, amrd_attach),
|
||||
DEVMETHOD(device_detach, amrd_detach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t amrd_driver = {
|
||||
"amrd",
|
||||
amrd_methods,
|
||||
sizeof(struct amrd_softc)
|
||||
};
|
||||
|
||||
DRIVER_MODULE(amrd, amr, amrd_driver, amrd_devclass, 0, 0);
|
||||
|
||||
static int
|
||||
amrd_open(struct disk *dp)
|
||||
{
|
||||
struct amrd_softc *sc = (struct amrd_softc *)dp->d_drv1;
|
||||
|
||||
debug_called(1);
|
||||
|
||||
if (sc == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
/* controller not active? */
|
||||
if (sc->amrd_controller->amr_state & AMR_STATE_SHUTDOWN)
|
||||
return(ENXIO);
|
||||
|
||||
return (0);
|
||||
}
|
||||
/********************************************************************************
|
||||
* System crashdump support
|
||||
*/
|
||||
|
||||
static int
|
||||
amrd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length)
|
||||
{
|
||||
|
||||
struct amrd_softc *amrd_sc;
|
||||
struct amr_softc *amr_sc;
|
||||
int error;
|
||||
struct disk *dp;
|
||||
|
||||
dp = arg;
|
||||
amrd_sc = (struct amrd_softc *)dp->d_drv1;
|
||||
if (amrd_sc == NULL)
|
||||
return(ENXIO);
|
||||
amr_sc = (struct amr_softc *)amrd_sc->amrd_controller;
|
||||
|
||||
if (length > 0) {
|
||||
int driveno = amrd_sc->amrd_drive - amr_sc->amr_drive;
|
||||
if ((error = amr_dump_blocks(amr_sc,driveno,offset / AMR_BLKSIZE ,(void *)virtual,(int) length / AMR_BLKSIZE )) != 0)
|
||||
return(error);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read/write routine for a buffer. Finds the proper unit, range checks
|
||||
* arguments, and schedules the transfer. Does not wait for the transfer
|
||||
* to complete. Multi-page transfers are supported. All I/O requests must
|
||||
* be a multiple of a sector in length.
|
||||
*/
|
||||
static void
|
||||
amrd_strategy(struct bio *bio)
|
||||
{
|
||||
struct amrd_softc *sc = (struct amrd_softc *)bio->bio_disk->d_drv1;
|
||||
|
||||
/* bogus disk? */
|
||||
if (sc == NULL) {
|
||||
bio->bio_error = EINVAL;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
amr_submit_bio(sc->amrd_controller, bio);
|
||||
return;
|
||||
|
||||
bad:
|
||||
bio->bio_flags |= BIO_ERROR;
|
||||
|
||||
/*
|
||||
* Correctly set the buf to indicate a completed transfer
|
||||
*/
|
||||
bio->bio_resid = bio->bio_bcount;
|
||||
biodone(bio);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
amrd_intr(void *data)
|
||||
{
|
||||
struct bio *bio = (struct bio *)data;
|
||||
|
||||
debug_called(2);
|
||||
|
||||
if (bio->bio_flags & BIO_ERROR) {
|
||||
bio->bio_error = EIO;
|
||||
debug(1, "i/o error\n");
|
||||
} else {
|
||||
bio->bio_resid = 0;
|
||||
}
|
||||
|
||||
biodone(bio);
|
||||
}
|
||||
|
||||
static int
|
||||
amrd_probe(device_t dev)
|
||||
{
|
||||
|
||||
debug_called(1);
|
||||
|
||||
device_set_desc(dev, "LSILogic MegaRAID logical drive");
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
amrd_attach(device_t dev)
|
||||
{
|
||||
struct amrd_softc *sc = (struct amrd_softc *)device_get_softc(dev);
|
||||
device_t parent;
|
||||
|
||||
debug_called(1);
|
||||
|
||||
parent = device_get_parent(dev);
|
||||
sc->amrd_controller = (struct amr_softc *)device_get_softc(parent);
|
||||
sc->amrd_unit = device_get_unit(dev);
|
||||
sc->amrd_drive = device_get_ivars(dev);
|
||||
sc->amrd_dev = dev;
|
||||
|
||||
device_printf(dev, "%uMB (%u sectors) RAID %d (%s)\n",
|
||||
sc->amrd_drive->al_size / ((1024 * 1024) / AMR_BLKSIZE),
|
||||
sc->amrd_drive->al_size, sc->amrd_drive->al_properties & AMR_DRV_RAID_MASK,
|
||||
amr_describe_code(amr_table_drvstate, AMR_DRV_CURSTATE(sc->amrd_drive->al_state)));
|
||||
|
||||
sc->amrd_disk = disk_alloc();
|
||||
sc->amrd_disk->d_drv1 = sc;
|
||||
sc->amrd_disk->d_maxsize = (AMR_NSEG - 1) * PAGE_SIZE;
|
||||
sc->amrd_disk->d_open = amrd_open;
|
||||
sc->amrd_disk->d_strategy = amrd_strategy;
|
||||
sc->amrd_disk->d_name = "amrd";
|
||||
sc->amrd_disk->d_dump = (dumper_t *)amrd_dump;
|
||||
sc->amrd_disk->d_unit = sc->amrd_unit;
|
||||
sc->amrd_disk->d_flags = DISKFLAG_CANFLUSHCACHE;
|
||||
sc->amrd_disk->d_sectorsize = AMR_BLKSIZE;
|
||||
sc->amrd_disk->d_mediasize = (off_t)sc->amrd_drive->al_size * AMR_BLKSIZE;
|
||||
sc->amrd_disk->d_fwsectors = sc->amrd_drive->al_sectors;
|
||||
sc->amrd_disk->d_fwheads = sc->amrd_drive->al_heads;
|
||||
disk_create(sc->amrd_disk, DISK_VERSION);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
amrd_detach(device_t dev)
|
||||
{
|
||||
struct amrd_softc *sc = (struct amrd_softc *)device_get_softc(dev);
|
||||
|
||||
debug_called(1);
|
||||
|
||||
if (sc->amrd_disk->d_flags & DISKFLAG_OPEN)
|
||||
return(EBUSY);
|
||||
|
||||
#ifdef FREEBSD_4
|
||||
if (--amr_disks_registered == 0)
|
||||
cdevsw_remove(&amrddisk_cdevsw);
|
||||
#else
|
||||
disk_destroy(sc->amrd_disk);
|
||||
#endif
|
||||
return(0);
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2005 Paul Saab
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#if defined(__amd64__) /* Assume amd64 wants 32 bit Linux */
|
||||
#include <machine/../linux32/linux.h>
|
||||
#include <machine/../linux32/linux32_proto.h>
|
||||
#else
|
||||
#include <machine/../linux/linux.h>
|
||||
#include <machine/../linux/linux_proto.h>
|
||||
#endif
|
||||
#include <compat/linux/linux_ioctl.h>
|
||||
|
||||
/* There are multiple ioctl number ranges that need to be handled */
|
||||
#define AMR_LINUX_IOCTL_MIN 0x6d00
|
||||
#define AMR_LINUX_IOCTL_MAX 0x6d01
|
||||
|
||||
static linux_ioctl_function_t amr_linux_ioctl;
|
||||
static struct linux_ioctl_handler amr_linux_handler = {amr_linux_ioctl,
|
||||
AMR_LINUX_IOCTL_MIN,
|
||||
AMR_LINUX_IOCTL_MAX};
|
||||
|
||||
SYSINIT (amr_register, SI_SUB_KLD, SI_ORDER_MIDDLE,
|
||||
linux_ioctl_register_handler, &amr_linux_handler);
|
||||
SYSUNINIT(amr_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE,
|
||||
linux_ioctl_unregister_handler, &amr_linux_handler);
|
||||
|
||||
static int
|
||||
amr_linux_modevent(module_t mod, int cmd, void *data)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
DEV_MODULE(amr_linux, amr_linux_modevent, NULL);
|
||||
MODULE_DEPEND(amr, linux, 1, 1, 1);
|
||||
|
||||
static int
|
||||
amr_linux_ioctl(struct thread *p, struct linux_ioctl_args *args)
|
||||
{
|
||||
cap_rights_t rights;
|
||||
struct file *fp;
|
||||
int error;
|
||||
|
||||
error = fget(p, args->fd, cap_rights_init_one(&rights, CAP_IOCTL), &fp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = fo_ioctl(fp, args->cmd, (caddr_t)args->arg, p->td_ucred, p);
|
||||
fdrop(fp, p);
|
||||
return (error);
|
||||
}
|
@ -1,705 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1999,2000 Michael Smith
|
||||
* Copyright (c) 2000 BSDi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* Copyright (c) 2002 Eric Moore
|
||||
* Copyright (c) 2002, 2004 LSI Logic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The party using or redistributing the source code and binary forms
|
||||
* agrees to the disclaimer below and the terms and conditions set forth
|
||||
* herein.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <sys/bio.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
|
||||
#include <dev/amr/amrio.h>
|
||||
#include <dev/amr/amrreg.h>
|
||||
#include <dev/amr/amrvar.h>
|
||||
|
||||
static int amr_pci_probe(device_t dev);
|
||||
static int amr_pci_attach(device_t dev);
|
||||
static int amr_pci_detach(device_t dev);
|
||||
static int amr_pci_shutdown(device_t dev);
|
||||
static int amr_pci_suspend(device_t dev);
|
||||
static int amr_pci_resume(device_t dev);
|
||||
static void amr_pci_intr(void *arg);
|
||||
static void amr_pci_free(struct amr_softc *sc);
|
||||
static void amr_sglist_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error);
|
||||
static int amr_sglist_map(struct amr_softc *sc);
|
||||
static int amr_setup_mbox(struct amr_softc *sc);
|
||||
static int amr_ccb_map(struct amr_softc *sc);
|
||||
|
||||
static u_int amr_force_sg32 = 0;
|
||||
SYSCTL_DECL(_hw_amr);
|
||||
SYSCTL_UINT(_hw_amr, OID_AUTO, force_sg32, CTLFLAG_RDTUN, &amr_force_sg32, 0,
|
||||
"Force the AMR driver to use 32bit scatter gather");
|
||||
|
||||
static device_method_t amr_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, amr_pci_probe),
|
||||
DEVMETHOD(device_attach, amr_pci_attach),
|
||||
DEVMETHOD(device_detach, amr_pci_detach),
|
||||
DEVMETHOD(device_shutdown, amr_pci_shutdown),
|
||||
DEVMETHOD(device_suspend, amr_pci_suspend),
|
||||
DEVMETHOD(device_resume, amr_pci_resume),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
static driver_t amr_pci_driver = {
|
||||
"amr",
|
||||
amr_methods,
|
||||
sizeof(struct amr_softc)
|
||||
};
|
||||
|
||||
static struct amr_ident
|
||||
{
|
||||
uint16_t vendor;
|
||||
uint16_t device;
|
||||
int flags;
|
||||
#define AMR_ID_PROBE_SIG (1<<0) /* generic i960RD, check signature */
|
||||
#define AMR_ID_DO_SG64 (1<<1)
|
||||
#define AMR_ID_QUARTZ (1<<2)
|
||||
} amr_device_ids[] = {
|
||||
{0x101e, 0x9010, 0},
|
||||
{0x101e, 0x9060, 0},
|
||||
{0x8086, 0x1960, AMR_ID_QUARTZ | AMR_ID_PROBE_SIG},
|
||||
{0x101e, 0x1960, AMR_ID_QUARTZ},
|
||||
{0x1000, 0x1960, AMR_ID_QUARTZ | AMR_ID_DO_SG64 | AMR_ID_PROBE_SIG},
|
||||
{0x1000, 0x0407, AMR_ID_QUARTZ | AMR_ID_DO_SG64},
|
||||
{0x1000, 0x0408, AMR_ID_QUARTZ | AMR_ID_DO_SG64},
|
||||
{0x1000, 0x0409, AMR_ID_QUARTZ | AMR_ID_DO_SG64},
|
||||
{0x1028, 0x000e, AMR_ID_QUARTZ | AMR_ID_DO_SG64 | AMR_ID_PROBE_SIG}, /* perc4/di i960 */
|
||||
{0x1028, 0x000f, AMR_ID_QUARTZ | AMR_ID_DO_SG64}, /* perc4/di Verde*/
|
||||
{0x1028, 0x0013, AMR_ID_QUARTZ | AMR_ID_DO_SG64}, /* perc4/di */
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
static devclass_t amr_devclass;
|
||||
DRIVER_MODULE(amr, pci, amr_pci_driver, amr_devclass, 0, 0);
|
||||
MODULE_PNP_INFO("U16:vendor;U16:device", pci, amr, amr_device_ids,
|
||||
nitems(amr_device_ids) - 1);
|
||||
MODULE_DEPEND(amr, pci, 1, 1, 1);
|
||||
MODULE_DEPEND(amr, cam, 1, 1, 1);
|
||||
|
||||
static struct amr_ident *
|
||||
amr_find_ident(device_t dev)
|
||||
{
|
||||
struct amr_ident *id;
|
||||
int sig;
|
||||
|
||||
for (id = amr_device_ids; id->vendor != 0; id++) {
|
||||
if ((pci_get_vendor(dev) == id->vendor) &&
|
||||
(pci_get_device(dev) == id->device)) {
|
||||
/* do we need to test for a signature? */
|
||||
if (id->flags & AMR_ID_PROBE_SIG) {
|
||||
sig = pci_read_config(dev, AMR_CFG_SIG, 2);
|
||||
if ((sig != AMR_SIGNATURE_1) && (sig != AMR_SIGNATURE_2))
|
||||
continue;
|
||||
}
|
||||
return (id);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
amr_pci_probe(device_t dev)
|
||||
{
|
||||
|
||||
debug_called(1);
|
||||
|
||||
if (amr_find_ident(dev) != NULL) {
|
||||
device_set_desc(dev, LSI_DESC_PCI);
|
||||
return(BUS_PROBE_DEFAULT);
|
||||
}
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
amr_pci_attach(device_t dev)
|
||||
{
|
||||
struct amr_softc *sc;
|
||||
struct amr_ident *id;
|
||||
int rid, rtype, error;
|
||||
|
||||
debug_called(1);
|
||||
|
||||
/*
|
||||
* Initialise softc.
|
||||
*/
|
||||
sc = device_get_softc(dev);
|
||||
bzero(sc, sizeof(*sc));
|
||||
sc->amr_dev = dev;
|
||||
|
||||
/* assume failure is 'not configured' */
|
||||
error = ENXIO;
|
||||
|
||||
/*
|
||||
* Determine board type.
|
||||
*/
|
||||
if ((id = amr_find_ident(dev)) == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
if (id->flags & AMR_ID_QUARTZ) {
|
||||
sc->amr_type |= AMR_TYPE_QUARTZ;
|
||||
}
|
||||
|
||||
if ((amr_force_sg32 == 0) && (id->flags & AMR_ID_DO_SG64) &&
|
||||
(sizeof(vm_paddr_t) > 4)) {
|
||||
device_printf(dev, "Using 64-bit DMA\n");
|
||||
sc->amr_type |= AMR_TYPE_SG64;
|
||||
}
|
||||
|
||||
/* force the busmaster enable bit on */
|
||||
pci_enable_busmaster(dev);
|
||||
|
||||
/*
|
||||
* Allocate the PCI register window.
|
||||
*/
|
||||
rid = PCIR_BAR(0);
|
||||
rtype = AMR_IS_QUARTZ(sc) ? SYS_RES_MEMORY : SYS_RES_IOPORT;
|
||||
sc->amr_reg = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE);
|
||||
if (sc->amr_reg == NULL) {
|
||||
device_printf(sc->amr_dev, "can't allocate register window\n");
|
||||
goto out;
|
||||
}
|
||||
sc->amr_btag = rman_get_bustag(sc->amr_reg);
|
||||
sc->amr_bhandle = rman_get_bushandle(sc->amr_reg);
|
||||
|
||||
/*
|
||||
* Allocate and connect our interrupt.
|
||||
*/
|
||||
rid = 0;
|
||||
sc->amr_irq = bus_alloc_resource_any(sc->amr_dev, SYS_RES_IRQ, &rid,
|
||||
RF_SHAREABLE | RF_ACTIVE);
|
||||
if (sc->amr_irq == NULL) {
|
||||
device_printf(sc->amr_dev, "can't allocate interrupt\n");
|
||||
goto out;
|
||||
}
|
||||
if (bus_setup_intr(sc->amr_dev, sc->amr_irq,
|
||||
INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE, NULL, amr_pci_intr,
|
||||
sc, &sc->amr_intr)) {
|
||||
device_printf(sc->amr_dev, "can't set up interrupt\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
debug(2, "interrupt attached");
|
||||
|
||||
/* assume failure is 'out of memory' */
|
||||
error = ENOMEM;
|
||||
|
||||
/*
|
||||
* Allocate the parent bus DMA tag appropriate for PCI.
|
||||
*/
|
||||
if (bus_dma_tag_create(bus_get_dma_tag(dev), /* PCI parent */
|
||||
1, 0, /* alignment,boundary */
|
||||
AMR_IS_SG64(sc) ?
|
||||
BUS_SPACE_MAXADDR :
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
BUS_SPACE_MAXSIZE, /* maxsize */
|
||||
BUS_SPACE_UNRESTRICTED, /* nsegments */
|
||||
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
|
||||
0, /* flags */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&sc->amr_parent_dmat)) {
|
||||
device_printf(dev, "can't allocate parent DMA tag\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create DMA tag for mapping buffers into controller-addressable space.
|
||||
*/
|
||||
if (bus_dma_tag_create(sc->amr_parent_dmat, /* parent */
|
||||
1, 0, /* alignment,boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
DFLTPHYS, /* maxsize */
|
||||
AMR_NSEG, /* nsegments */
|
||||
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
|
||||
0, /* flags */
|
||||
busdma_lock_mutex, /* lockfunc */
|
||||
&sc->amr_list_lock, /* lockarg */
|
||||
&sc->amr_buffer_dmat)) {
|
||||
device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (bus_dma_tag_create(sc->amr_parent_dmat, /* parent */
|
||||
1, 0, /* alignment,boundary */
|
||||
BUS_SPACE_MAXADDR, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
DFLTPHYS, /* maxsize */
|
||||
AMR_NSEG, /* nsegments */
|
||||
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
|
||||
0, /* flags */
|
||||
busdma_lock_mutex, /* lockfunc */
|
||||
&sc->amr_list_lock, /* lockarg */
|
||||
&sc->amr_buffer64_dmat)) {
|
||||
device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
debug(2, "dma tag done");
|
||||
|
||||
/*
|
||||
* Allocate and set up mailbox in a bus-visible fashion.
|
||||
*/
|
||||
mtx_init(&sc->amr_list_lock, "AMR List Lock", NULL, MTX_DEF);
|
||||
mtx_init(&sc->amr_hw_lock, "AMR HW Lock", NULL, MTX_DEF);
|
||||
if ((error = amr_setup_mbox(sc)) != 0)
|
||||
goto out;
|
||||
|
||||
debug(2, "mailbox setup");
|
||||
|
||||
/*
|
||||
* Build the scatter/gather buffers.
|
||||
*/
|
||||
if ((error = amr_sglist_map(sc)) != 0)
|
||||
goto out;
|
||||
debug(2, "s/g list mapped");
|
||||
|
||||
if ((error = amr_ccb_map(sc)) != 0)
|
||||
goto out;
|
||||
debug(2, "ccb mapped");
|
||||
|
||||
/*
|
||||
* Do bus-independant initialisation, bring controller online.
|
||||
*/
|
||||
error = amr_attach(sc);
|
||||
|
||||
out:
|
||||
if (error)
|
||||
amr_pci_free(sc);
|
||||
else
|
||||
gone_in_dev(dev, 13, "amr(4) driver");
|
||||
return(error);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Disconnect from the controller completely, in preparation for unload.
|
||||
*/
|
||||
static int
|
||||
amr_pci_detach(device_t dev)
|
||||
{
|
||||
struct amr_softc *sc = device_get_softc(dev);
|
||||
int error;
|
||||
|
||||
debug_called(1);
|
||||
|
||||
if (sc->amr_state & AMR_STATE_OPEN)
|
||||
return(EBUSY);
|
||||
|
||||
if ((error = amr_pci_shutdown(dev)))
|
||||
return(error);
|
||||
|
||||
amr_pci_free(sc);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Bring the controller down to a dormant state and detach all child devices.
|
||||
*
|
||||
* This function is called before detach, system shutdown, or before performing
|
||||
* an operation which may add or delete system disks. (Call amr_startup to
|
||||
* resume normal operation.)
|
||||
*
|
||||
* Note that we can assume that the bioq on the controller is empty, as we won't
|
||||
* allow shutdown if any device is open.
|
||||
*/
|
||||
static int
|
||||
amr_pci_shutdown(device_t dev)
|
||||
{
|
||||
struct amr_softc *sc = device_get_softc(dev);
|
||||
int i,error;
|
||||
|
||||
debug_called(1);
|
||||
|
||||
/* mark ourselves as in-shutdown */
|
||||
sc->amr_state |= AMR_STATE_SHUTDOWN;
|
||||
|
||||
/* flush controller */
|
||||
device_printf(sc->amr_dev, "flushing cache...");
|
||||
printf("%s\n", amr_flush(sc) ? "failed" : "done");
|
||||
|
||||
error = 0;
|
||||
|
||||
/* delete all our child devices */
|
||||
for(i = 0 ; i < AMR_MAXLD; i++) {
|
||||
if( sc->amr_drive[i].al_disk != 0) {
|
||||
if((error = device_delete_child(sc->amr_dev,sc->amr_drive[i].al_disk)) != 0)
|
||||
goto shutdown_out;
|
||||
sc->amr_drive[i].al_disk = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX disable interrupts? */
|
||||
|
||||
shutdown_out:
|
||||
return(error);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Bring the controller to a quiescent state, ready for system suspend.
|
||||
*/
|
||||
static int
|
||||
amr_pci_suspend(device_t dev)
|
||||
{
|
||||
struct amr_softc *sc = device_get_softc(dev);
|
||||
|
||||
debug_called(1);
|
||||
|
||||
sc->amr_state |= AMR_STATE_SUSPEND;
|
||||
|
||||
/* flush controller */
|
||||
device_printf(sc->amr_dev, "flushing cache...");
|
||||
printf("%s\n", amr_flush(sc) ? "failed" : "done");
|
||||
|
||||
/* XXX disable interrupts? */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Bring the controller back to a state ready for operation.
|
||||
*/
|
||||
static int
|
||||
amr_pci_resume(device_t dev)
|
||||
{
|
||||
struct amr_softc *sc = device_get_softc(dev);
|
||||
|
||||
debug_called(1);
|
||||
|
||||
sc->amr_state &= ~AMR_STATE_SUSPEND;
|
||||
|
||||
/* XXX enable interrupts? */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Take an interrupt, or be poked by other code to look for interrupt-worthy
|
||||
* status.
|
||||
*/
|
||||
static void
|
||||
amr_pci_intr(void *arg)
|
||||
{
|
||||
struct amr_softc *sc = (struct amr_softc *)arg;
|
||||
|
||||
debug_called(3);
|
||||
|
||||
/* collect finished commands, queue anything waiting */
|
||||
amr_done(sc);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Free all of the resources associated with (sc)
|
||||
*
|
||||
* Should not be called if the controller is active.
|
||||
*/
|
||||
static void
|
||||
amr_pci_free(struct amr_softc *sc)
|
||||
{
|
||||
void *p;
|
||||
|
||||
debug_called(1);
|
||||
|
||||
amr_free(sc);
|
||||
|
||||
/* destroy data-transfer DMA tag */
|
||||
if (sc->amr_buffer_dmat)
|
||||
bus_dma_tag_destroy(sc->amr_buffer_dmat);
|
||||
if (sc->amr_buffer64_dmat)
|
||||
bus_dma_tag_destroy(sc->amr_buffer64_dmat);
|
||||
|
||||
/* free and destroy DMA memory and tag for passthrough pool */
|
||||
if (sc->amr_ccb) {
|
||||
bus_dmamap_unload(sc->amr_ccb_dmat, sc->amr_ccb_dmamap);
|
||||
bus_dmamem_free(sc->amr_ccb_dmat, sc->amr_ccb, sc->amr_ccb_dmamap);
|
||||
}
|
||||
if (sc->amr_ccb_dmat)
|
||||
bus_dma_tag_destroy(sc->amr_ccb_dmat);
|
||||
|
||||
/* free and destroy DMA memory and tag for s/g lists */
|
||||
if (sc->amr_sgtable) {
|
||||
bus_dmamap_unload(sc->amr_sg_dmat, sc->amr_sg_dmamap);
|
||||
bus_dmamem_free(sc->amr_sg_dmat, sc->amr_sgtable, sc->amr_sg_dmamap);
|
||||
}
|
||||
if (sc->amr_sg_dmat)
|
||||
bus_dma_tag_destroy(sc->amr_sg_dmat);
|
||||
|
||||
/* free and destroy DMA memory and tag for mailbox */
|
||||
p = (void *)(uintptr_t)(volatile void *)sc->amr_mailbox64;
|
||||
if (sc->amr_mailbox) {
|
||||
bus_dmamap_unload(sc->amr_mailbox_dmat, sc->amr_mailbox_dmamap);
|
||||
bus_dmamem_free(sc->amr_mailbox_dmat, p, sc->amr_mailbox_dmamap);
|
||||
}
|
||||
if (sc->amr_mailbox_dmat)
|
||||
bus_dma_tag_destroy(sc->amr_mailbox_dmat);
|
||||
|
||||
/* disconnect the interrupt handler */
|
||||
if (sc->amr_intr)
|
||||
bus_teardown_intr(sc->amr_dev, sc->amr_irq, sc->amr_intr);
|
||||
if (sc->amr_irq != NULL)
|
||||
bus_release_resource(sc->amr_dev, SYS_RES_IRQ, 0, sc->amr_irq);
|
||||
|
||||
/* destroy the parent DMA tag */
|
||||
if (sc->amr_parent_dmat)
|
||||
bus_dma_tag_destroy(sc->amr_parent_dmat);
|
||||
|
||||
/* release the register window mapping */
|
||||
if (sc->amr_reg != NULL)
|
||||
bus_release_resource(sc->amr_dev,
|
||||
AMR_IS_QUARTZ(sc) ? SYS_RES_MEMORY : SYS_RES_IOPORT,
|
||||
PCIR_BAR(0), sc->amr_reg);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Allocate and map the scatter/gather table in bus space.
|
||||
*/
|
||||
static void
|
||||
amr_sglist_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
|
||||
{
|
||||
uint32_t *addr;
|
||||
|
||||
debug_called(1);
|
||||
|
||||
addr = arg;
|
||||
*addr = segs[0].ds_addr;
|
||||
}
|
||||
|
||||
static int
|
||||
amr_sglist_map(struct amr_softc *sc)
|
||||
{
|
||||
size_t segsize;
|
||||
void *p;
|
||||
int error;
|
||||
|
||||
debug_called(1);
|
||||
|
||||
/*
|
||||
* Create a single tag describing a region large enough to hold all of
|
||||
* the s/g lists we will need.
|
||||
*
|
||||
* Note that we could probably use AMR_LIMITCMD here, but that may become
|
||||
* tunable.
|
||||
*/
|
||||
if (AMR_IS_SG64(sc))
|
||||
segsize = sizeof(struct amr_sg64entry) * AMR_NSEG * AMR_MAXCMD;
|
||||
else
|
||||
segsize = sizeof(struct amr_sgentry) * AMR_NSEG * AMR_MAXCMD;
|
||||
|
||||
error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */
|
||||
512, 0, /* alignment,boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
segsize, 1, /* maxsize, nsegments */
|
||||
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
|
||||
0, /* flags */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&sc->amr_sg_dmat);
|
||||
if (error != 0) {
|
||||
device_printf(sc->amr_dev, "can't allocate scatter/gather DMA tag\n");
|
||||
return(ENOMEM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate enough s/g maps for all commands and permanently map them into
|
||||
* controller-visible space.
|
||||
*
|
||||
* XXX this assumes we can get enough space for all the s/g maps in one
|
||||
* contiguous slab. We may need to switch to a more complex arrangement
|
||||
* where we allocate in smaller chunks and keep a lookup table from slot
|
||||
* to bus address.
|
||||
*
|
||||
* XXX HACK ALERT: at least some controllers don't like the s/g memory
|
||||
* being allocated below 0x2000. We leak some memory if
|
||||
* we get some below this mark and allocate again. We
|
||||
* should be able to avoid this with the tag setup, but
|
||||
* that does't seem to work.
|
||||
*/
|
||||
retry:
|
||||
error = bus_dmamem_alloc(sc->amr_sg_dmat, (void **)&p, BUS_DMA_NOWAIT, &sc->amr_sg_dmamap);
|
||||
if (error) {
|
||||
device_printf(sc->amr_dev, "can't allocate s/g table\n");
|
||||
return(ENOMEM);
|
||||
}
|
||||
bus_dmamap_load(sc->amr_sg_dmat, sc->amr_sg_dmamap, p, segsize, amr_sglist_helper, &sc->amr_sgbusaddr, 0);
|
||||
if (sc->amr_sgbusaddr < 0x2000) {
|
||||
debug(1, "s/g table too low (0x%x), reallocating\n", sc->amr_sgbusaddr);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (AMR_IS_SG64(sc))
|
||||
sc->amr_sg64table = (struct amr_sg64entry *)p;
|
||||
sc->amr_sgtable = (struct amr_sgentry *)p;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
* Allocate and set up mailbox areas for the controller (sc)
|
||||
*
|
||||
* The basic mailbox structure should be 16-byte aligned.
|
||||
*/
|
||||
static int
|
||||
amr_setup_mbox(struct amr_softc *sc)
|
||||
{
|
||||
int error;
|
||||
void *p;
|
||||
uint32_t baddr;
|
||||
|
||||
debug_called(1);
|
||||
|
||||
/*
|
||||
* Create a single tag describing a region large enough to hold the entire
|
||||
* mailbox.
|
||||
*/
|
||||
error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */
|
||||
16, 0, /* alignment,boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
sizeof(struct amr_mailbox64), /* maxsize */
|
||||
1, /* nsegments */
|
||||
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
|
||||
0, /* flags */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&sc->amr_mailbox_dmat);
|
||||
if (error != 0) {
|
||||
device_printf(sc->amr_dev, "can't allocate mailbox tag\n");
|
||||
return(ENOMEM);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the mailbox structure and permanently map it into
|
||||
* controller-visible space.
|
||||
*/
|
||||
error = bus_dmamem_alloc(sc->amr_mailbox_dmat, (void **)&p, BUS_DMA_NOWAIT,
|
||||
&sc->amr_mailbox_dmamap);
|
||||
if (error) {
|
||||
device_printf(sc->amr_dev, "can't allocate mailbox memory\n");
|
||||
return(ENOMEM);
|
||||
}
|
||||
bus_dmamap_load(sc->amr_mailbox_dmat, sc->amr_mailbox_dmamap, p,
|
||||
sizeof(struct amr_mailbox64), amr_sglist_helper, &baddr, 0);
|
||||
/*
|
||||
* Conventional mailbox is inside the mailbox64 region.
|
||||
*/
|
||||
/* save physical base of the basic mailbox structure */
|
||||
sc->amr_mailboxphys = baddr + offsetof(struct amr_mailbox64, mb);
|
||||
bzero(p, sizeof(struct amr_mailbox64));
|
||||
sc->amr_mailbox64 = (struct amr_mailbox64 *)p;
|
||||
sc->amr_mailbox = &sc->amr_mailbox64->mb;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
amr_ccb_map(struct amr_softc *sc)
|
||||
{
|
||||
int ccbsize, error;
|
||||
|
||||
/*
|
||||
* Passthrough and Extended passthrough structures will share the same
|
||||
* memory.
|
||||
*/
|
||||
ccbsize = sizeof(union amr_ccb) * AMR_MAXCMD;
|
||||
error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */
|
||||
128, 0, /* alignment,boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
ccbsize, /* maxsize */
|
||||
1, /* nsegments */
|
||||
ccbsize, /* maxsegsize */
|
||||
0, /* flags */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&sc->amr_ccb_dmat);
|
||||
if (error != 0) {
|
||||
device_printf(sc->amr_dev, "can't allocate ccb tag\n");
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
error = bus_dmamem_alloc(sc->amr_ccb_dmat, (void **)&sc->amr_ccb,
|
||||
BUS_DMA_NOWAIT, &sc->amr_ccb_dmamap);
|
||||
if (error) {
|
||||
device_printf(sc->amr_dev, "can't allocate ccb memory\n");
|
||||
return (ENOMEM);
|
||||
}
|
||||
bus_dmamap_load(sc->amr_ccb_dmat, sc->amr_ccb_dmamap, sc->amr_ccb,
|
||||
ccbsize, amr_sglist_helper, &sc->amr_ccb_busaddr, 0);
|
||||
bzero(sc->amr_ccb, ccbsize);
|
||||
|
||||
return (0);
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-3-Clause
|
||||
*
|
||||
* Copyright (c) 2000 Michael Smith
|
||||
* Copyright (c) 2000 BSDi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Copyright (c) 2002 Eric Moore
|
||||
* Copyright (c) 2002 LSI Logic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The party using or redistributing the source code and binary forms
|
||||
* agrees to the disclaimer below and the terms and conditions set forth
|
||||
* herein.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Lookup table for code-to-text translations.
|
||||
*/
|
||||
struct amr_code_lookup {
|
||||
char *string;
|
||||
u_int32_t code;
|
||||
};
|
||||
|
||||
extern char *amr_describe_code(struct amr_code_lookup *table, u_int32_t code);
|
||||
|
||||
#ifndef AMR_DEFINE_TABLES
|
||||
extern struct amr_code_lookup amr_table_qinit[];
|
||||
extern struct amr_code_lookup amr_table_sinit[];
|
||||
extern struct amr_code_lookup amr_table_drvstate[];
|
||||
|
||||
#else /* AMR_DEFINE_TABLES */
|
||||
|
||||
/********************************************************************************
|
||||
* Look up a text description of a numeric code and return a pointer to same.
|
||||
*/
|
||||
char *
|
||||
amr_describe_code(struct amr_code_lookup *table, u_int32_t code)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; table[i].string != NULL; i++)
|
||||
if (table[i].code == code)
|
||||
return(table[i].string);
|
||||
return(table[i+1].string);
|
||||
}
|
||||
|
||||
struct amr_code_lookup amr_table_qinit[] = {
|
||||
{"init scanning drives", AMR_QINIT_SCAN},
|
||||
{"init scanning initialising", AMR_QINIT_SCANINIT},
|
||||
{"init firmware initing", AMR_QINIT_FIRMWARE},
|
||||
{"init in progress", AMR_QINIT_INPROG},
|
||||
{"init spinning drives", AMR_QINIT_SPINUP},
|
||||
{"insufficient memory", AMR_QINIT_NOMEM},
|
||||
{"init flushing cache", AMR_QINIT_CACHEFLUSH},
|
||||
{"init successfully done", AMR_QINIT_DONE},
|
||||
{NULL, 0},
|
||||
{"unknown init code", 0}
|
||||
};
|
||||
|
||||
struct amr_code_lookup amr_table_sinit[] = {
|
||||
{"init abnormal terminated", AMR_SINIT_ABEND},
|
||||
{"insufficient memory", AMR_SINIT_NOMEM},
|
||||
{"firmware flushing cache", AMR_SINIT_CACHEFLUSH},
|
||||
{"init in progress", AMR_SINIT_INPROG},
|
||||
{"firmware spinning drives", AMR_SINIT_SPINUP},
|
||||
{"init successfully done", AMR_SINIT_DONE},
|
||||
{NULL, 0},
|
||||
{"unknown init code", 0}
|
||||
};
|
||||
|
||||
struct amr_code_lookup amr_table_drvstate[] = {
|
||||
{"offline", AMR_DRV_OFFLINE},
|
||||
{"degraded", AMR_DRV_DEGRADED},
|
||||
{"optimal", AMR_DRV_OPTIMAL},
|
||||
{"online", AMR_DRV_ONLINE},
|
||||
{"failed", AMR_DRV_FAILED},
|
||||
{"rebuild", AMR_DRV_REBUILD},
|
||||
{"hot spare", AMR_DRV_HOTSPARE},
|
||||
{NULL, 0},
|
||||
{"unknown", 0}
|
||||
};
|
||||
|
||||
struct amr_code_lookup amr_table_adaptertype[] = {
|
||||
{"Series 431", AMR_SIG_431},
|
||||
{"Series 438", AMR_SIG_438},
|
||||
{"Series 762", AMR_SIG_762},
|
||||
{"Integrated HP NetRAID (T5)", AMR_SIG_T5},
|
||||
{"Series 466", AMR_SIG_466},
|
||||
{"Series 467", AMR_SIG_467},
|
||||
{"Integrated HP NetRAID (T7)", AMR_SIG_T7},
|
||||
{"Series 490", AMR_SIG_490},
|
||||
{NULL, 0},
|
||||
{"unknown adapter", 0}
|
||||
};
|
||||
|
||||
#endif
|
@ -1,124 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-3-Clause
|
||||
*
|
||||
* Copyright (c) 1999 Michael Smith
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Copyright (c) 2002 Eric Moore
|
||||
* Copyright (c) 2002 LSI Logic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The party using or redistributing the source code and binary forms
|
||||
* agrees to the disclaimer below and the terms and conditions set forth
|
||||
* herein.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/*
|
||||
* ioctl interface
|
||||
*/
|
||||
|
||||
#include <sys/ioccom.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
/*
|
||||
* Fetch the driver's interface version.
|
||||
*/
|
||||
#define AMR_IO_VERSION_NUMBER 153
|
||||
#define AMR_IO_VERSION _IOR('A', 0x200, int)
|
||||
|
||||
/*
|
||||
* Pass a command from userspace through to the adapter.
|
||||
*
|
||||
* Note that in order to be code-compatible with the Linux
|
||||
* interface where possible, the formatting of the au_cmd field is
|
||||
* somewhat Interesting.
|
||||
*
|
||||
* For normal commands, the layout is (fields from struct amr_mailbox_ioctl):
|
||||
*
|
||||
* 0 mb_command
|
||||
* 1 mb_channel
|
||||
* 2 mb_param
|
||||
* 3 mb_pad[0]
|
||||
* 4 mb_drive
|
||||
*
|
||||
* For SCSI passthrough commands, the layout is:
|
||||
*
|
||||
* 0 AMR_CMD_PASS (0x3)
|
||||
* 1 reserved, 0
|
||||
* 2 cdb length
|
||||
* 3 cdb data
|
||||
* 3+cdb_len passthrough control byte (timeout, ars, islogical)
|
||||
* 4+cdb_len reserved, 0
|
||||
* 5+cdb_len channel
|
||||
* 6+cdb_len target
|
||||
*/
|
||||
|
||||
struct amr_user_ioctl {
|
||||
unsigned char au_cmd[32]; /* command text from userspace */
|
||||
void *au_buffer; /* data buffer in userspace */
|
||||
unsigned long au_length; /* data buffer size (0 == no data) */
|
||||
int au_direction; /* data transfer direction */
|
||||
#define AMR_IO_NODATA 0
|
||||
#define AMR_IO_READ 1
|
||||
#define AMR_IO_WRITE 2
|
||||
int au_status; /* command status returned by adapter */
|
||||
};
|
||||
|
||||
#define AMR_IO_COMMAND _IOWR('A', 0x201, struct amr_user_ioctl)
|
||||
|
||||
#if defined(__amd64__)
|
||||
|
||||
struct amr_user_ioctl32 {
|
||||
unsigned char au_cmd[32]; /* command text from userspace */
|
||||
u_int32_t au_buffer; /* 32-bit pointer to uspace buf */
|
||||
u_int32_t au_length; /* length of the uspace buffer */
|
||||
int32_t au_direction; /* data transfer direction */
|
||||
int32_t au_status; /* command status returned by adapter */
|
||||
};
|
||||
|
||||
# define AMR_IO_COMMAND32 _IOWR('A', 0x201, struct amr_user_ioctl32)
|
||||
#endif
|
@ -1,657 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-3-Clause
|
||||
*
|
||||
* Copyright (c) 1999,2000 Michael Smith
|
||||
* Copyright (c) 2000 BSDi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Copyright (c) 2002 Eric Moore
|
||||
* Copyright (c) 2002 LSI Logic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The party using or redistributing the source code and binary forms
|
||||
* agrees to the disclaimer below and the terms and conditions set forth
|
||||
* herein.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/********************************************************************************
|
||||
********************************************************************************
|
||||
Driver parameters
|
||||
********************************************************************************
|
||||
********************************************************************************/
|
||||
|
||||
/*
|
||||
* We could actually use all 17 segments, but using only 16 means that
|
||||
* each scatter/gather map is 128 bytes in size, and thus we don't have to worry about
|
||||
* maps crossing page boundaries.
|
||||
*
|
||||
* The AMI documentation says that the limit is 26. Unfortunately, there's no way to
|
||||
* cleanly fit more than 16 entries in without a page boundary. But is this a concern,
|
||||
* since we allocate the s/g maps contiguously anyway?
|
||||
*/
|
||||
/*
|
||||
* emoore - Oct 21, 2002
|
||||
* firmware doesn't have sglist boundary restrictions.
|
||||
* The sgelem can be set to 26
|
||||
*/
|
||||
#define AMR_NSEG 26
|
||||
|
||||
#define AMR_MAXCMD 255 /* ident = 0 not allowed */
|
||||
#define AMR_LIMITCMD 120 /* maximum count of outstanding commands */
|
||||
#define AMR_MAXLD 40
|
||||
|
||||
#define AMR_MAX_CHANNELS 8
|
||||
#define AMR_MAX_TARGETS 15
|
||||
#define AMR_MAX_LUNS 7
|
||||
#define AMR_MAX_SCSI_CMDS (15 * AMR_MAX_CHANNELS) /* one for every target? */
|
||||
|
||||
#define AMR_MAX_CDB_LEN 0x0a
|
||||
#define AMR_MAX_EXTCDB_LEN 0x10
|
||||
#define AMR_MAX_REQ_SENSE_LEN 0x20
|
||||
|
||||
#define AMR_BLKSIZE 512 /* constant for all controllers */
|
||||
|
||||
/*
|
||||
* Perform at-startup board initialisation.
|
||||
* At this point in time, this code doesn't work correctly, so leave it disabled.
|
||||
*/
|
||||
/*#define AMR_BOARD_INIT*/
|
||||
|
||||
/********************************************************************************
|
||||
********************************************************************************
|
||||
Interface Magic Numbers
|
||||
********************************************************************************
|
||||
********************************************************************************/
|
||||
|
||||
/*
|
||||
* Mailbox commands
|
||||
*/
|
||||
#define AMR_CMD_LREAD 0x01
|
||||
#define AMR_CMD_LWRITE 0x02
|
||||
#define AMR_CMD_PASS 0x03
|
||||
#define AMR_CMD_EXT_ENQUIRY 0x04
|
||||
#define AMR_CMD_ENQUIRY 0x05
|
||||
#define AMR_CMD_FLUSH 0x0a
|
||||
#define AMR_CMD_EXT_ENQUIRY2 0x0c
|
||||
#define AMR_CONFIG_PRODINFO 0x0e
|
||||
#define AMR_CMD_GET_MACHINEID 0x36
|
||||
#define AMR_CMD_GET_INITIATOR 0x7d /* returns one byte */
|
||||
#define AMR_CMD_CONFIG 0xa1
|
||||
#define AMR_CMD_LREAD64 0xa7
|
||||
#define AMR_CMD_LWRITE64 0xa8
|
||||
#define AMR_CMD_PASS_64 0xc3
|
||||
#define AMR_CMD_EXTPASS 0xe3
|
||||
|
||||
#define AMR_CONFIG_READ_NVRAM_CONFIG 0x04
|
||||
#define AMR_CONFIG_WRITE_NVRAM_CONFIG 0x0d
|
||||
#define AMR_CONFIG_PRODUCT_INFO 0x0e
|
||||
#define AMR_CONFIG_ENQ3 0x0f
|
||||
#define AMR_CONFIG_ENQ3_SOLICITED_NOTIFY 0x01
|
||||
#define AMR_CONFIG_ENQ3_SOLICITED_FULL 0x02
|
||||
#define AMR_CONFIG_ENQ3_UNSOLICITED 0x03
|
||||
|
||||
/*
|
||||
* Command for random deletion of logical drives
|
||||
*/
|
||||
#define FC_DEL_LOGDRV 0xA4
|
||||
#define OP_SUP_DEL_LOGDRV 0x2A
|
||||
#define OP_GET_LDID_MAP 0x18
|
||||
#define OP_DEL_LOGDRV 0x1C
|
||||
|
||||
/*
|
||||
* Command for random deletion of logical drives
|
||||
*/
|
||||
#define FC_DEL_LOGDRV 0xA4
|
||||
#define OP_SUP_DEL_LOGDRV 0x2A
|
||||
#define OP_GET_LDID_MAP 0x18
|
||||
#define OP_DEL_LOGDRV 0x1C
|
||||
|
||||
/*
|
||||
* Command results
|
||||
*/
|
||||
#define AMR_STATUS_SUCCESS 0x00
|
||||
#define AMR_STATUS_ABORTED 0x02
|
||||
#define AMR_STATUS_FAILED 0x80
|
||||
|
||||
/*
|
||||
* Physical/logical drive states
|
||||
*/
|
||||
#define AMR_DRV_CURSTATE(x) ((x) & 0x0f)
|
||||
#define AMR_DRV_PREVSTATE(x) (((x) >> 4) & 0x0f)
|
||||
#define AMR_DRV_OFFLINE 0x00
|
||||
#define AMR_DRV_DEGRADED 0x01
|
||||
#define AMR_DRV_OPTIMAL 0x02
|
||||
#define AMR_DRV_ONLINE 0x03
|
||||
#define AMR_DRV_FAILED 0x04
|
||||
#define AMR_DRV_REBUILD 0x05
|
||||
#define AMR_DRV_HOTSPARE 0x06
|
||||
|
||||
/*
|
||||
* Logical drive properties
|
||||
*/
|
||||
#define AMR_DRV_RAID_MASK 0x0f /* RAID level 0, 1, 3, 5, etc. */
|
||||
#define AMR_DRV_WRITEBACK 0x10 /* write-back enabled */
|
||||
#define AMR_DRV_READHEAD 0x20 /* readhead policy enabled */
|
||||
#define AMR_DRV_ADAPTIVE 0x40 /* adaptive I/O policy enabled */
|
||||
|
||||
/*
|
||||
* Battery status
|
||||
*/
|
||||
#define AMR_BATT_MODULE_MISSING 0x01
|
||||
#define AMR_BATT_LOW_VOLTAGE 0x02
|
||||
#define AMR_BATT_TEMP_HIGH 0x04
|
||||
#define AMR_BATT_PACK_MISSING 0x08
|
||||
#define AMR_BATT_CHARGE_MASK 0x30
|
||||
#define AMR_BATT_CHARGE_DONE 0x00
|
||||
#define AMR_BATT_CHARGE_INPROG 0x10
|
||||
#define AMR_BATT_CHARGE_FAIL 0x20
|
||||
#define AMR_BATT_CYCLES_EXCEEDED 0x40
|
||||
|
||||
/********************************************************************************
|
||||
********************************************************************************
|
||||
8LD Firmware Interface
|
||||
********************************************************************************
|
||||
********************************************************************************/
|
||||
|
||||
/*
|
||||
* Array constraints
|
||||
*/
|
||||
#define AMR_8LD_MAXDRIVES 8
|
||||
#define AMR_8LD_MAXCHAN 5
|
||||
#define AMR_8LD_MAXTARG 15
|
||||
#define AMR_8LD_MAXPHYSDRIVES (AMR_8LD_MAXCHAN * AMR_8LD_MAXTARG)
|
||||
|
||||
/*
|
||||
* Adapter Info structure
|
||||
*/
|
||||
struct amr_adapter_info
|
||||
{
|
||||
u_int8_t aa_maxio;
|
||||
u_int8_t aa_rebuild_rate;
|
||||
u_int8_t aa_maxtargchan;
|
||||
u_int8_t aa_channels;
|
||||
u_int8_t aa_firmware[4];
|
||||
u_int16_t aa_flashage;
|
||||
u_int8_t aa_chipsetvalue;
|
||||
u_int8_t aa_memorysize;
|
||||
u_int8_t aa_cacheflush;
|
||||
u_int8_t aa_bios[4];
|
||||
u_int8_t aa_boardtype;
|
||||
u_int8_t aa_scsisensealert;
|
||||
u_int8_t aa_writeconfigcount;
|
||||
u_int8_t aa_driveinsertioncount;
|
||||
u_int8_t aa_inserteddrive;
|
||||
u_int8_t aa_batterystatus;
|
||||
u_int8_t res1;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Logical Drive info structure
|
||||
*/
|
||||
struct amr_logdrive_info
|
||||
{
|
||||
u_int8_t al_numdrives;
|
||||
u_int8_t res1[3];
|
||||
u_int32_t al_size[AMR_8LD_MAXDRIVES];
|
||||
u_int8_t al_properties[AMR_8LD_MAXDRIVES];
|
||||
u_int8_t al_state[AMR_8LD_MAXDRIVES];
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Physical Drive info structure
|
||||
*/
|
||||
struct amr_physdrive_info
|
||||
{
|
||||
u_int8_t ap_state[AMR_8LD_MAXPHYSDRIVES]; /* low nibble current state, high nibble previous state */
|
||||
u_int8_t ap_predictivefailure;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Enquiry response structure for AMR_CMD_ENQUIRY, AMR_CMD_EXT_ENQUIRY and
|
||||
* AMR_CMD_EXT_ENQUIRY2.
|
||||
* ENQUIRY EXT_ENQUIRY EXT_ENQUIRY2
|
||||
*/
|
||||
struct amr_enquiry
|
||||
{
|
||||
struct amr_adapter_info ae_adapter; /* X X X */
|
||||
struct amr_logdrive_info ae_ldrv; /* X X X */
|
||||
struct amr_physdrive_info ae_pdrv; /* X X X */
|
||||
u_int8_t ae_formatting[AMR_8LD_MAXDRIVES];/* X X */
|
||||
u_int8_t res1[AMR_8LD_MAXDRIVES]; /* X X */
|
||||
u_int32_t ae_extlen; /* X */
|
||||
u_int16_t ae_subsystem; /* X */
|
||||
u_int16_t ae_subvendor; /* X */
|
||||
u_int32_t ae_signature; /* X */
|
||||
#define AMR_SIG_431 0xfffe0001
|
||||
#define AMR_SIG_438 0xfffd0002
|
||||
#define AMR_SIG_762 0xfffc0003
|
||||
#define AMR_SIG_T5 0xfffb0004
|
||||
#define AMR_SIG_466 0xfffa0005
|
||||
#define AMR_SIG_467 0xfff90006
|
||||
#define AMR_SIG_T7 0xfff80007
|
||||
#define AMR_SIG_490 0xfff70008
|
||||
u_int8_t res2[844]; /* X */
|
||||
} __packed;
|
||||
|
||||
/********************************************************************************
|
||||
********************************************************************************
|
||||
40LD Firmware Interface
|
||||
********************************************************************************
|
||||
********************************************************************************/
|
||||
|
||||
/*
|
||||
* Array constraints
|
||||
*/
|
||||
#define AMR_40LD_MAXDRIVES 40
|
||||
#define AMR_40LD_MAXCHAN 16
|
||||
#define AMR_40LD_MAXTARG 16
|
||||
#define AMR_40LD_MAXPHYSDRIVES 256
|
||||
|
||||
/*
|
||||
* Product Info structure
|
||||
*/
|
||||
struct amr_prodinfo
|
||||
{
|
||||
u_int32_t ap_size; /* current size in bytes (not including resvd) */
|
||||
u_int32_t ap_configsig; /* default is 0x00282008, indicating 0x28 maximum
|
||||
* logical drives, 0x20 maximum stripes and 0x08
|
||||
* maximum spans */
|
||||
u_int8_t ap_firmware[16]; /* printable identifiers */
|
||||
u_int8_t ap_bios[16];
|
||||
u_int8_t ap_product[80];
|
||||
u_int8_t ap_maxio; /* maximum number of concurrent commands supported */
|
||||
u_int8_t ap_nschan; /* number of SCSI channels present */
|
||||
u_int8_t ap_fcloops; /* number of fibre loops present */
|
||||
u_int8_t ap_memtype; /* memory type */
|
||||
u_int32_t ap_signature;
|
||||
u_int16_t ap_memsize; /* onboard memory in MB */
|
||||
u_int16_t ap_subsystem; /* subsystem identifier */
|
||||
u_int16_t ap_subvendor; /* subsystem vendor ID */
|
||||
u_int8_t ap_numnotifyctr; /* number of notify counters */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Notify structure
|
||||
*/
|
||||
struct amr_notify
|
||||
{
|
||||
u_int32_t an_globalcounter; /* change counter */
|
||||
|
||||
u_int8_t an_paramcounter; /* parameter change counter */
|
||||
u_int8_t an_paramid;
|
||||
#define AMR_PARAM_REBUILD_RATE 0x01 /* value = new rebuild rate */
|
||||
#define AMR_PARAM_FLUSH_INTERVAL 0x02 /* value = new flush interval */
|
||||
#define AMR_PARAM_SENSE_ALERT 0x03 /* value = last physical drive with check condition set */
|
||||
#define AMR_PARAM_DRIVE_INSERTED 0x04 /* value = last physical drive inserted */
|
||||
#define AMR_PARAM_BATTERY_STATUS 0x05 /* value = battery status */
|
||||
u_int16_t an_paramval;
|
||||
|
||||
u_int8_t an_writeconfigcounter; /* write config occurred */
|
||||
u_int8_t res1[3];
|
||||
|
||||
u_int8_t an_ldrvopcounter; /* logical drive operation started/completed */
|
||||
u_int8_t an_ldrvopid;
|
||||
u_int8_t an_ldrvopcmd;
|
||||
#define AMR_LDRVOP_CHECK 0x01
|
||||
#define AMR_LDRVOP_INIT 0x02
|
||||
#define AMR_LDRVOP_REBUILD 0x03
|
||||
u_int8_t an_ldrvopstatus;
|
||||
#define AMR_LDRVOP_SUCCESS 0x00
|
||||
#define AMR_LDRVOP_FAILED 0x01
|
||||
#define AMR_LDRVOP_ABORTED 0x02
|
||||
#define AMR_LDRVOP_CORRECTED 0x03
|
||||
#define AMR_LDRVOP_STARTED 0x04
|
||||
|
||||
u_int8_t an_ldrvstatecounter; /* logical drive state change occurred */
|
||||
u_int8_t an_ldrvstateid;
|
||||
u_int8_t an_ldrvstatenew;
|
||||
u_int8_t an_ldrvstateold;
|
||||
|
||||
u_int8_t an_pdrvstatecounter; /* physical drive state change occurred */
|
||||
u_int8_t an_pdrvstateid;
|
||||
u_int8_t an_pdrvstatenew;
|
||||
u_int8_t an_pdrvstateold;
|
||||
|
||||
u_int8_t an_pdrvfmtcounter;
|
||||
u_int8_t an_pdrvfmtid;
|
||||
u_int8_t an_pdrvfmtval;
|
||||
#define AMR_FORMAT_START 0x01
|
||||
#define AMR_FORMAT_COMPLETE 0x02
|
||||
u_int8_t res2;
|
||||
|
||||
u_int8_t an_targxfercounter; /* scsi xfer rate change */
|
||||
u_int8_t an_targxferid;
|
||||
u_int8_t an_targxferval;
|
||||
u_int8_t res3;
|
||||
|
||||
u_int8_t an_fcloopidcounter; /* FC/AL loop ID changed */
|
||||
u_int8_t an_fcloopidpdrvid;
|
||||
u_int8_t an_fcloopid0;
|
||||
u_int8_t an_fcloopid1;
|
||||
|
||||
u_int8_t an_fcloopstatecounter; /* FC/AL loop status changed */
|
||||
u_int8_t an_fcloopstate0;
|
||||
u_int8_t an_fcloopstate1;
|
||||
u_int8_t res4;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* Enquiry3 structure
|
||||
*/
|
||||
struct amr_enquiry3
|
||||
{
|
||||
u_int32_t ae_datasize; /* valid data size in this structure */
|
||||
union { /* event notify structure */
|
||||
struct amr_notify n;
|
||||
u_int8_t pad[0x80];
|
||||
} ae_notify;
|
||||
u_int8_t ae_rebuildrate; /* current rebuild rate in % */
|
||||
u_int8_t ae_cacheflush; /* flush interval in seconds */
|
||||
u_int8_t ae_sensealert;
|
||||
u_int8_t ae_driveinsertcount; /* count of inserted drives */
|
||||
u_int8_t ae_batterystatus;
|
||||
u_int8_t ae_numldrives;
|
||||
u_int8_t ae_reconstate[AMR_40LD_MAXDRIVES / 8]; /* reconstruction state */
|
||||
u_int16_t ae_opstatus[AMR_40LD_MAXDRIVES / 8]; /* operation status per drive */
|
||||
u_int32_t ae_drivesize[AMR_40LD_MAXDRIVES]; /* logical drive size */
|
||||
u_int8_t ae_driveprop[AMR_40LD_MAXDRIVES]; /* logical drive properties */
|
||||
u_int8_t ae_drivestate[AMR_40LD_MAXDRIVES]; /* logical drive state */
|
||||
u_int8_t ae_pdrivestate[AMR_40LD_MAXPHYSDRIVES]; /* physical drive state */
|
||||
u_int16_t ae_pdriveformat[AMR_40LD_MAXPHYSDRIVES / 16];
|
||||
u_int8_t ae_targxfer[80]; /* physical drive transfer rates */
|
||||
|
||||
u_int8_t res1[263]; /* pad to 1024 bytes */
|
||||
} __packed;
|
||||
|
||||
/********************************************************************************
|
||||
********************************************************************************
|
||||
Mailbox and Command Structures
|
||||
********************************************************************************
|
||||
********************************************************************************/
|
||||
|
||||
#define AMR_MBOX_CMDSIZE 0x10 /* portion worth copying for controller */
|
||||
|
||||
struct amr_mailbox
|
||||
{
|
||||
u_int8_t mb_command;
|
||||
u_int8_t mb_ident;
|
||||
u_int16_t mb_blkcount; /* u_int8_t opcode */
|
||||
/* u_int8_t subopcode */
|
||||
u_int32_t mb_lba;
|
||||
u_int32_t mb_physaddr;
|
||||
u_int8_t mb_drive;
|
||||
u_int8_t mb_nsgelem; /* u_int8_t rserv[0] */
|
||||
u_int8_t res1; /* u_int8_t rserv[1] */
|
||||
u_int8_t mb_busy; /* u_int8_t rserv[2] */
|
||||
u_int8_t mb_nstatus;
|
||||
u_int8_t mb_status;
|
||||
u_int8_t mb_completed[46];
|
||||
u_int8_t mb_poll;
|
||||
u_int8_t mb_ack;
|
||||
u_int8_t res2[16];
|
||||
} __packed;
|
||||
|
||||
struct amr_mailbox64
|
||||
{
|
||||
u_int8_t pad[8]; /* Needed for alignment */
|
||||
u_int32_t sg64_lo; /* S/G pointer for 64-bit commands */
|
||||
u_int32_t sg64_hi; /* S/G pointer for 64-bit commands */
|
||||
struct amr_mailbox mb;
|
||||
} __packed;
|
||||
|
||||
struct amr_mailbox_ioctl
|
||||
{
|
||||
u_int8_t mb_command;
|
||||
u_int8_t mb_ident;
|
||||
u_int8_t mb_channel;
|
||||
u_int8_t mb_param;
|
||||
u_int8_t mb_pad[4];
|
||||
u_int32_t mb_physaddr;
|
||||
u_int8_t mb_drive;
|
||||
u_int8_t mb_nsgelem;
|
||||
u_int8_t res1;
|
||||
u_int8_t mb_busy;
|
||||
u_int8_t mb_nstatus;
|
||||
u_int8_t mb_completed[46];
|
||||
u_int8_t mb_poll;
|
||||
u_int8_t mb_ack;
|
||||
u_int8_t res4[16];
|
||||
} __packed;
|
||||
|
||||
struct amr_sgentry
|
||||
{
|
||||
u_int32_t sg_addr;
|
||||
u_int32_t sg_count;
|
||||
} __packed;
|
||||
|
||||
struct amr_sg64entry
|
||||
{
|
||||
u_int64_t sg_addr;
|
||||
u_int32_t sg_count;
|
||||
} __packed;
|
||||
|
||||
struct amr_passthrough
|
||||
{
|
||||
u_int8_t ap_timeout:3;
|
||||
u_int8_t ap_ars:1;
|
||||
u_int8_t ap_dummy:3;
|
||||
u_int8_t ap_islogical:1;
|
||||
u_int8_t ap_logical_drive_no;
|
||||
u_int8_t ap_channel;
|
||||
u_int8_t ap_scsi_id;
|
||||
u_int8_t ap_queue_tag;
|
||||
u_int8_t ap_queue_action;
|
||||
u_int8_t ap_cdb[AMR_MAX_CDB_LEN];
|
||||
u_int8_t ap_cdb_length;
|
||||
u_int8_t ap_request_sense_length;
|
||||
u_int8_t ap_request_sense_area[AMR_MAX_REQ_SENSE_LEN];
|
||||
u_int8_t ap_no_sg_elements;
|
||||
u_int8_t ap_scsi_status;
|
||||
u_int32_t ap_data_transfer_address;
|
||||
u_int32_t ap_data_transfer_length;
|
||||
} __packed;
|
||||
|
||||
struct amr_ext_passthrough
|
||||
{
|
||||
u_int8_t ap_timeout:3;
|
||||
u_int8_t ap_ars:1;
|
||||
u_int8_t ap_rsvd1:1;
|
||||
u_int8_t ap_cd_rom:1;
|
||||
u_int8_t ap_rsvd2:1;
|
||||
u_int8_t ap_islogical:1;
|
||||
u_int8_t ap_logical_drive_no;
|
||||
u_int8_t ap_channel;
|
||||
u_int8_t ap_scsi_id;
|
||||
u_int8_t ap_queue_tag;
|
||||
u_int8_t ap_queue_action;
|
||||
u_int8_t ap_cdb_length;
|
||||
u_int8_t ap_rsvd3;
|
||||
u_int8_t ap_cdb[AMR_MAX_EXTCDB_LEN];
|
||||
u_int8_t ap_no_sg_elements;
|
||||
u_int8_t ap_scsi_status;
|
||||
u_int8_t ap_request_sense_length;
|
||||
u_int8_t ap_request_sense_area[AMR_MAX_REQ_SENSE_LEN];
|
||||
u_int8_t ap_rsvd4;
|
||||
u_int32_t ap_data_transfer_address;
|
||||
u_int32_t ap_data_transfer_length;
|
||||
} __packed;
|
||||
|
||||
struct amr_linux_ioctl {
|
||||
u_int32_t inlen;
|
||||
u_int32_t outlen;
|
||||
union {
|
||||
u_int8_t fca[16];
|
||||
struct {
|
||||
u_int8_t opcode;
|
||||
u_int8_t subopcode;
|
||||
u_int16_t adapno;
|
||||
u_int32_t buffer;
|
||||
u_int8_t pad[4];
|
||||
u_int32_t length;
|
||||
} __packed fcs;
|
||||
} __packed ui;
|
||||
u_int8_t mbox[18];
|
||||
struct amr_passthrough pthru;
|
||||
u_int32_t data;
|
||||
u_int8_t pad[4];
|
||||
} __packed;
|
||||
|
||||
#ifdef _KERNEL
|
||||
/********************************************************************************
|
||||
********************************************************************************
|
||||
"Quartz" i960 PCI bridge interface
|
||||
********************************************************************************
|
||||
********************************************************************************/
|
||||
|
||||
#define AMR_CFG_SIG 0xa0 /* PCI config register for signature */
|
||||
#define AMR_SIGNATURE_1 0xCCCC /* i960 signature (older adapters) */
|
||||
#define AMR_SIGNATURE_2 0x3344 /* i960 signature (newer adapters) */
|
||||
|
||||
/*
|
||||
* Doorbell registers
|
||||
*/
|
||||
#define AMR_QIDB 0x20
|
||||
#define AMR_QODB 0x2c
|
||||
#define AMR_QIDB_SUBMIT 0x00000001 /* mailbox ready for work */
|
||||
#define AMR_QIDB_ACK 0x00000002 /* mailbox done */
|
||||
#define AMR_QODB_READY 0x10001234 /* work ready to be processed */
|
||||
|
||||
/*
|
||||
* Initialisation status
|
||||
*/
|
||||
#define AMR_QINIT_SCAN 0x01 /* init scanning drives */
|
||||
#define AMR_QINIT_SCANINIT 0x02 /* init scanning initialising */
|
||||
#define AMR_QINIT_FIRMWARE 0x03 /* init firmware initing */
|
||||
#define AMR_QINIT_INPROG 0xdc /* init in progress */
|
||||
#define AMR_QINIT_SPINUP 0x2c /* init spinning drives */
|
||||
#define AMR_QINIT_NOMEM 0xac /* insufficient memory */
|
||||
#define AMR_QINIT_CACHEFLUSH 0xbc /* init flushing cache */
|
||||
#define AMR_QINIT_DONE 0x9c /* init successfully done */
|
||||
|
||||
/*
|
||||
* I/O primitives
|
||||
*/
|
||||
#define AMR_QPUT_IDB(sc, val) bus_space_write_4(sc->amr_btag, sc->amr_bhandle, AMR_QIDB, val)
|
||||
#define AMR_QGET_IDB(sc) bus_space_read_4 (sc->amr_btag, sc->amr_bhandle, AMR_QIDB)
|
||||
#define AMR_QPUT_ODB(sc, val) bus_space_write_4(sc->amr_btag, sc->amr_bhandle, AMR_QODB, val)
|
||||
#define AMR_QGET_ODB(sc) bus_space_read_4 (sc->amr_btag, sc->amr_bhandle, AMR_QODB)
|
||||
|
||||
#ifdef AMR_BOARD_INIT
|
||||
#define AMR_QRESET(sc) \
|
||||
do { \
|
||||
pci_write_config((sc)->amr_dev, 0x40, pci_read_config((sc)->amr_dev, 0x40, 1) | 0x20, 1); \
|
||||
pci_write_config((sc)->amr_dev, 0x64, 0x1122, 1); \
|
||||
} while (0)
|
||||
#define AMR_QGET_INITSTATUS(sc) pci_read_config((sc)->amr_dev, 0x9c, 1)
|
||||
#define AMR_QGET_INITCHAN(sc) pci_read_config((sc)->amr_dev, 0x9f, 1)
|
||||
#define AMR_QGET_INITTARG(sc) pci_read_config((sc)->amr_dev, 0x9e, 1)
|
||||
#endif
|
||||
|
||||
/********************************************************************************
|
||||
********************************************************************************
|
||||
"Standard" old-style ASIC bridge interface
|
||||
********************************************************************************
|
||||
********************************************************************************/
|
||||
|
||||
/*
|
||||
* I/O registers
|
||||
*/
|
||||
#define AMR_SCMD 0x10 /* command/ack register (write) */
|
||||
#define AMR_SMBOX_BUSY 0x10 /* mailbox status (read) */
|
||||
#define AMR_STOGGLE 0x11 /* interrupt enable bit here */
|
||||
#define AMR_SMBOX_0 0x14 /* mailbox physical address low byte */
|
||||
#define AMR_SMBOX_1 0x15
|
||||
#define AMR_SMBOX_2 0x16
|
||||
#define AMR_SMBOX_3 0x17 /* high byte */
|
||||
#define AMR_SMBOX_ENABLE 0x18 /* atomic mailbox address enable */
|
||||
#define AMR_SINTR 0x1a /* interrupt status */
|
||||
|
||||
/*
|
||||
* I/O magic numbers
|
||||
*/
|
||||
#define AMR_SCMD_POST 0x10 /* -> SCMD to initiate action on mailbox */
|
||||
#define AMR_SCMD_ACKINTR 0x08 /* -> SCMD to ack mailbox retrieved */
|
||||
#define AMR_STOGL_IENABLE 0xc0 /* in STOGGLE */
|
||||
#define AMR_SINTR_VALID 0x40 /* in SINTR */
|
||||
#define AMR_SMBOX_BUSYFLAG 0x10 /* in SMBOX_BUSY */
|
||||
#define AMR_SMBOX_ADDR 0x00 /* -> SMBOX_ENABLE */
|
||||
|
||||
/*
|
||||
* Initialisation status
|
||||
*/
|
||||
#define AMR_SINIT_ABEND 0xee /* init abnormal terminated */
|
||||
#define AMR_SINIT_NOMEM 0xca /* insufficient memory */
|
||||
#define AMR_SINIT_CACHEFLUSH 0xbb /* firmware flushing cache */
|
||||
#define AMR_SINIT_INPROG 0x11 /* init in progress */
|
||||
#define AMR_SINIT_SPINUP 0x22 /* firmware spinning drives */
|
||||
#define AMR_SINIT_DONE 0x99 /* init successfully done */
|
||||
|
||||
/*
|
||||
* I/O primitives
|
||||
*/
|
||||
#define AMR_SPUT_ISTAT(sc, val) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SINTR, val)
|
||||
#define AMR_SGET_ISTAT(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SINTR)
|
||||
#define AMR_SACK_INTERRUPT(sc) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SCMD, AMR_SCMD_ACKINTR)
|
||||
#define AMR_SPOST_COMMAND(sc) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SCMD, AMR_SCMD_POST)
|
||||
#define AMR_SGET_MBSTAT(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SMBOX_BUSY)
|
||||
#define AMR_SENABLE_INTR(sc) \
|
||||
bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE, \
|
||||
bus_space_read_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE) | AMR_STOGL_IENABLE)
|
||||
#define AMR_SDISABLE_INTR(sc) \
|
||||
bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE, \
|
||||
bus_space_read_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE) & ~AMR_STOGL_IENABLE)
|
||||
#define AMR_SBYTE_SET(sc, reg, val) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, reg, val)
|
||||
|
||||
#ifdef AMR_BOARD_INIT
|
||||
#define AMR_SRESET(sc) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, 0, 0x80)
|
||||
#define AMR_SGET_INITSTATUS(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SMBOX_ENABLE)
|
||||
#define AMR_SGET_FAILDRIVE(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SMBOX_ENABLE + 1)
|
||||
#define AMR_SGET_INITCHAN(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SMBOX_ENABLE + 2)
|
||||
#define AMR_SGET_INITTARG(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SMBOX_ENABLE + 3)
|
||||
#endif
|
||||
|
||||
#endif /* _KERNEL */
|
@ -1,384 +0,0 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-3-Clause
|
||||
*
|
||||
* Copyright (c) 1999,2000 Michael Smith
|
||||
* Copyright (c) 2000 BSDi
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* Copyright (c) 2002 Eric Moore
|
||||
* Copyright (c) 2002 LSI Logic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The party using or redistributing the source code and binary forms
|
||||
* agrees to the disclaimer below and the terms and conditions set forth
|
||||
* herein.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <geom/geom_disk.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
|
||||
#define LSI_DESC_PCI "LSILogic MegaRAID 1.53"
|
||||
|
||||
#ifdef AMR_DEBUG
|
||||
# define debug(level, fmt, args...) do {if (level <= AMR_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);} while(0)
|
||||
# define debug_called(level) do {if (level <= AMR_DEBUG) printf("%s: called\n", __func__);} while(0)
|
||||
#else
|
||||
# define debug(level, fmt, args...) do {} while (0)
|
||||
# define debug_called(level) do {} while (0)
|
||||
#endif
|
||||
#define xdebug(fmt, args...) printf("%s: " fmt "\n", __func__ , ##args)
|
||||
|
||||
/*
|
||||
* Per-logical-drive datastructure
|
||||
*/
|
||||
struct amr_logdrive
|
||||
{
|
||||
u_int32_t al_size;
|
||||
int al_state;
|
||||
int al_properties;
|
||||
|
||||
/* synthetic geometry */
|
||||
int al_cylinders;
|
||||
int al_heads;
|
||||
int al_sectors;
|
||||
|
||||
/* driver */
|
||||
device_t al_disk;
|
||||
};
|
||||
|
||||
/*
|
||||
* Due to the difficulty of using the zone allocator to create a new
|
||||
* zone from within a module, we use our own clustering to reduce
|
||||
* memory wastage due to allocating lots of these small structures.
|
||||
*
|
||||
* 16k gives us a little under 200 command structures, which should
|
||||
* normally be plenty. We will grab more if we need them.
|
||||
*/
|
||||
|
||||
#define AMR_CMD_CLUSTERSIZE (16 * 1024)
|
||||
|
||||
typedef STAILQ_HEAD(, amr_command) ac_qhead_t;
|
||||
typedef STAILQ_ENTRY(amr_command) ac_link_t;
|
||||
|
||||
union amr_ccb {
|
||||
struct amr_passthrough ccb_pthru;
|
||||
struct amr_ext_passthrough ccb_epthru;
|
||||
uint8_t bytes[128];
|
||||
};
|
||||
|
||||
/*
|
||||
* Per-command control structure.
|
||||
*/
|
||||
struct amr_command
|
||||
{
|
||||
ac_link_t ac_link;
|
||||
|
||||
struct amr_softc *ac_sc;
|
||||
u_int8_t ac_slot;
|
||||
int ac_status; /* command completion status */
|
||||
union {
|
||||
struct amr_sgentry *sg32;
|
||||
struct amr_sg64entry *sg64;
|
||||
} ac_sg;
|
||||
u_int32_t ac_sgbusaddr;
|
||||
u_int32_t ac_sg64_lo;
|
||||
u_int32_t ac_sg64_hi;
|
||||
struct amr_mailbox ac_mailbox;
|
||||
int ac_flags;
|
||||
#define AMR_CMD_DATAIN (1<<0)
|
||||
#define AMR_CMD_DATAOUT (1<<1)
|
||||
#define AMR_CMD_CCB (1<<2)
|
||||
#define AMR_CMD_PRIORITY (1<<4)
|
||||
#define AMR_CMD_MAPPED (1<<5)
|
||||
#define AMR_CMD_SLEEP (1<<6)
|
||||
#define AMR_CMD_BUSY (1<<7)
|
||||
#define AMR_CMD_SG64 (1<<8)
|
||||
#define AC_IS_SG64(ac) ((ac)->ac_flags & AMR_CMD_SG64)
|
||||
u_int ac_retries;
|
||||
|
||||
struct bio *ac_bio;
|
||||
void (* ac_complete)(struct amr_command *ac);
|
||||
void *ac_private;
|
||||
|
||||
void *ac_data;
|
||||
size_t ac_length;
|
||||
bus_dmamap_t ac_dmamap;
|
||||
bus_dmamap_t ac_dma64map;
|
||||
|
||||
bus_dma_tag_t ac_tag;
|
||||
bus_dmamap_t ac_datamap;
|
||||
int ac_nsegments;
|
||||
uint32_t ac_mb_physaddr;
|
||||
|
||||
union amr_ccb *ac_ccb;
|
||||
uint32_t ac_ccb_busaddr;
|
||||
};
|
||||
|
||||
struct amr_command_cluster
|
||||
{
|
||||
TAILQ_ENTRY(amr_command_cluster) acc_link;
|
||||
struct amr_command acc_command[0];
|
||||
};
|
||||
|
||||
#define AMR_CMD_CLUSTERCOUNT ((AMR_CMD_CLUSTERSIZE - sizeof(struct amr_command_cluster)) / \
|
||||
sizeof(struct amr_command))
|
||||
|
||||
/*
|
||||
* Per-controller-instance data
|
||||
*/
|
||||
struct amr_softc
|
||||
{
|
||||
/* bus attachments */
|
||||
device_t amr_dev;
|
||||
struct resource *amr_reg; /* control registers */
|
||||
bus_space_handle_t amr_bhandle;
|
||||
bus_space_tag_t amr_btag;
|
||||
bus_dma_tag_t amr_parent_dmat; /* parent DMA tag */
|
||||
bus_dma_tag_t amr_buffer_dmat; /* data buffer DMA tag */
|
||||
bus_dma_tag_t amr_buffer64_dmat;
|
||||
struct resource *amr_irq; /* interrupt */
|
||||
void *amr_intr;
|
||||
|
||||
/* mailbox */
|
||||
volatile struct amr_mailbox *amr_mailbox;
|
||||
volatile struct amr_mailbox64 *amr_mailbox64;
|
||||
u_int32_t amr_mailboxphys;
|
||||
bus_dma_tag_t amr_mailbox_dmat;
|
||||
bus_dmamap_t amr_mailbox_dmamap;
|
||||
|
||||
/* scatter/gather lists and their controller-visible mappings */
|
||||
struct amr_sgentry *amr_sgtable; /* s/g lists */
|
||||
struct amr_sg64entry *amr_sg64table; /* 64bit s/g lists */
|
||||
u_int32_t amr_sgbusaddr; /* s/g table base address in bus space */
|
||||
bus_dma_tag_t amr_sg_dmat; /* s/g buffer DMA tag */
|
||||
bus_dmamap_t amr_sg_dmamap; /* map for s/g buffers */
|
||||
|
||||
union amr_ccb *amr_ccb;
|
||||
uint32_t amr_ccb_busaddr;
|
||||
bus_dma_tag_t amr_ccb_dmat;
|
||||
bus_dmamap_t amr_ccb_dmamap;
|
||||
|
||||
/* controller limits and features */
|
||||
int amr_nextslot; /* Next slot to use for newly allocated commands */
|
||||
int amr_maxio; /* maximum number of I/O transactions */
|
||||
int amr_maxdrives; /* max number of logical drives */
|
||||
int amr_maxchan; /* count of SCSI channels */
|
||||
|
||||
/* connected logical drives */
|
||||
struct amr_logdrive amr_drive[AMR_MAXLD];
|
||||
|
||||
/* controller state */
|
||||
int amr_state;
|
||||
#define AMR_STATE_OPEN (1<<0)
|
||||
#define AMR_STATE_SUSPEND (1<<1)
|
||||
#define AMR_STATE_INTEN (1<<2)
|
||||
#define AMR_STATE_SHUTDOWN (1<<3)
|
||||
#define AMR_STATE_CRASHDUMP (1<<4)
|
||||
#define AMR_STATE_QUEUE_FRZN (1<<5)
|
||||
#define AMR_STATE_LD_DELETE (1<<6)
|
||||
#define AMR_STATE_REMAP_LD (1<<7)
|
||||
|
||||
/* per-controller queues */
|
||||
struct bio_queue_head amr_bioq; /* pending I/O with no commands */
|
||||
ac_qhead_t amr_ready; /* commands ready to be submitted */
|
||||
struct amr_command *amr_busycmd[AMR_MAXCMD];
|
||||
int amr_busyslots;
|
||||
ac_qhead_t amr_freecmds;
|
||||
TAILQ_HEAD(,amr_command_cluster) amr_cmd_clusters;
|
||||
|
||||
/* CAM attachments for passthrough */
|
||||
struct cam_sim *amr_cam_sim[AMR_MAX_CHANNELS];
|
||||
TAILQ_HEAD(, ccb_hdr) amr_cam_ccbq;
|
||||
struct cam_devq *amr_cam_devq;
|
||||
|
||||
/* control device */
|
||||
struct cdev *amr_dev_t;
|
||||
struct mtx amr_list_lock;
|
||||
|
||||
/* controller type-specific support */
|
||||
int amr_type;
|
||||
#define AMR_TYPE_QUARTZ (1<<0)
|
||||
#define AMR_IS_QUARTZ(sc) ((sc)->amr_type & AMR_TYPE_QUARTZ)
|
||||
#define AMR_TYPE_40LD (1<<1)
|
||||
#define AMR_IS_40LD(sc) ((sc)->amr_type & AMR_TYPE_40LD)
|
||||
#define AMR_TYPE_SG64 (1<<2)
|
||||
#define AMR_IS_SG64(sc) ((sc)->amr_type & AMR_TYPE_SG64)
|
||||
int (* amr_submit_command)(struct amr_command *ac);
|
||||
int (* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave);
|
||||
int (*amr_poll_command)(struct amr_command *ac);
|
||||
int (*amr_poll_command1)(struct amr_softc *sc, struct amr_command *ac);
|
||||
int support_ext_cdb; /* greater than 10 byte cdb support */
|
||||
|
||||
/* misc glue */
|
||||
device_t amr_pass;
|
||||
int (*amr_cam_command)(struct amr_softc *sc, struct amr_command **acp);
|
||||
struct intr_config_hook amr_ich; /* wait-for-interrupts probe hook */
|
||||
int amr_allow_vol_config;
|
||||
int amr_linux_no_adapters;
|
||||
int amr_ld_del_supported;
|
||||
struct mtx amr_hw_lock;
|
||||
};
|
||||
|
||||
/*
|
||||
* Interface between bus connections and driver core.
|
||||
*/
|
||||
extern int amr_attach(struct amr_softc *sc);
|
||||
extern void amr_free(struct amr_softc *sc);
|
||||
extern int amr_flush(struct amr_softc *sc);
|
||||
extern int amr_done(struct amr_softc *sc);
|
||||
extern void amr_startio(struct amr_softc *sc);
|
||||
|
||||
/*
|
||||
* Command buffer allocation.
|
||||
*/
|
||||
extern struct amr_command *amr_alloccmd(struct amr_softc *sc);
|
||||
extern void amr_releasecmd(struct amr_command *ac);
|
||||
|
||||
/*
|
||||
* MegaRAID logical disk driver
|
||||
*/
|
||||
struct amrd_softc
|
||||
{
|
||||
device_t amrd_dev;
|
||||
struct amr_softc *amrd_controller;
|
||||
struct amr_logdrive *amrd_drive;
|
||||
struct disk *amrd_disk;
|
||||
int amrd_unit;
|
||||
};
|
||||
|
||||
/*
|
||||
* Interface between driver core and disk driver (should be using a bus?)
|
||||
*/
|
||||
extern int amr_submit_bio(struct amr_softc *sc, struct bio *bio);
|
||||
extern int amr_dump_blocks(struct amr_softc *sc, int unit, u_int32_t lba, void *data, int blks);
|
||||
extern void amrd_intr(void *data);
|
||||
|
||||
/********************************************************************************
|
||||
* Enqueue/dequeue functions
|
||||
*/
|
||||
static __inline void
|
||||
amr_enqueue_bio(struct amr_softc *sc, struct bio *bio)
|
||||
{
|
||||
|
||||
bioq_insert_tail(&sc->amr_bioq, bio);
|
||||
}
|
||||
|
||||
static __inline struct bio *
|
||||
amr_dequeue_bio(struct amr_softc *sc)
|
||||
{
|
||||
struct bio *bio;
|
||||
|
||||
if ((bio = bioq_first(&sc->amr_bioq)) != NULL)
|
||||
bioq_remove(&sc->amr_bioq, bio);
|
||||
return(bio);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
amr_init_qhead(ac_qhead_t *head)
|
||||
{
|
||||
|
||||
STAILQ_INIT(head);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
amr_enqueue_ready(struct amr_command *ac)
|
||||
{
|
||||
|
||||
STAILQ_INSERT_TAIL(&ac->ac_sc->amr_ready, ac, ac_link);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
amr_requeue_ready(struct amr_command *ac)
|
||||
{
|
||||
|
||||
STAILQ_INSERT_HEAD(&ac->ac_sc->amr_ready, ac, ac_link);
|
||||
}
|
||||
|
||||
static __inline struct amr_command *
|
||||
amr_dequeue_ready(struct amr_softc *sc)
|
||||
{
|
||||
struct amr_command *ac;
|
||||
|
||||
if ((ac = STAILQ_FIRST(&sc->amr_ready)) != NULL)
|
||||
STAILQ_REMOVE_HEAD(&sc->amr_ready, ac_link);
|
||||
return(ac);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
amr_enqueue_completed(struct amr_command *ac, ac_qhead_t *head)
|
||||
{
|
||||
|
||||
STAILQ_INSERT_TAIL(head, ac, ac_link);
|
||||
}
|
||||
|
||||
static __inline struct amr_command *
|
||||
amr_dequeue_completed(struct amr_softc *sc, ac_qhead_t *head)
|
||||
{
|
||||
struct amr_command *ac;
|
||||
|
||||
if ((ac = STAILQ_FIRST(head)) != NULL)
|
||||
STAILQ_REMOVE_HEAD(head, ac_link);
|
||||
return(ac);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
amr_enqueue_free(struct amr_command *ac)
|
||||
{
|
||||
|
||||
STAILQ_INSERT_HEAD(&ac->ac_sc->amr_freecmds, ac, ac_link);
|
||||
}
|
||||
|
||||
static __inline struct amr_command *
|
||||
amr_dequeue_free(struct amr_softc *sc)
|
||||
{
|
||||
struct amr_command *ac;
|
||||
|
||||
if ((ac = STAILQ_FIRST(&sc->amr_freecmds)) != NULL)
|
||||
STAILQ_REMOVE_HEAD(&sc->amr_freecmds, ac_link);
|
||||
return(ac);
|
||||
}
|
@ -154,7 +154,6 @@ device ses # Enclosure Services (SES and SAF-TE)
|
||||
#device ctl # CAM Target Layer
|
||||
|
||||
# RAID controllers interfaced to the SCSI subsystem
|
||||
device amr # AMI MegaRAID
|
||||
device arcmsr # Areca SATA II RAID
|
||||
device ciss # Compaq Smart RAID 5*
|
||||
device ips # IBM (Adaptec) ServeRAID
|
||||
|
@ -38,7 +38,6 @@ SUBDIR= \
|
||||
${_amdsbwd} \
|
||||
${_amdsmn} \
|
||||
${_amdtemp} \
|
||||
amr \
|
||||
${_aout} \
|
||||
${_arcmsr} \
|
||||
${_allwinner} \
|
||||
|
@ -1,21 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${SRCTOP}/sys/dev/amr
|
||||
|
||||
SUBDIR= amr_cam
|
||||
.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
|
||||
SUBDIR+= amr_linux
|
||||
.endif
|
||||
|
||||
KMOD= amr
|
||||
SRCS= amr.c amr_pci.c amr_disk.c device_if.h bus_if.h pci_if.h
|
||||
|
||||
# Enable a questionable optimisation for newer adapters
|
||||
#CFLAGS+= -DAMR_QUARTZ_GOFASTER
|
||||
|
||||
# Debugging
|
||||
#CFLAGS+= -DAMR_DEBUG=3
|
||||
|
||||
EXPORT_SYMS= YES
|
||||
|
||||
.include <bsd.kmod.mk>
|
@ -1,9 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${SRCTOP}/sys/dev/amr
|
||||
|
||||
KMOD= amr_cam
|
||||
SRCS= amr_cam.c device_if.h bus_if.h
|
||||
SRCS+= opt_cam.h opt_scsi.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
@ -1,8 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${SRCTOP}/sys/dev/amr
|
||||
|
||||
KMOD= amr_linux
|
||||
SRCS= amr_linux.c device_if.h bus_if.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
@ -1,21 +0,0 @@
|
||||
# Doxyfile 1.5.2
|
||||
|
||||
# $FreeBSD$
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = "FreeBSD kernel AMR device code"
|
||||
OUTPUT_DIRECTORY = $(DOXYGEN_DEST_PATH)/dev_amr/
|
||||
EXTRACT_ALL = YES # for undocumented src, no warnings enabled
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = $(DOXYGEN_SRC_PATH)/dev/amr/ \
|
||||
$(NOTREVIEWED)
|
||||
|
||||
GENERATE_TAGFILE = dev_amr/dev_amr.tag
|
||||
|
||||
@INCLUDE_PATH = $(DOXYGEN_INCLUDE_PATH)
|
||||
@INCLUDE = common-Doxyfile
|
||||
|
Loading…
x
Reference in New Issue
Block a user