A new driver for PCI:SCSI RAID controllers based on the Adaptec FSA

design.  This includes integrated Dell RAID controllers, the Dell
PERC 2/QC and the HP NetRAID-4M.
This commit is contained in:
Mike Smith 2000-09-13 03:20:35 +00:00
parent 553427fc01
commit 358637397e
17 changed files with 4787 additions and 1 deletions

View File

@ -112,6 +112,7 @@ device cd # CD
device pass # Passthrough device (direct SCSI access)
# RAID controllers
device aac # Adaptec FSA RAID
device ida # Compaq Smart RAID
device amr # AMI MegaRAID
device mlx # Mylex DAC960 family

View File

@ -1330,6 +1330,11 @@ options DPT_ALLOW_MEMIO
#
device mly
#
# Adaptec FSA RAID controllers, including integrated DELL controllers,
# the Dell PERC 2/QC and the HP NetRAID-4M
device aac
#
# Compaq Smart RAID, Mylex DAC960 and AMI MegaRAID controllers. Only
# one entry is needed; the code will find and configure all supported

View File

@ -71,6 +71,7 @@ ddb/db_trap.c optional ddb
ddb/db_variables.c optional ddb
ddb/db_watch.c optional ddb
ddb/db_write_cmd.c optional ddb
dev/aac/aac.c optional aac
dev/acpi/acpi.c count acpi
dev/acpi/acpi_powerres.c optional acpi
dev/acpi/aml/aml_amlmem.c optional acpi

1896
sys/dev/aac/aac.c Normal file

File diff suppressed because it is too large Load Diff

64
sys/dev/aac/aac_compat.h Normal file
View File

@ -0,0 +1,64 @@
/*-
* Copyright (c) 2000 Michael Smith
* Copyright (c) 2000 BSDi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* Backwards compatibility support.
*/
/*
* Handle the new/old bio/buf changeover
*/
#if __FreeBSD_version < 500003 /* old buf style */
# include <sys/buf.h>
# define FREEBSD_4
# define bio buf
# define bioq_init(x) bufq_init(x)
# define bioq_insert_tail(x, y) bufq_insert_tail(x, y)
# define bioq_remove(x, y) bufq_remove(x, y)
# define bioq_first(x) bufq_first(x)
# define bio_queue_head buf_queue_head
# define bio_bcount b_bcount
# define bio_blkno b_blkno
# define bio_caller1 b_caller1
# define bio_data b_data
# define bio_dev b_dev
# define bio_driver1 b_driver1
# define bio_driver2 b_driver2
# define bio_error b_error
# define bio_flags b_flags
# define bio_pblkno b_pblkno
# define bio_resid b_resid
# define BIO_ERROR B_ERROR
# define devstat_end_transaction_bio(x, y) devstat_end_transaction_buf(x, y)
# define BIO_IS_READ(x) ((x)->b_flags & B_READ)
#else /* new bio style */
# include <sys/bio.h>
#define BIO_IS_READ(x) ((x)->bio_cmd == BIO_READ)
#endif

426
sys/dev/aac/aac_debug.c Normal file
View File

@ -0,0 +1,426 @@
/*-
* Copyright (c) 2000 Michael Smith
* Copyright (c) 2000 BSDi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* Debugging support.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <dev/aac/aac_compat.h>
#include <sys/bus.h>
#include <sys/devicestat.h>
#include <sys/disk.h>
#include <machine/resource.h>
#include <machine/bus.h>
#include <dev/aac/aacreg.h>
#include <dev/aac/aacvar.h>
void aac_printstate0(void);
void aac_intr0(void);
/********************************************************************************
* Dump the command queue indices
*/
void
aac_print_queues(struct aac_softc *sc)
{
device_printf(sc->aac_dev, "FIB queue header at %p queues at %p\n",
&sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][0],
&sc->aac_queues->qt_HostNormCmdQueue[0]);
device_printf(sc->aac_dev, "HOST_NORM_CMD %d/%d (%d)\n",
sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX],
sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX],
AAC_HOST_NORM_CMD_ENTRIES);
device_printf(sc->aac_dev, "HOST_HIGH_CMD %d/%d (%d)\n",
sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX],
sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX],
AAC_HOST_HIGH_CMD_ENTRIES);
device_printf(sc->aac_dev, "ADAP_NORM_CMD %d/%d (%d)\n",
sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX],
sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX],
AAC_ADAP_NORM_CMD_ENTRIES);
device_printf(sc->aac_dev, "ADAP_HIGH_CMD %d/%d (%d)\n",
sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX],
sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX],
AAC_ADAP_HIGH_CMD_ENTRIES);
device_printf(sc->aac_dev, "HOST_NORM_RESP %d/%d (%d)\n",
sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX],
sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX],
AAC_HOST_NORM_RESP_ENTRIES);
device_printf(sc->aac_dev, "HOST_HIGH_RESP %d/%d (%d)\n",
sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX],
sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX],
AAC_HOST_HIGH_RESP_ENTRIES);
device_printf(sc->aac_dev, "ADAP_NORM_RESP %d/%d (%d)\n",
sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX],
sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX],
AAC_ADAP_NORM_RESP_ENTRIES);
device_printf(sc->aac_dev, "ADAP_HIGH_RESP %d/%d (%d)\n",
sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX],
sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX],
AAC_ADAP_HIGH_RESP_ENTRIES);
}
/********************************************************************************
* Print the command queue states for controller 0 (callable from DDB)
*/
void
aac_printstate0(void)
{
struct aac_softc *sc = devclass_get_softc(aac_devclass, 0);
aac_print_queues(sc);
switch (sc->aac_hwif) {
case AAC_HWIF_I960RX:
device_printf(sc->aac_dev, "IDBR 0x%08x IIMR 0x%08x IISR 0x%08x\n",
AAC_GETREG4(sc, AAC_RX_IDBR), AAC_GETREG4(sc, AAC_RX_IIMR), AAC_GETREG4(sc, AAC_RX_IISR));
device_printf(sc->aac_dev, "ODBR 0x%08x OIMR 0x%08x OISR 0x%08x\n",
AAC_GETREG4(sc, AAC_RX_ODBR), AAC_GETREG4(sc, AAC_RX_OIMR), AAC_GETREG4(sc, AAC_RX_OISR));
AAC_SETREG4(sc, AAC_RX_OIMR, 0/*~(AAC_DB_COMMAND_READY | AAC_DB_RESPONSE_READY | AAC_DB_PRINTF)*/);
device_printf(sc->aac_dev, "ODBR 0x%08x OIMR 0x%08x OISR 0x%08x\n",
AAC_GETREG4(sc, AAC_RX_ODBR), AAC_GETREG4(sc, AAC_RX_OIMR), AAC_GETREG4(sc, AAC_RX_OISR));
break;
case AAC_HWIF_STRONGARM:
/* XXX implement */
}
}
/********************************************************************************
* simulate an interrupt for controller 0
*/
void
aac_intr0(void)
{
struct aac_softc *sc = devclass_get_softc(aac_devclass, 0);
aac_intr(sc);
}
/********************************************************************************
* Panic in a slightly informative fashion
*/
void
aac_panic(struct aac_softc *sc, char *reason)
{
aac_print_queues(sc);
panic(reason);
}
/********************************************************************************
* Print a FIB
*/
void
aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, char *caller)
{
device_printf(sc->aac_dev, "%s: FIB @ %p\n", caller, fib);
device_printf(sc->aac_dev, " XferState %b\n", fib->Header.XferState, "\20"
"\1HOSTOWNED"
"\2ADAPTEROWNED"
"\3INITIALISED"
"\4EMPTY"
"\5FROMPOOL"
"\6FROMHOST"
"\7FROMADAP"
"\10REXPECTED"
"\11RNOTEXPECTED"
"\12DONEADAP"
"\13DONEHOST"
"\14HIGH"
"\15NORM"
"\16ASYNC"
"\17PAGEFILEIO"
"\20SHUTDOWN"
"\21LAZYWRITE"
"\22ADAPMICROFIB"
"\23BIOSFIB"
"\24FAST_RESPONSE"
"\25APIFIB\n");
device_printf(sc->aac_dev, " Command %d\n", fib->Header.Command);
device_printf(sc->aac_dev, " StructType %d\n", fib->Header.StructType);
device_printf(sc->aac_dev, " Flags 0x%x\n", fib->Header.Flags);
device_printf(sc->aac_dev, " Size %d\n", fib->Header.Size);
device_printf(sc->aac_dev, " SenderSize %d\n", fib->Header.SenderSize);
device_printf(sc->aac_dev, " SenderAddress 0x%x\n", fib->Header.SenderFibAddress);
device_printf(sc->aac_dev, " ReceiverAddress 0x%x\n", fib->Header.ReceiverFibAddress);
device_printf(sc->aac_dev, " SenderData 0x%x\n", fib->Header.SenderData);
switch(fib->Header.Command) {
case ContainerCommand:
{
struct aac_blockread *br = (struct aac_blockread *)fib->data;
struct aac_blockwrite *bw = (struct aac_blockwrite *)fib->data;
struct aac_sg_table *sg = NULL;
int i;
if (br->Command == VM_CtBlockRead) {
device_printf(sc->aac_dev, " BlockRead: container %d 0x%x/%d\n",
br->ContainerId, br->BlockNumber, br->ByteCount);
sg = &br->SgMap;
}
if (bw->Command == VM_CtBlockWrite) {
device_printf(sc->aac_dev, " BlockWrite: container %d 0x%x/%d (%s)\n",
bw->ContainerId, bw->BlockNumber, bw->ByteCount,
bw->Stable == CSTABLE ? "stable" : "unstable");
sg = &bw->SgMap;
}
if (sg != NULL) {
device_printf(sc->aac_dev, " %d s/g entries\n", sg->SgCount);
for (i = 0; i < sg->SgCount; i++)
device_printf(sc->aac_dev, " 0x%08x/%d\n", sg->SgEntry[i].SgAddress, sg->SgEntry[i].SgByteCount);
}
break;
}
default:
device_printf(sc->aac_dev, " %16D\n", fib->data, " ");
device_printf(sc->aac_dev, " %16D\n", fib->data + 16, " ");
break;
}
}
/********************************************************************************
* Describe an AIF we have received.
*/
void
aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif)
{
switch(aif->command) {
case AifCmdEventNotify:
device_printf(sc->aac_dev, "EventNotify (%d)\n", aif->seqNumber);
switch(aif->data.EN.type) {
case AifEnGeneric: /* Generic notification */
device_printf(sc->aac_dev, "(Generic) %.*s\n",
(int)sizeof(aif->data.EN.data.EG), aif->data.EN.data.EG.text);
break;
case AifEnTaskComplete: /* Task has completed */
device_printf(sc->aac_dev, "(TaskComplete)\n");
break;
case AifEnConfigChange: /* Adapter configuration change occurred */
device_printf(sc->aac_dev, "(ConfigChange)\n");
break;
case AifEnContainerChange: /* Adapter specific container configuration change */
device_printf(sc->aac_dev, "(ContainerChange) container %d,%d\n",
aif->data.EN.data.ECC.container[0],
aif->data.EN.data.ECC.container[1]);
break;
case AifEnDeviceFailure: /* SCSI device failed */
device_printf(sc->aac_dev, "(DeviceFailure) handle %d\n",
aif->data.EN.data.EDF.deviceHandle); /* XXX interpret */
break;
case AifEnMirrorFailover: /* Mirror failover started */
device_printf(sc->aac_dev, "(MirrorFailover) container %d failed, migrating from slice %d to %d\n",
aif->data.EN.data.EMF.container,
aif->data.EN.data.EMF.failedSlice,
aif->data.EN.data.EMF.creatingSlice);
break;
case AifEnContainerEvent: /* Significant container event */
device_printf(sc->aac_dev, "(ContainerEvent) container %d event %d\n",
aif->data.EN.data.ECE.container,
aif->data.EN.data.ECE.eventType); /* XXX interpret? */
break;
case AifEnFileSystemChange: /* File system changed */
device_printf(sc->aac_dev, "(FileSystemChange)\n");
break;
case AifEnConfigPause: /* Container pause event */
device_printf(sc->aac_dev, "(ConfigPause)\n");
break;
case AifEnConfigResume: /* Container resume event */
device_printf(sc->aac_dev, "(ConfigResume)\n");
break;
case AifEnFailoverChange: /* Failover space assignment changed */
device_printf(sc->aac_dev, "(FailoverChange)\n");
break;
case AifEnRAID5RebuildDone: /* RAID5 rebuild finished */
device_printf(sc->aac_dev, "(RAID5RebuildDone)\n");
break;
case AifEnEnclosureManagement: /* Enclosure management event */
device_printf(sc->aac_dev, "(EnclosureManagement) EMPID %d unit %d event %d\n",
aif->data.EN.data.EEE.empID,
aif->data.EN.data.EEE.unitID,
aif->data.EN.data.EEE.eventType);
break;
case AifEnBatteryEvent: /* Significant NV battery event */
device_printf(sc->aac_dev, "(BatteryEvent) %d (state was %d, is %d)\n",
aif->data.EN.data.EBE.transition_type, /* XXX interpret */
aif->data.EN.data.EBE.current_state,
aif->data.EN.data.EBE.prior_state);
break;
case AifEnAddContainer: /* A new container was created. */
device_printf(sc->aac_dev, "(AddContainer)\n");
break;
case AifEnDeleteContainer: /* A container was deleted. */
device_printf(sc->aac_dev, "(DeleteContainer)\n");
break;
case AifEnBatteryNeedsRecond: /* The battery needs reconditioning */
device_printf(sc->aac_dev, "(BatteryNeedsRecond)\n");
break;
case AifEnClusterEvent: /* Some cluster event */
device_printf(sc->aac_dev, "(ClusterEvent) event %d\n",
aif->data.EN.data.ECLE.eventType);
break;
case AifEnDiskSetEvent: /* A disk set event occured. */
device_printf(sc->aac_dev, "(DiskSetEvent) event %d diskset %lld creator %lld\n",
aif->data.EN.data.EDS.eventType,
aif->data.EN.data.EDS.DsNum,
aif->data.EN.data.EDS.CreatorId);
break;
case AifDenMorphComplete: /* A morph operation completed */
device_printf(sc->aac_dev, "(MorphComplete)\n");
break;
case AifDenVolumeExtendComplete: /* A volume expand operation completed */
device_printf(sc->aac_dev, "(VolumeExtendComplete)\n");
break;
default:
device_printf(sc->aac_dev, "(%d)\n", aif->data.EN.type);
break;
}
break;
case AifCmdJobProgress:
{
char *status;
switch(aif->data.PR[0].status) {
case AifJobStsSuccess:
status = "success"; break;
case AifJobStsFinished:
status = "finished"; break;
case AifJobStsAborted:
status = "aborted"; break;
case AifJobStsFailed:
status = "failed"; break;
case AifJobStsSuspended:
status = "suspended"; break;
case AifJobStsRunning:
status = "running"; break;
default:
status = "unknown status"; break;
}
device_printf(sc->aac_dev, "JobProgress (%d) - %s (%d, %d)\n", aif->seqNumber, status,
aif->data.PR[0].currentTick, aif->data.PR[0].finalTick);
switch(aif->data.PR[0].jd.type) {
case AifJobScsiZero: /* SCSI device clear operation */
device_printf(sc->aac_dev, "(ScsiZero) handle %d\n", aif->data.PR[0].jd.client.scsi_dh);
break;
case AifJobScsiVerify: /* SCSI device Verify operation NO REPAIR */
device_printf(sc->aac_dev, "(ScsiVerify) handle %d\n", aif->data.PR[0].jd.client.scsi_dh);
break;
case AifJobScsiExercise: /* SCSI device Exercise operation */
device_printf(sc->aac_dev, "(ScsiExercise) handle %d\n", aif->data.PR[0].jd.client.scsi_dh);
break;
case AifJobScsiVerifyRepair: /* SCSI device Verify operation WITH repair */
device_printf(sc->aac_dev, "(ScsiVerifyRepair) handle %d\n", aif->data.PR[0].jd.client.scsi_dh);
break;
case AifJobCtrZero: /* Container clear operation */
device_printf(sc->aac_dev, "(ConatainerZero) container %d\n",
aif->data.PR[0].jd.client.container.src);
break;
case AifJobCtrCopy: /* Container copy operation */
device_printf(sc->aac_dev, "(ConatainerCopy) container %d to %d\n",
aif->data.PR[0].jd.client.container.src, aif->data.PR[0].jd.client.container.dst);
break;
case AifJobCtrCreateMirror: /* Container Create Mirror operation */
device_printf(sc->aac_dev, "(ConatainerCreateMirror) container %d\n",
aif->data.PR[0].jd.client.container.src); /* XXX two containers? */
break;
case AifJobCtrMergeMirror: /* Container Merge Mirror operation */
device_printf(sc->aac_dev, "(ConatainerMergeMirror) container %d\n",
aif->data.PR[0].jd.client.container.src); /* XXX two containers? */
break;
case AifJobCtrScrubMirror: /* Container Scrub Mirror operation */
device_printf(sc->aac_dev, "(ConatainerScrubMirror) container %d\n",
aif->data.PR[0].jd.client.container.src);
break;
case AifJobCtrRebuildRaid5: /* Container Rebuild Raid5 operation */
device_printf(sc->aac_dev, "(ConatainerRebuildRaid5) container %d\n",
aif->data.PR[0].jd.client.container.src);
break;
case AifJobCtrScrubRaid5: /* Container Scrub Raid5 operation */
device_printf(sc->aac_dev, "(ConatainerScrubRaid5) container %d\n",
aif->data.PR[0].jd.client.container.src);
break;
case AifJobCtrMorph: /* Container morph operation */
device_printf(sc->aac_dev, "(ConatainerMorph) container %d\n",
aif->data.PR[0].jd.client.container.src); /* XXX two containers? */
break;
case AifJobCtrPartCopy: /* Container Partition copy operation */
device_printf(sc->aac_dev, "(ConatainerPartCopy) container %d to %d\n",
aif->data.PR[0].jd.client.container.src, aif->data.PR[0].jd.client.container.dst);
break;
case AifJobCtrRebuildMirror: /* Container Rebuild Mirror operation */
device_printf(sc->aac_dev, "(ConatainerRebuildMirror) container %d\n",
aif->data.PR[0].jd.client.container.src);
break;
case AifJobCtrCrazyCache: /* crazy cache */
device_printf(sc->aac_dev, "(ConatainerCrazyCache) container %d\n",
aif->data.PR[0].jd.client.container.src); /* XXX two containers? */
break;
case AifJobFsCreate: /* File System Create operation */
device_printf(sc->aac_dev, "(FsCreate)\n");
break;
case AifJobFsVerify: /* File System Verify operation */
device_printf(sc->aac_dev, "(FsVerivy)\n");
break;
case AifJobFsExtend: /* File System Extend operation */
device_printf(sc->aac_dev, "(FsExtend)\n");
break;
case AifJobApiFormatNTFS: /* Format a drive to NTFS */
device_printf(sc->aac_dev, "(FormatNTFS)\n");
break;
case AifJobApiFormatFAT: /* Format a drive to FAT */
device_printf(sc->aac_dev, "(FormatFAT)\n");
break;
case AifJobApiUpdateSnapshot: /* update the read/write half of a snapshot */
device_printf(sc->aac_dev, "(UpdateSnapshot)\n");
break;
case AifJobApiFormatFAT32: /* Format a drive to FAT32 */
device_printf(sc->aac_dev, "(FormatFAT32)\n");
break;
case AifJobCtlContinuousCtrVerify: /* Adapter operation */
device_printf(sc->aac_dev, "(ContinuousCtrVerify)\n");
break;
default:
device_printf(sc->aac_dev, "(%d)\n", aif->data.PR[0].jd.type);
break;
}
break;
}
case AifCmdAPIReport:
device_printf(sc->aac_dev, "APIReport (%d)\n", aif->seqNumber);
break;
case AifCmdDriverNotify:
device_printf(sc->aac_dev, "DriverNotify (%d)\n", aif->seqNumber);
break;
default:
device_printf(sc->aac_dev, "AIF %d (%d)\n", aif->command, aif->seqNumber);
break;
}
}

296
sys/dev/aac/aac_disk.c Normal file
View File

@ -0,0 +1,296 @@
/*-
* Copyright (c) 2000 Michael Smith
* Copyright (c) 2000 BSDi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <dev/aac/aac_compat.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/devicestat.h>
#include <sys/disk.h>
#include <machine/bus.h>
#include <machine/clock.h>
#include <sys/rman.h>
#include <dev/aac/aacreg.h>
#include <dev/aac/aacvar.h>
/*
* Interface to parent.
*/
static int aac_disk_probe(device_t dev);
static int aac_disk_attach(device_t dev);
static int aac_disk_detach(device_t dev);
/*
* Interface to the device switch.
*/
static d_open_t aac_disk_open;
static d_close_t aac_disk_close;
static d_strategy_t aac_disk_strategy;
#define AAC_DISK_CDEV_MAJOR 151
static struct cdevsw aac_disk_cdevsw = {
/* open */ aac_disk_open,
/* close */ aac_disk_close,
/* read */ physread,
/* write */ physwrite,
/* ioctl */ noioctl,
/* poll */ nopoll,
/* mmap */ nommap,
/* strategy */ aac_disk_strategy,
/* name */ "aacd",
/* maj */ AAC_DISK_CDEV_MAJOR,
/* dump */ nodump,
/* psize */ nopsize,
/* flags */ D_DISK,
/* bmaj */ -1
};
devclass_t aac_disk_devclass;
static struct cdevsw aac_disk_disk_cdevsw;
#ifdef FREEBSD_4
static int disks_registered = 0;
#endif
static device_method_t aac_disk_methods[] = {
DEVMETHOD(device_probe, aac_disk_probe),
DEVMETHOD(device_attach, aac_disk_attach),
DEVMETHOD(device_detach, aac_disk_detach),
{ 0, 0 }
};
static driver_t aac_disk_driver = {
"aacd",
aac_disk_methods,
sizeof(struct aac_disk)
};
DRIVER_MODULE(aacd, aac, aac_disk_driver, aac_disk_devclass, 0, 0);
/********************************************************************************
* Handle open from generic layer.
*
* This is called by the diskslice code on first open in order to get the
* basic device geometry paramters.
*/
static int
aac_disk_open(dev_t dev, int flags, int fmt, struct proc *p)
{
struct aac_disk *sc = (struct aac_disk *)dev->si_drv1;
struct disklabel *label;
debug_called(4);
if (sc == NULL)
return (ENXIO);
/* check that the controller is up and running */
if (sc->ad_controller->aac_state & AAC_STATE_SUSPEND)
return(ENXIO);
/* build synthetic label */
label = &sc->ad_disk.d_label;
bzero(label, sizeof(*label));
label->d_type = DTYPE_ESDI;
label->d_secsize = AAC_BLOCK_SIZE;
label->d_nsectors = sc->ad_sectors;
label->d_ntracks = sc->ad_heads;
label->d_ncylinders = sc->ad_cylinders;
label->d_secpercyl = sc->ad_sectors * sc->ad_heads;
label->d_secperunit = sc->ad_size;
sc->ad_flags |= AAC_DISK_OPEN;
return (0);
}
/********************************************************************************
* Handle last close of the disk device.
*/
static int
aac_disk_close(dev_t dev, int flags, int fmt, struct proc *p)
{
struct aac_disk *sc = (struct aac_disk *)dev->si_drv1;
debug_called(4);
if (sc == NULL)
return (ENXIO);
sc->ad_flags &= ~AAC_DISK_OPEN;
return (0);
}
/********************************************************************************
* Handle an I/O request.
*/
static void
aac_disk_strategy(struct bio *bp)
{
struct aac_disk *sc = (struct aac_disk *)bp->bio_dev->si_drv1;
debug_called(4);
/* bogus disk? */
if (sc == NULL) {
bp->bio_flags |= BIO_ERROR;
bp->bio_error = EINVAL;
biodone(bp);
return;
}
/* do-nothing operation? */
if (bp->bio_bcount == 0) {
bp->bio_resid = bp->bio_bcount;
biodone(bp);
return;
}
/* perform accounting */
devstat_start_transaction(&sc->ad_stats);
/* pass the bio to the controller - it can work out who we are */
aac_submit_bio(bp);
return;
}
/********************************************************************************
* Handle completion of an I/O request.
*/
void
aac_complete_bio(struct bio *bp)
{
struct aac_disk *sc = (struct aac_disk *)bp->bio_dev->si_drv1;
debug_called(4);
devstat_end_transaction_bio(&sc->ad_stats, bp);
biodone(bp);
}
/********************************************************************************
* Stub only.
*/
static int
aac_disk_probe(device_t dev)
{
debug_called(4);
return (0);
}
/********************************************************************************
* Attach a unit to the controller.
*/
static int
aac_disk_attach(device_t dev)
{
struct aac_disk *sc = (struct aac_disk *)device_get_softc(dev);
int sgspace;
int maxsg;
debug_called(4);
/* initialise our softc */
sc->ad_controller = (struct aac_softc *)device_get_softc(device_get_parent(dev));
sc->ad_container = device_get_ivars(dev);
sc->ad_dev = dev;
/* require that extended translation be enabled XXX document! */
sc->ad_size = sc->ad_container->co_mntobj.Capacity;
if (sc->ad_size >= (2 * 1024 * 1024)) { /* 2GB */
sc->ad_heads = 255;
sc->ad_sectors = 63;
} else if (sc->ad_size >= (2 * 1024 * 1024)) { /* 1GB */
sc->ad_heads = 128;
sc->ad_sectors = 32;
} else {
sc->ad_heads = 64;
sc->ad_sectors = 32;
}
sc->ad_cylinders = (sc->ad_size / (sc->ad_heads * sc->ad_sectors));
device_printf(dev, "%uMB (%u sectors)\n",
sc->ad_size / ((1024 * 1024) / AAC_BLOCK_SIZE), sc->ad_size);
devstat_add_entry(&sc->ad_stats, "aacd", device_get_unit(dev), AAC_BLOCK_SIZE,
DEVSTAT_NO_ORDERED_TAGS,
DEVSTAT_TYPE_STORARRAY | DEVSTAT_TYPE_IF_OTHER,
DEVSTAT_PRIORITY_ARRAY);
/* attach a generic disk device to ourselves */
sc->ad_dev_t = disk_create(device_get_unit(dev), &sc->ad_disk, 0, &aac_disk_cdevsw, &aac_disk_disk_cdevsw);
sc->ad_dev_t->si_drv1 = sc;
#ifdef FREEBSD_4
disks_registered++;
#endif
/*
* We can calculate the maximum number of s/g entries based on the size of the
* FIB and the command structures packed within it.
*/
sgspace = (sizeof(struct aac_fib) - sizeof(struct aac_fib_header) -
imax(sizeof(struct aac_blockwrite), sizeof(struct aac_blockread)));
maxsg = (sgspace - sizeof(struct aac_sg_table)) / sizeof(struct aac_sg_entry);
/* set the maximum I/O size to the theoretical worst maximum allowed by the S/G list size */
sc->ad_dev_t->si_iosize_max = (maxsg - 1) * PAGE_SIZE;
return (0);
}
/********************************************************************************
* Disconnect ourselves from the system.
*/
static int
aac_disk_detach(device_t dev)
{
struct aac_disk *sc = (struct aac_disk *)device_get_softc(dev);
debug_called(4);
if (sc->ad_flags & AAC_DISK_OPEN)
return(EBUSY);
devstat_remove_entry(&sc->ad_stats);
#ifdef FREEBSD_4
if (--disks_registered == 0)
cdevsw_remove(&aac_disk_disk_cdevsw);
#else
disk_destroy(sc->ad_dev_t);
#endif
return(0);
}

78
sys/dev/aac/aac_ioctl.h Normal file
View File

@ -0,0 +1,78 @@
/*-
* Copyright (c) 2000 Michael Smith
* Copyright (c) 2000 Scott Long
* Copyright (c) 2000 BSDi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifdef AAC_COMPAT_LINUX
/*
* Ioctl commands likely to be submitted from a Linux management application.
* These bit encodings are actually descended from Windows NT. Ick.
*/
#define CTL_CODE(devType, func, meth, acc) (((devType) << 16) | ((acc) << 14) | ((func) << 2) | (meth))
#define METHOD_BUFFERED 0
#define METHOD_IN_DIRECT 1
#define METHOD_OUT_DIRECT 2
#define METHOD_NEITHER 3
#define FILE_ANY_ACCESS 0
#define FILE_READ_ACCESS ( 0x0001 )
#define FILE_WRITE_ACCESS ( 0x0002 )
#define FILE_DEVICE_CONTROLLER 0x00000004
#define FSACTL_SENDFIB CTL_CODE(FILE_DEVICE_CONTROLLER, 2050, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSACTL_AIF_THREAD CTL_CODE(FILE_DEVICE_CONTROLLER, 2127, METHOD_NEITHER, FILE_ANY_ACCESS)
#define FSACTL_OPEN_GET_ADAPTER_FIB CTL_CODE(FILE_DEVICE_CONTROLLER, 2100, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSACTL_GET_NEXT_ADAPTER_FIB CTL_CODE(FILE_DEVICE_CONTROLLER, 2101, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSACTL_CLOSE_GET_ADAPTER_FIB CTL_CODE(FILE_DEVICE_CONTROLLER, 2102, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSACTL_MINIPORT_REV_CHECK CTL_CODE(FILE_DEVICE_CONTROLLER, 2107, METHOD_BUFFERED, FILE_ANY_ACCESS)
/*
* Support for faking the "miniport" version.
*/
struct aac_rev_check {
RevComponent callingComponent;
struct FsaRevision callingRevision;
};
struct aac_rev_check_resp {
int possiblyCompatible;
struct FsaRevision adapterSWRevision;
};
/*
* Context passed in by a consumer looking to collect an AIF.
*/
#define AAC_AIF_SILLYMAGIC 0xdeadbeef
struct get_adapter_fib_ioctl {
u_int32_t AdapterFibContext;
int Wait;
caddr_t AifFib;
};
#endif

272
sys/dev/aac/aac_pci.c Normal file
View File

@ -0,0 +1,272 @@
/*-
* Copyright (c) 2000 Michael Smith
* Copyright (c) 2000 BSDi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* PCI bus interface and resource allocation.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <dev/aac/aac_compat.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/devicestat.h>
#include <sys/disk.h>
#include <machine/bus_memio.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <pci/pcireg.h>
#include <pci/pcivar.h>
#include <dev/aac/aacreg.h>
#include <dev/aac/aacvar.h>
static int aac_pci_probe(device_t dev);
static int aac_pci_attach(device_t dev);
static device_method_t aac_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, aac_pci_probe),
DEVMETHOD(device_attach, aac_pci_attach),
DEVMETHOD(device_detach, aac_detach),
DEVMETHOD(device_shutdown, aac_shutdown),
DEVMETHOD(device_suspend, aac_suspend),
DEVMETHOD(device_resume, aac_resume),
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
{ 0, 0 }
};
static driver_t aac_pci_driver = {
"aac",
aac_methods,
sizeof(struct aac_softc)
};
DRIVER_MODULE(aac, pci, aac_pci_driver, aac_devclass, 0, 0);
struct aac_ident
{
u_int16_t vendor;
u_int16_t device;
u_int16_t subvendor;
u_int16_t subdevice;
int hwif;
char *desc;
} aac_identifiers[] = {
{0x1028, 0x0001, 0x1028, 0x0001, AAC_HWIF_I960RX, "Dell PERC 2/Si"},
{0x1028, 0x0002, 0x1028, 0x0002, AAC_HWIF_I960RX, "Dell PERC 3/Di"},
{0x1028, 0x0003, 0x1028, 0x0003, AAC_HWIF_I960RX, "Dell PERC 3/Si"},
{0x9005, 0x0282, 0x9005, 0x0282, AAC_HWIF_I960RX, "Adaptec AAC-2622"},
{0x1011, 0x0046, 0x9005, 0x0364, AAC_HWIF_STRONGARM, "Adaptec AAC-364"},
{0x1011, 0x0046, 0x9005, 0x0365, AAC_HWIF_STRONGARM, "Adaptec AAC-3642"},
{0x1011, 0x0046, 0x9005, 0x1364, AAC_HWIF_STRONGARM, "Dell PERC 2/QC"},
{0x1011, 0x0046, 0x9005, 0x1365, AAC_HWIF_STRONGARM, "Dell PERC 3/QC"}, /* XXX guess */
{0x1011, 0x0046, 0x103c, 0x10c2, AAC_HWIF_STRONGARM, "HP NetRaid-4M"},
{0, 0, 0, 0, 0, 0}
};
/********************************************************************************
* Determine whether this is one of our supported adapters.
*/
static int
aac_pci_probe(device_t dev)
{
struct aac_ident *m;
debug_called(1);
for (m = aac_identifiers; m->vendor != 0; m++) {
if ((m->vendor == pci_get_vendor(dev)) &&
(m->device == pci_get_device(dev)) &&
((m->subvendor == 0) || (m->subvendor == pci_get_subvendor(dev))) &&
((m->subdevice == 0) || ((m->subdevice == pci_get_subdevice(dev))))) {
device_set_desc(dev, m->desc);
return(0);
}
}
return(ENXIO);
}
/********************************************************************************
* Allocate resources for our device, set up the bus interface.
*/
static int
aac_pci_attach(device_t dev)
{
struct aac_softc *sc;
int i, error;
u_int32_t command;
debug_called(1);
/*
* Initialise softc.
*/
sc = device_get_softc(dev);
bzero(sc, sizeof(*sc));
sc->aac_dev = dev;
/* assume failure is 'not configured' */
error = ENXIO;
/*
* Verify that the adapter is correctly set up in PCI space.
*/
command = pci_read_config(sc->aac_dev, PCIR_COMMAND, 2);
command |= PCIM_CMD_BUSMASTEREN;
pci_write_config(dev, PCIR_COMMAND, command, 2);
command = pci_read_config(sc->aac_dev, PCIR_COMMAND, 2);
if (!(command & PCIM_CMD_BUSMASTEREN)) {
device_printf(sc->aac_dev, "can't enable bus-master feature\n");
goto out;
}
if ((command & PCIM_CMD_MEMEN) == 0) {
device_printf(sc->aac_dev, "memory window not available\n");
goto out;
}
/*
* Allocate the PCI register window.
*/
sc->aac_regs_rid = 0x10; /* first base address register */
if ((sc->aac_regs_resource = bus_alloc_resource(sc->aac_dev, SYS_RES_MEMORY, &sc->aac_regs_rid,
0, ~0, 1, RF_ACTIVE)) == NULL) {
device_printf(sc->aac_dev, "couldn't allocate register window\n");
goto out;
}
sc->aac_btag = rman_get_bustag(sc->aac_regs_resource);
sc->aac_bhandle = rman_get_bushandle(sc->aac_regs_resource);
/*
* Allocate and connect our interrupt.
*/
sc->aac_irq_rid = 0;
if ((sc->aac_irq = bus_alloc_resource(sc->aac_dev, SYS_RES_IRQ, &sc->aac_irq_rid,
0, ~0, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
device_printf(sc->aac_dev, "can't allocate interrupt\n");
goto out;
}
if (bus_setup_intr(sc->aac_dev, sc->aac_irq, INTR_TYPE_BIO, aac_intr, sc, &sc->aac_intr)) {
device_printf(sc->aac_dev, "can't set up interrupt\n");
goto out;
}
/* assume failure is 'out of memory' */
error = ENOMEM;
/*
* Allocate the parent bus DMA tag appropriate for our PCI interface.
*
* Note that some of these controllers are 64-bit capable.
*/
if (bus_dma_tag_create(NULL, /* parent */
1, 0, /* alignment, boundary */
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
MAXBSIZE, AAC_MAXSGENTRIES, /* maxsize, nsegments */
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
BUS_DMA_ALLOCNOW, /* flags */
&sc->aac_parent_dmat)) {
device_printf(sc->aac_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->aac_parent_dmat, /* parent */
1, 0, /* alignment, boundary */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
MAXBSIZE, AAC_MAXSGENTRIES, /* maxsize, nsegments */
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
0, /* flags */
&sc->aac_buffer_dmat)) {
device_printf(sc->aac_dev, "can't allocate buffer DMA tag\n");
goto out;
}
/*
* Create DMA tag for mapping FIBs into controller-addressable space..
*/
if (bus_dma_tag_create(sc->aac_parent_dmat, /* parent */
1, 0, /* alignment, boundary */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
AAC_CLUSTER_COUNT * sizeof(struct aac_fib), 1,/* maxsize, nsegments */
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
0, /* flags */
&sc->aac_fib_dmat)) {
device_printf(sc->aac_dev, "can't allocate FIB DMA tag\n");
goto out;
}
/*
* Detect the hardware interface version, set up the bus interface indirection.
*/
for (i = 0; aac_identifiers[i].vendor != 0; i++) {
if ((aac_identifiers[i].vendor == pci_get_vendor(dev)) &&
(aac_identifiers[i].device == pci_get_device(dev))) {
sc->aac_hwif = aac_identifiers[i].hwif;
switch(sc->aac_hwif) {
case AAC_HWIF_I960RX:
debug(2, "set hardware up for i960Rx");
sc->aac_if = aac_rx_interface;
break;
case AAC_HWIF_STRONGARM:
debug(2, "set hardware up for StrongARM");
sc->aac_if = aac_sa_interface;
break;
}
break;
}
}
/*
* Do bus-independent initialisation.
*/
error = aac_attach(sc);
out:
if (error)
aac_free(sc);
return(error);
}

117
sys/dev/aac/aac_tables.h Normal file
View File

@ -0,0 +1,117 @@
/*-
* Copyright (c) 2000 Michael Smith
* Copyright (c) 2000 BSDi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* Status codes for block read/write commands, etc.
*
* XXX many of these would not normally be returned, as they are
* relevant only to FSA operations.
*/
static struct aac_code_lookup aac_command_status_table[] = {
{"OK", 0},
{"operation not permitted", 1},
{"not found", 2},
{"I/O error", 5},
{"device not configured", 6},
{"too big", 7},
{"permission denoed", 13},
{"file exists", 17},
{"cross-device link", 18},
{"operation not supported by device", 19},
{"not a directory", 20},
{"is a directory", 21},
{"invalid argument", 22},
{"file too large", 27},
{"no space on device", 28},
{"readonly filesystem", 30},
{"too many links", 31},
{"operation would block", 35},
{"file name too long", 63},
{"directory not empty", 66},
{"quota exceeded", 69},
{"stale file handle", 70},
{"too many levels of remote in path", 71},
{"bad file handle", 10001},
{"not sync", 10002},
{"bad cookie", 10003},
{"operation not supported", 10004},
{"too small", 10005},
{"server fault", 10006},
{"bad type", 10007},
{"jukebox", 10008},
{"not mounted", 10009},
{"in maintenace mode", 10010},
{"stale ACL", 10011},
{NULL, 0},
{"unknown command status", 0}
};
#define AAC_COMMAND_STATUS(x) aac_describe_code(aac_command_status_table, x)
static struct aac_code_lookup aac_cpu_variant[] = {
{"i960JX", CPUI960_JX},
{"i960CX", CPUI960_CX},
{"i960HX", CPUI960_HX},
{"i960RX", CPUI960_RX},
{"StrongARM SA110", CPUARM_SA110},
{"PowerPC 603e", CPUPPC_603e},
{"Unknown StrongARM", CPUARM_xxx},
{"Unknown PowerPC", CPUPPC_xxx},
{NULL, 0},
{"Unknown processor", 0}
};
static struct aac_code_lookup aac_battery_platform[] = {
{"required battery present", PLATFORM_BAT_REQ_PRESENT},
{"REQUIRED BATTERY NOT PRESENT", PLATFORM_BAT_REQ_NOTPRESENT},
{"optional battery present", PLATFORM_BAT_OPT_PRESENT},
{"optional battery not installed", PLATFORM_BAT_OPT_NOTPRESENT},
{"no battery support", PLATFORM_BAT_NOT_SUPPORTED},
{NULL, 0},
{"unknown battery platform", 0}
};
static struct aac_code_lookup aac_container_types[] = {
{"Volume", CT_VOLUME},
{"RAID 1 (Mirror)", CT_MIRROR},
{"RAID 0 (Stripe)", CT_STRIPE},
{"RAID 5", CT_RAID5},
{"SSRW", CT_SSRW},
{"SSRO", CT_SSRO},
{"Morph", CT_MORPH},
{"Passthrough", CT_PASSTHRU},
{"RAID 4", CT_RAID4},
{"RAID 10", CT_RAID10},
{"RAID 00", CT_RAID00},
{"Volume of Mirrors", CT_VOLUME_OF_MIRRORS},
{"Pseudo RAID 3", CT_PSEUDO_RAID3},
{NULL, 0},
{"unknown", 0}
};

1082
sys/dev/aac/aacreg.h Normal file

File diff suppressed because it is too large Load Diff

451
sys/dev/aac/aacvar.h Normal file
View File

@ -0,0 +1,451 @@
/*-
* Copyright (c) 2000 Michael Smith
* Copyright (c) 2000 BSDi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/********************************************************************************
********************************************************************************
Driver Parameter Definitions
********************************************************************************
********************************************************************************/
/*
* The firmware interface allows for a 16-bit s/g list length. We limit
* ourselves to a reasonable maximum and ensure alignment.
*/
#define AAC_MAXSGENTRIES 64 /* max S/G entries, limit 65535 */
/*
* We allocate a small set of FIBs for the adapter to use to send us messages.
*/
#define AAC_ADAPTER_FIBS 8
/*
* FIBs are allocated in clusters as we need them; each cluster must be physically
* contiguous. Set the number of FIBs to try to allocate in a cluster.
* Setting this value too high may result in FIBs not being available in conditions
* of high load with fragmented physical memory. The value must be a multiple of
* (PAGE_SIZE / 512).
*/
#define AAC_CLUSTER_COUNT 64
/*
* The controller reports status events in AIFs. We hang on to a number of these
* in order to pass them out to user-space management tools.
*/
#define AAC_AIFQ_LENGTH 64
/*
* Firmware messages are passed in the printf buffer.
*/
#define AAC_PRINTF_BUFSIZE 256
/*
* We wait this many seconds for the adapter to come ready if it is still booting
*/
#define AAC_BOOT_TIMEOUT (3 * 60)
/*
* Timeout for immediate commands.
*/
#define AAC_IMMEDIATE_TIMEOUT 30
/*
* Character device major numbers.
*/
#define AAC_DISK_MAJOR 200
/********************************************************************************
********************************************************************************
Driver Variable Definitions
********************************************************************************
********************************************************************************/
#if __FreeBSD_version >= 500005
# include <sys/taskqueue.h>
#endif
/*
* Per-container data structure
*/
struct aac_container
{
struct aac_mntobj co_mntobj;
device_t co_disk;
};
/*
* Per-disk structure
*/
struct aac_disk
{
device_t ad_dev;
dev_t ad_dev_t;
struct aac_softc *ad_controller;
struct aac_container *ad_container;
struct disk ad_disk;
struct devstat ad_stats;
struct disklabel ad_label;
int ad_flags;
#define AAC_DISK_OPEN (1<<0)
int ad_cylinders;
int ad_heads;
int ad_sectors;
u_int32_t ad_size;
};
/*
* Per-command control structure.
*/
struct aac_command
{
TAILQ_ENTRY(aac_command) cm_link; /* list linkage */
struct aac_softc *cm_sc; /* controller that owns us */
struct aac_fib *cm_fib; /* FIB associated with this command */
u_int32_t cm_fibphys; /* bus address of the FIB */
struct bio *cm_data; /* pointer to data in kernel space */
u_int32_t cm_datalen; /* data length */
bus_dmamap_t cm_datamap; /* DMA map for bio data */
struct aac_sg_table *cm_sgtable; /* pointer to s/g table in command */
int cm_flags;
#define AAC_CMD_MAPPED (1<<0) /* command has had its data mapped */
#define AAC_CMD_DATAIN (1<<1) /* command involves data moving from controller to host */
#define AAC_CMD_DATAOUT (1<<2) /* command involves data moving from host to controller */
#define AAC_CMD_COMPLETED (1<<3) /* command has been completed */
void (* cm_complete)(struct aac_command *cm);
void *cm_private;
};
/*
* Command/command packet cluster.
*
* 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.
*/
struct aac_command_cluster
{
TAILQ_ENTRY(aac_command_cluster) cmc_link;
struct aac_fib *cmc_fibs;
bus_dmamap_t cmc_fibmap;
u_int32_t cmc_fibphys;
struct aac_command cmc_command[AAC_CLUSTER_COUNT];
};
/*
* We gather a number of adapter-visible items into a single structure.
*
* The ordering of this strucure may be important; we copy the Linux driver:
*
* Adapter FIBs
* Init struct
* Queue headers (Comm Area)
* Printf buffer
*
* In addition, we add:
* Sync Fib
*/
struct aac_common {
/* fibs for the controller to send us messages */
struct aac_fib ac_fibs[AAC_ADAPTER_FIBS];
/* the init structure */
struct aac_adapter_init ac_init;
/* arena within which the queue structures are kept */
u_int8_t ac_qbuf[sizeof(struct aac_queue_table) + AAC_QUEUE_ALIGN];
/* buffer for text messages from the controller */
char ac_printf[AAC_PRINTF_BUFSIZE];
/* fib for synchronous commands */
struct aac_fib ac_sync_fib;
};
/*
* Interface operations
*/
struct aac_interface
{
int (* aif_get_fwstatus)(struct aac_softc *sc);
void (* aif_qnotify)(struct aac_softc *sc, int qbit);
int (* aif_get_istatus)(struct aac_softc *sc);
void (* aif_set_istatus)(struct aac_softc *sc, int mask);
void (* aif_set_mailbox)(struct aac_softc *sc, u_int32_t command,
u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3);
int (* aif_get_mailboxstatus)(struct aac_softc *sc);
void (* aif_set_interrupts)(struct aac_softc *sc, int enable);
};
extern struct aac_interface aac_rx_interface;
extern struct aac_interface aac_sa_interface;
#define AAC_GET_FWSTATUS(sc) ((sc)->aac_if.aif_get_fwstatus((sc)))
#define AAC_QNOTIFY(sc, qbit) ((sc)->aac_if.aif_qnotify((sc), (qbit)))
#define AAC_GET_ISTATUS(sc) ((sc)->aac_if.aif_get_istatus((sc)))
#define AAC_CLEAR_ISTATUS(sc, mask) ((sc)->aac_if.aif_set_istatus((sc), (mask)))
#define AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3) \
((sc)->aac_if.aif_set_mailbox((sc), (command), (arg0), (arg1), (arg2), (arg3)))
#define AAC_GET_MAILBOXSTATUS(sc) ((sc)->aac_if.aif_get_mailboxstatus((sc)))
#define AAC_MASK_INTERRUPTS(sc) ((sc)->aac_if.aif_set_interrupts((sc), 0))
#define AAC_UNMASK_INTERRUPTS(sc) ((sc)->aac_if.aif_set_interrupts((sc), 1))
#define AAC_SETREG4(sc, reg, val) bus_space_write_4(sc->aac_btag, sc->aac_bhandle, reg, val)
#define AAC_GETREG4(sc, reg) bus_space_read_4 (sc->aac_btag, sc->aac_bhandle, reg)
#define AAC_SETREG2(sc, reg, val) bus_space_write_2(sc->aac_btag, sc->aac_bhandle, reg, val)
#define AAC_GETREG2(sc, reg) bus_space_read_2 (sc->aac_btag, sc->aac_bhandle, reg)
#define AAC_SETREG1(sc, reg, val) bus_space_write_1(sc->aac_btag, sc->aac_bhandle, reg, val)
#define AAC_GETREG1(sc, reg) bus_space_read_1 (sc->aac_btag, sc->aac_bhandle, reg)
/*
* Per-controller structure.
*/
struct aac_softc
{
/* bus connections */
device_t aac_dev;
struct resource *aac_regs_resource; /* register interface window */
int aac_regs_rid; /* resource ID */
bus_space_handle_t aac_bhandle; /* bus space handle */
bus_space_tag_t aac_btag; /* bus space tag */
bus_dma_tag_t aac_parent_dmat; /* parent DMA tag */
bus_dma_tag_t aac_buffer_dmat; /* data buffer/command DMA tag */
struct resource *aac_irq; /* interrupt */
int aac_irq_rid;
void *aac_intr; /* interrupt handle */
/* controller features, limits and status */
int aac_state;
#define AAC_STATE_SUSPEND (1<<0)
#define AAC_STATE_OPEN (1<<1)
#define AAC_STATE_INTERRUPTS_ON (1<<2)
#define AAC_STATE_AIF_SLEEPER (1<<3)
struct FsaRevision aac_revision;
/* controller hardware interface */
int aac_hwif;
#define AAC_HWIF_I960RX 0
#define AAC_HWIF_STRONGARM 1
bus_dma_tag_t aac_common_dmat; /* common structure DMA tag */
bus_dmamap_t aac_common_dmamap; /* common structure DMA map */
struct aac_common *aac_common;
u_int32_t aac_common_busaddr;
struct aac_interface aac_if;
/* command/fib resources */
TAILQ_HEAD(,aac_command_cluster) aac_clusters; /* command memory blocks */
bus_dma_tag_t aac_fib_dmat; /* DMA tag for allocating FIBs */
/* command management */
TAILQ_HEAD(,aac_command) aac_freecmds; /* command structures available for reuse */
TAILQ_HEAD(,aac_command) aac_ready; /* commands on hold for controller resources */
TAILQ_HEAD(,aac_command) aac_completed; /* commands which have been returned by the controller */
struct bio_queue_head aac_bioq;
struct aac_queue_table *aac_queues;
struct aac_queue_entry *aac_qentries[AAC_QUEUE_COUNT];
/* connected containters */
struct aac_container aac_container[AAC_MAX_CONTAINERS];
/* delayed activity infrastructure */
#if __FreeBSD_version >= 500005
struct task aac_task_complete; /* deferred-completion task */
#endif
struct intr_config_hook aac_ich;
/* management interface */
dev_t aac_dev_t;
struct aac_aif_command aac_aifq[AAC_AIFQ_LENGTH];
int aac_aifq_head;
int aac_aifq_tail;
};
/*
* Public functions
*/
extern void aac_free(struct aac_softc *sc);
extern int aac_attach(struct aac_softc *sc);
extern int aac_detach(device_t dev);
extern int aac_shutdown(device_t dev);
extern int aac_suspend(device_t dev);
extern int aac_resume(device_t dev);
extern void aac_intr(void *arg);
extern devclass_t aac_devclass;
extern void aac_submit_bio(struct bio *bp);
extern void aac_complete_bio(struct bio *bp);
/*
* Debugging levels:
* 0 - quiet, only emit warnings
* 1 - noisy, emit major function points and things done
* 2 - extremely noisy, emit trace items in loops, etc.
*/
#ifdef AAC_DEBUG
#define debug(level, fmt, args...) do { if (level <= AAC_DEBUG) printf("%s: " fmt "\n", __FUNCTION__ , ##args); } while(0)
#define debug_called(level) do { if (level <= AAC_DEBUG) printf(__FUNCTION__ ": called\n"); } while(0)
extern void aac_print_queues(struct aac_softc *sc);
extern void aac_panic(struct aac_softc *sc, char *reason);
extern void aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, char *caller);
extern void aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif);
#define AAC_PRINT_FIB(sc, fib) aac_print_fib(sc, fib, __FUNCTION__)
#else
#define debug(level, fmt, args...)
#define debug_called(level)
#define aac_print_queues(sc)
#define aac_panic(sc, reason)
#define aac_print_aif(sc, aif)
#define AAC_PRINT_FIB(sc, fib)
#endif
struct aac_code_lookup {
char *string;
u_int32_t code;
};
/*
* Borrowed from <struct.h>
*/
/* Offset of the field in the structure. */
#define fldoff(name, field) \
((int)&(((struct name *)0)->field))
/********************************************************************************
* Queue primitives
*
* These are broken out individually to make statistics gathering easier.
*/
static __inline void
aac_enqueue_ready(struct aac_command *cm)
{
int s;
s = splbio();
TAILQ_INSERT_TAIL(&cm->cm_sc->aac_ready, cm, cm_link);
splx(s);
}
static __inline void
aac_requeue_ready(struct aac_command *cm)
{
int s;
s = splbio();
TAILQ_INSERT_HEAD(&cm->cm_sc->aac_ready, cm, cm_link);
splx(s);
}
static __inline struct aac_command *
aac_dequeue_ready(struct aac_softc *sc)
{
struct aac_command *cm;
int s;
s = splbio();
if ((cm = TAILQ_FIRST(&sc->aac_ready)) != NULL)
TAILQ_REMOVE(&sc->aac_ready, cm, cm_link);
splx(s);
return(cm);
}
static __inline void
aac_enqueue_completed(struct aac_command *cm)
{
int s;
s = splbio();
TAILQ_INSERT_TAIL(&cm->cm_sc->aac_completed, cm, cm_link);
splx(s);
}
static __inline struct aac_command *
aac_dequeue_completed(struct aac_softc *sc)
{
struct aac_command *cm;
int s;
s = splbio();
if ((cm = TAILQ_FIRST(&sc->aac_completed)) != NULL)
TAILQ_REMOVE(&sc->aac_completed, cm, cm_link);
splx(s);
return(cm);
}
static __inline void
aac_enqueue_free(struct aac_command *cm)
{
int s;
s = splbio();
TAILQ_INSERT_HEAD(&cm->cm_sc->aac_freecmds, cm, cm_link);
splx(s);
}
static __inline struct aac_command *
aac_dequeue_free(struct aac_softc *sc)
{
struct aac_command *cm;
int s;
s = splbio();
if ((cm = TAILQ_FIRST(&sc->aac_freecmds)) != NULL)
TAILQ_REMOVE(&sc->aac_freecmds, cm, cm_link);
splx(s);
return(cm);
}
static __inline void
aac_enqueue_cluster(struct aac_softc *sc, struct aac_command_cluster *cmc)
{
int s;
s = splbio();
TAILQ_INSERT_HEAD(&sc->aac_clusters, cmc, cmc_link);
splx(s);
}
static __inline struct aac_command_cluster *
aac_dequeue_cluster(struct aac_softc *sc)
{
struct aac_command_cluster *cmc;
int s;
s = splbio();
if ((cmc = TAILQ_FIRST(&sc->aac_clusters)) != NULL)
TAILQ_REMOVE(&sc->aac_clusters, cmc, cmc_link);
splx(s);
return(cmc);
}

View File

@ -112,6 +112,7 @@ device cd # CD
device pass # Passthrough device (direct SCSI access)
# RAID controllers
device aac # Adaptec FSA RAID
device ida # Compaq Smart RAID
device amr # AMI MegaRAID
device mlx # Mylex DAC960 family

View File

@ -1330,6 +1330,11 @@ options DPT_ALLOW_MEMIO
#
device mly
#
# Adaptec FSA RAID controllers, including integrated DELL controllers,
# the Dell PERC 2/QC and the HP NetRAID-4M
device aac
#
# Compaq Smart RAID, Mylex DAC960 and AMI MegaRAID controllers. Only
# one entry is needed; the code will find and configure all supported

View File

@ -17,7 +17,7 @@ SUBDIR= 3dfx accf_data accf_http agp aha amr an aue \
# XXX some of these can move to the general case when de-i386'ed
.if ${MACHINE_ARCH} == "i386"
SUBDIR+=asr bktr coff fpu gnufpu ibcs2 linprocfs linux mly splash streams \
SUBDIR+=aac asr bktr coff fpu gnufpu ibcs2 linprocfs linux mly splash streams \
svr4 vesa wi
.endif

13
sys/modules/aac/Makefile Normal file
View File

@ -0,0 +1,13 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../dev/aac
KMOD = aac
SRCS = aac.c aac_pci.c aac_disk.c
SRCS += device_if.h bus_if.h pci_if.h
CFLAGS+= -DAAC_COMPAT_LINUX
#CFLAGS+= -DAAC_DEBUG=2
#SRCS += aac_debug.c
.include <bsd.kmod.mk>

78
sys/sys/aac_ioctl.h Normal file
View File

@ -0,0 +1,78 @@
/*-
* Copyright (c) 2000 Michael Smith
* Copyright (c) 2000 Scott Long
* Copyright (c) 2000 BSDi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifdef AAC_COMPAT_LINUX
/*
* Ioctl commands likely to be submitted from a Linux management application.
* These bit encodings are actually descended from Windows NT. Ick.
*/
#define CTL_CODE(devType, func, meth, acc) (((devType) << 16) | ((acc) << 14) | ((func) << 2) | (meth))
#define METHOD_BUFFERED 0
#define METHOD_IN_DIRECT 1
#define METHOD_OUT_DIRECT 2
#define METHOD_NEITHER 3
#define FILE_ANY_ACCESS 0
#define FILE_READ_ACCESS ( 0x0001 )
#define FILE_WRITE_ACCESS ( 0x0002 )
#define FILE_DEVICE_CONTROLLER 0x00000004
#define FSACTL_SENDFIB CTL_CODE(FILE_DEVICE_CONTROLLER, 2050, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSACTL_AIF_THREAD CTL_CODE(FILE_DEVICE_CONTROLLER, 2127, METHOD_NEITHER, FILE_ANY_ACCESS)
#define FSACTL_OPEN_GET_ADAPTER_FIB CTL_CODE(FILE_DEVICE_CONTROLLER, 2100, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSACTL_GET_NEXT_ADAPTER_FIB CTL_CODE(FILE_DEVICE_CONTROLLER, 2101, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSACTL_CLOSE_GET_ADAPTER_FIB CTL_CODE(FILE_DEVICE_CONTROLLER, 2102, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSACTL_MINIPORT_REV_CHECK CTL_CODE(FILE_DEVICE_CONTROLLER, 2107, METHOD_BUFFERED, FILE_ANY_ACCESS)
/*
* Support for faking the "miniport" version.
*/
struct aac_rev_check {
RevComponent callingComponent;
struct FsaRevision callingRevision;
};
struct aac_rev_check_resp {
int possiblyCompatible;
struct FsaRevision adapterSWRevision;
};
/*
* Context passed in by a consumer looking to collect an AIF.
*/
#define AAC_AIF_SILLYMAGIC 0xdeadbeef
struct get_adapter_fib_ioctl {
u_int32_t AdapterFibContext;
int Wait;
caddr_t AifFib;
};
#endif