3ware 9000 driver, contributed by Wasabi Systems and written

by Jordan Rhody (based on the FreeBSD driver).

Contributed in NetBSD PR 33364.
This commit is contained in:
wrstuden 2006-05-24 23:44:28 +00:00
parent aecdec648e
commit a4dd1e2635
6 changed files with 4449 additions and 1 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: files.pci,v 1.253 2006/05/07 01:32:43 jmcneill Exp $
# $NetBSD: files.pci,v 1.254 2006/05/24 23:44:28 wrstuden Exp $
#
# Config file and device description for machine-independent PCI code.
# Included by ports that need it. Requires that the SCSI files be
@ -59,6 +59,13 @@ file dev/pci/twe.c twe
attach ld at twe with ld_twe
file dev/pci/ld_twe.c ld_twe
device twa {unit = -1}
attach twa at pci
file dev/pci/twa.c twa
attach ld at twa with ld_twa
file dev/pci/ld_twa.c ld_twa
# AMI RAID controllers
device amr {unit = -1}
attach amr at pci

315
sys/dev/pci/ld_twa.c Normal file
View File

@ -0,0 +1,315 @@
/* $wasabi: ld_twa.c,v 1.9 2006/02/14 18:44:37 jordanr Exp $ */
/* $netbsd: $ */
/*-
* Copyright (c) 2004 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jordan Rhody of Wasabi Systems, Inc.
*
* 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
/*
* 3ware "Apache" RAID controller front-end for ld(4) driver.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$wasabi: ld_twa.c,v 1.9 2006/02/14 18:44:37 jordanr Exp $");
#include "rnd.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/buf.h>
#include <sys/bufq.h>
#include <sys/endian.h>
#include <sys/dkio.h>
#include <sys/disk.h>
#if NRND > 0
#include <sys/rnd.h>
#endif
#include <machine/bus.h>
#include <uvm/uvm_extern.h>
#include <dev/ldvar.h>
#include <dev/scsipi/scsipi_all.h>
#include <dev/scsipi/scsipi_disk.h>
#include <dev/scsipi/scsipiconf.h>
#include <dev/scsipi/scsi_disk.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/twareg.h>
#include <dev/pci/twavar.h>
struct ld_twa_softc {
struct ld_softc sc_ld;
int sc_hwunit;
};
static void ld_twa_attach(struct device *, struct device *, void *);
static int ld_twa_detach(struct device *, int);
static int ld_twa_dobio(struct ld_twa_softc *, void *, int, int,
struct buf *);
static int ld_twa_dump(struct ld_softc *, void *, int, int);
static int ld_twa_flush(struct ld_softc *);
static void ld_twa_handler(struct twa_request *);
static int ld_twa_match(struct device *, struct cfdata *, void *);
static int ld_twa_start(struct ld_softc *, struct buf *);
static void ld_twa_adjqparam(struct device *, int);
static int ld_twa_scsicmd(struct ld_twa_softc *,
struct twa_request *, struct buf *);
CFATTACH_DECL(ld_twa, sizeof(struct ld_twa_softc),
ld_twa_match, ld_twa_attach, ld_twa_detach, NULL);
static const struct twa_callbacks ld_twa_callbacks = {
ld_twa_adjqparam,
};
static int
ld_twa_match(struct device *parent, struct cfdata *match, void *aux)
{
return (1);
}
static void
ld_twa_attach(struct device *parent, struct device *self, void *aux)
{
struct twa_attach_args *twa_args;
struct ld_twa_softc *sc;
struct ld_softc *ld;
struct twa_softc *twa;
sc = (struct ld_twa_softc *)self;
ld = &sc->sc_ld;
twa = (struct twa_softc *)parent;
twa_args = aux;
twa_register_callbacks(twa, twa_args->twaa_unit, &ld_twa_callbacks);
sc->sc_hwunit = twa_args->twaa_unit;
ld->sc_maxxfer = twa_get_maxxfer(twa_get_maxsegs());
ld->sc_secperunit = twa->sc_units[sc->sc_hwunit].td_size;
ld->sc_flags = LDF_ENABLED;
ld->sc_secsize = TWA_SECTOR_SIZE;
ld->sc_maxqueuecnt = twa->sc_openings;
ld->sc_start = ld_twa_start;
ld->sc_dump = ld_twa_dump;
ld->sc_flush = ld_twa_flush;
ldattach(ld);
}
static int
ld_twa_detach(struct device *self, int flags)
{
int error;
if ((error = ldbegindetach((struct ld_softc *)self, flags)) != 0)
return (error);
ldenddetach((struct ld_softc *)self);
return (0);
}
static int
ld_twa_dobio(struct ld_twa_softc *sc, void *data, int datasize, int blkno,
struct buf *bp)
{
int rv;
struct twa_request *tr;
struct twa_softc *twa;
twa = (struct twa_softc *)sc->sc_ld.sc_dv.dv_parent;
if ((tr = twa_get_request(twa, 0)) == NULL) {
return (EAGAIN);
}
if (bp->b_flags & B_READ) {
tr->tr_flags = TWA_CMD_DATA_OUT;
} else {
tr->tr_flags = TWA_CMD_DATA_IN;
}
tr->tr_data = data;
tr->tr_length = datasize;
tr->tr_cmd_pkt_type =
(TWA_CMD_PKT_TYPE_9K | TWA_CMD_PKT_TYPE_EXTERNAL);
tr->tr_command->cmd_hdr.header_desc.size_header = 128;
tr->tr_command->command.cmd_pkt_9k.command.opcode =
TWA_OP_EXECUTE_SCSI_COMMAND;
tr->tr_command->command.cmd_pkt_9k.unit =
sc->sc_hwunit;
tr->tr_command->command.cmd_pkt_9k.request_id =
tr->tr_request_id;
tr->tr_command->command.cmd_pkt_9k.status = 0;
tr->tr_command->command.cmd_pkt_9k.sgl_entries = 1;
tr->tr_command->command.cmd_pkt_9k.sgl_offset = 16;
/* offset from end of hdr = max cdb len */
ld_twa_scsicmd(sc, tr, bp);
tr->tr_callback = ld_twa_handler;
tr->tr_ld_sc = sc;
tr->bp = bp;
rv = twa_map_request(tr);
return (rv);
}
static int
ld_twa_start(struct ld_softc *ld, struct buf *bp)
{
return (ld_twa_dobio((struct ld_twa_softc *)ld, bp->b_data,
bp->b_bcount, bp->b_rawblkno, bp));
}
static void
ld_twa_handler(struct twa_request *tr)
{
uint8_t status;
struct buf *bp;
struct ld_twa_softc *sc;
struct twa_softc *twa;
bp = tr->bp;
sc = (struct ld_twa_softc *)tr->tr_ld_sc;
twa = (struct twa_softc *)sc->sc_ld.sc_dv.dv_parent;
status = tr->tr_command->command.cmd_pkt_9k.status;
if (status != 0) {
bp->b_flags |= B_ERROR;
bp->b_error = EIO;
bp->b_resid = bp->b_bcount;
} else {
bp->b_resid = 0;
bp->b_error = 0;
}
twa_release_request(tr);
lddone(&sc->sc_ld, bp);
}
static int
ld_twa_dump(struct ld_softc *ld, void *data, int blkno, int blkcnt)
{
return (ld_twa_dobio((struct ld_twa_softc *)ld, data,
blkcnt * ld->sc_secsize, blkno, NULL));
}
static int
ld_twa_flush(struct ld_softc *ld)
{
int s, rv = 0;
struct twa_request *tr;
struct twa_softc *twa = (void *)ld->sc_dv.dv_parent;
struct ld_twa_softc *sc = (void *)ld;
struct twa_command_generic *generic_cmd;
/* Get a request packet. */
tr = twa_get_request_wait(twa, 0);
KASSERT(tr != NULL);
tr->tr_cmd_pkt_type =
(TWA_CMD_PKT_TYPE_9K | TWA_CMD_PKT_TYPE_EXTERNAL);
tr->tr_callback = twa_request_wait_handler;
tr->tr_ld_sc = sc;
tr->tr_command->cmd_hdr.header_desc.size_header = 128;
generic_cmd = &(tr->tr_command->command.cmd_pkt_7k.generic);
generic_cmd->opcode = TWA_OP_FLUSH;
generic_cmd->size = 2;
generic_cmd->unit = sc->sc_hwunit;
generic_cmd->request_id = tr->tr_request_id;
generic_cmd->sgl_offset = 0;
generic_cmd->host_id = 0;
generic_cmd->status = 0;
generic_cmd->flags = 0;
generic_cmd->count = 0;
rv = twa_map_request(tr);
s = splbio();
while (tr->tr_status != TWA_CMD_COMPLETE)
if ((rv = tsleep(tr, PRIBIO, "twaflush", 60 * hz)) != 0)
break;
twa_release_request(tr);
splx(s);
return (rv);
}
static void
ld_twa_adjqparam(struct device *self, int openings)
{
ldadjqparam((struct ld_softc *)self, openings);
}
static int
ld_twa_scsicmd(struct ld_twa_softc *sc,
struct twa_request *tr, struct buf *bp)
{
if (tr->tr_flags == TWA_CMD_DATA_IN) {
tr->tr_command->command.cmd_pkt_9k.cdb[0] = WRITE_16;
} else {
tr->tr_command->command.cmd_pkt_9k.cdb[0] = READ_16;
}
tr->tr_command->command.cmd_pkt_9k.cdb[1] =
(sc->sc_hwunit << 5); /* lun for CDB */
_lto8b(htole64(bp->b_rawblkno),
&tr->tr_command->command.cmd_pkt_9k.cdb[2]);
_lto4b(htole32((bp->b_bcount / TWA_SECTOR_SIZE)),
&tr->tr_command->command.cmd_pkt_9k.cdb[10]);
tr->tr_command->command.cmd_pkt_9k.cdb[14] = 0;
tr->tr_command->command.cmd_pkt_9k.cdb[15] = 0;
return (0);
}

3233
sys/dev/pci/twa.c Normal file

File diff suppressed because it is too large Load Diff

155
sys/dev/pci/twaio.h Normal file
View File

@ -0,0 +1,155 @@
/* $wasabi: twaio.h,v 1.8 2006/04/27 17:12:39 wrstuden Exp $ */
/*
* Copyright (c) 2005-2006 Wasabi Systems, Inc.
* All rights reserved.
*
* Your Wasabi Systems License Agreement specifies the terms and
* conditions for use and redistribution.
*/
/*-
* Copyright (c) 2003-04 3ware, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*$FreeBSD: src/sys/dev/twa/twa_ioctl.h,v 1.1 2004/03/30 03:45:59 vkashyap Exp $
*/
/*
* 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
*/
#ifndef _DEV_PCI_TWAIO_H_
#define _DEV_PCI_TWAIO_H_
#define TWA_AEN_NOT_RETRIEVED 0x1
#define TWA_AEN_RETRIEVED 0x2
#define TWA_ERROR_AEN_NO_EVENTS 0x1003 /* No more events */
#define TWA_ERROR_AEN_OVERFLOW 0x1004 /* AEN clobber occurred */
#define TWA_ERROR_IOCTL_LOCK_NOT_HELD 0x1001 /* Not locked */
#define TWA_ERROR_IOCTL_LOCK_ALREADY_HELD 0x1002 /* Already locked */
struct twa_scan_bus_packet {
uint32_t unit;
} __attribute__ ((packed));
struct tw_cl_event_packet {
uint32_t sequence_id;
uint32_t time_stamp_sec;
uint16_t aen_code;
uint8_t severity;
uint8_t retrieved;
uint8_t repeat_count;
uint8_t parameter_len;
uint8_t parameter_data[98];
uint32_t event_src;
uint8_t severity_str[20];
} __attribute__ ((packed));
struct tw_cl_lock_packet {
uint32_t timeout_msec;
uint32_t time_remaining_msec;
uint32_t force_flag;
} __attribute__ ((packed));
struct tw_cl_compatibility_packet {
uint8_t driver_version[32];/* driver version */
uint16_t working_srl; /* driver & firmware negotiated srl */
uint16_t working_branch; /* branch # of the firmware that the driver is compatible with */
uint16_t working_build; /* build # of the firmware that the driver is compatible with */
} __attribute__ ((packed));
struct twa_driver_packet {
uint32_t control_code;
uint32_t status;
uint32_t unique_id;
uint32_t sequence_id;
uint32_t os_status;
uint32_t buffer_length;
} __attribute__ ((packed));
/* Account for differences between 32/64 bit system. Offsets into memory
* are anticipated for driver/firmware command packets and having a
* variable sized pointer depending on architecture add 4 bytes to any offset
* after the pdata declaration
*/
#define TW_SIZEOF_VOIDPTR (sizeof(void *))
struct twa_ioctl_9k {
struct twa_driver_packet twa_drvr_pkt;
void *pdata; /* points to data_buf */
int8_t padding[488 - TW_SIZEOF_VOIDPTR];
struct twa_command_packet twa_cmd_pkt;
int8_t data_buf[1];
} __attribute__ ((packed));
/*
* We need the structure below to ensure that the first byte of
* data_buf is not overwritten by the kernel, after we return
* from the ioctl call. Note that twa_cmd_pkt has been reduced
* to an array of 1024 bytes even though it's actually 2048 bytes
* in size. This is because, we don't expect requests from user
* land requiring 2048 (273 sg elements) byte cmd pkts.
*/
typedef struct twa_ioctl_no_data_buf {
struct twa_driver_packet twa_drvr_pkt;
void *pdata; /* points to data_buf */
int8_t padding[484];
struct twa_command_packet twa_cmd_pkt;
} __attribute__ ((packed)) TWA_IOCTL_NO_DATA_BUF;
/*
* Get the device external name of the specified array unit.
*/
/* WASABI */
struct twa_unitname {
int tn_unit;
char tn_name[16]; /* XXX sizeof(dev->dv_xname) */
};
#define TW_OSL_IOCTL_SCAN_BUS _IO ('T', 200)
#define TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH \
_IOWR('T', 202, TWA_IOCTL_NO_DATA_BUF)
#define TW_CL_IOCTL_GET_FIRST_EVENT _IOWR('T', 203, TWA_IOCTL_NO_DATA_BUF)
#define TW_CL_IOCTL_GET_LAST_EVENT _IOWR('T', 204, TWA_IOCTL_NO_DATA_BUF)
#define TW_CL_IOCTL_GET_NEXT_EVENT _IOWR('T', 205, TWA_IOCTL_NO_DATA_BUF)
#define TW_CL_IOCTL_GET_PREVIOUS_EVENT _IOWR('T', 206, TWA_IOCTL_NO_DATA_BUF)
#define TW_CL_IOCTL_GET_LOCK _IOWR('T', 207, TWA_IOCTL_NO_DATA_BUF)
#define TW_CL_IOCTL_RELEASE_LOCK _IOWR('T', 208, TWA_IOCTL_NO_DATA_BUF)
#define TW_CL_IOCTL_GET_COMPATIBILITY_INFO \
_IOWR('T', 209, TWA_IOCTL_NO_DATA_BUF)
/* WASABI */
#define TWA_IOCTL_GET_UNITNAME _IOWR('T', 220, struct twa_unitname)
#endif /* _DEV_PCI_TWAIO_H_ */

510
sys/dev/pci/twareg.h Normal file
View File

@ -0,0 +1,510 @@
/* $wasabi: twareg.h,v 1.11 2006/04/27 17:12:39 wrstuden Exp $ */
/*
* Copyright (c) 2005-2006 Wasabi Systems, Inc.
* All rights reserved.
*
* Your Wasabi Systems License Agreement specifies the terms and
* conditions for use and redistribution.
*/
/*-
* Copyright (c) 2003-04 3ware, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: src/sys/dev/twa/twa_reg.h,v 1.2 2004/08/18 16:14:44 vkashyap Exp $
*/
/*
* 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
*/
#ifndef _PCI_TWAREG_H_
#define _PCI_TWAREG_H_
#if defined(_KERNEL)
#include <machine/bus.h>
/*
* The following macro has no business being in twa_reg.h. It should probably
* be defined in twa_includes.h, before the #include twa_reg.h.... But that
* causes the API to run into build errors. Will leave it here for now...
*/
#define TWA_64BIT_ADDRESSES ((sizeof(bus_addr_t) == 8) ? 1 : 0)
/*
* Define the following here since it relies on TWA_64BIT_ADDRESSES which
* depends on sizeof(bus_addr_t), which is not exported to userland.
* The userland API shouldn't care about the kernel's bus_addr_t.
* For the userland API, use the array size that we would use for 32-bit
* addresses since that's what we use in the sg structure definition.
* The userland API does not actually appear to use the array, but it
* does include the array in various command structures.
*/
#define TWA_MAX_SG_ELEMENTS (TWA_64BIT_ADDRESSES ? 70 : 105)
#else
#define TWA_MAX_SG_ELEMENTS 105
#endif
#define TWAQ_FREE 0
#define TWAQ_BUSY 1
#define TWAQ_PENDING 2
#define TWAQ_COMPLETE 3
#define TWAQ_IO_PENDING 4
#define TWAQ_COUNT 5 /* total number of queues */
#define TWA_DRIVER_VERSION_STRING "1.00.00.000"
#define TWA_REQUEST_TIMEOUT_PERIOD 60 /* seconds */
#define TWA_MESSAGE_SOURCE_CONTROLLER_ERROR 3
/* Register offsets from base address. */
#define TWA_CONTROL_REGISTER_OFFSET 0x0
#define TWA_STATUS_REGISTER_OFFSET 0x4
#define TWA_COMMAND_QUEUE_OFFSET 0x8
#define TWA_RESPONSE_QUEUE_OFFSET 0xC
#define TWA_COMMAND_QUEUE_OFFSET_LOW 0x20
#define TWA_COMMAND_QUEUE_OFFSET_HIGH 0x24
#if defined(_KERNEL)
#define TWA_WRITE_REGISTER(sc, offset, val) \
bus_space_write_4(sc->twa_bus_iot, sc->twa_bus_ioh, offset, (u_int32_t)val)
#define TWA_WRITE_COMMAND_QUEUE(sc, val) \
do { \
if (TWA_64BIT_ADDRESSES) { \
/* First write the low 4 bytes, then the high 4. */ \
TWA_WRITE_REGISTER(sc, TWA_COMMAND_QUEUE_OFFSET_LOW, \
(u_int32_t)(val)); \
TWA_WRITE_REGISTER(sc, TWA_COMMAND_QUEUE_OFFSET_HIGH,\
(u_int32_t)(((u_int64_t)val)>>32)); \
} else \
TWA_WRITE_REGISTER(sc, TWA_COMMAND_QUEUE_OFFSET,\
(u_int32_t)(val)); \
} while (0)
#endif
/* Control register bit definitions. */
#define TWA_CONTROL_CLEAR_SBUF_WRITE_ERROR 0x00000008
#define TWA_CONTROL_ISSUE_HOST_INTERRUPT 0x00000020
#define TWA_CONTROL_DISABLE_INTERRUPTS 0x00000040
#define TWA_CONTROL_ENABLE_INTERRUPTS 0x00000080
#define TWA_CONTROL_ISSUE_SOFT_RESET 0x00000100
#define TWA_CONTROL_UNMASK_RESPONSE_INTERRUPT 0x00004000
#define TWA_CONTROL_UNMASK_COMMAND_INTERRUPT 0x00008000
#define TWA_CONTROL_MASK_RESPONSE_INTERRUPT 0x00010000
#define TWA_CONTROL_MASK_COMMAND_INTERRUPT 0x00020000
#define TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT 0x00040000
#define TWA_CONTROL_CLEAR_HOST_INTERRUPT 0x00080000
#define TWA_CONTROL_CLEAR_PCI_ABORT 0x00100000
#define TWA_CONTROL_CLEAR_QUEUE_ERROR 0x00400000
#define TWA_CONTROL_CLEAR_PARITY_ERROR 0x00800000
/* Status register bit definitions. */
#define TWA_STATUS_ROM_BIOS_IN_SBUF 0x00000002
#define TWA_STATUS_SBUF_WRITE_ERROR 0x00000008
#define TWA_STATUS_COMMAND_QUEUE_EMPTY 0x00001000
#define TWA_STATUS_MICROCONTROLLER_READY 0x00002000
#define TWA_STATUS_RESPONSE_QUEUE_EMPTY 0x00004000
#define TWA_STATUS_COMMAND_QUEUE_FULL 0x00008000
#define TWA_STATUS_RESPONSE_INTERRUPT 0x00010000
#define TWA_STATUS_COMMAND_INTERRUPT 0x00020000
#define TWA_STATUS_ATTENTION_INTERRUPT 0x00040000
#define TWA_STATUS_HOST_INTERRUPT 0x00080000
#define TWA_STATUS_PCI_ABORT_INTERRUPT 0x00100000
#define TWA_STATUS_MICROCONTROLLER_ERROR 0x00200000
#define TWA_STATUS_QUEUE_ERROR_INTERRUPT 0x00400000
#define TWA_STATUS_PCI_PARITY_ERROR_INTERRUPT 0x00800000
#define TWA_STATUS_MINOR_VERSION_MASK 0x0F000000
#define TWA_STATUS_MAJOR_VERSION_MASK 0xF0000000
#define TWA_STATUS_EXPECTED_BITS 0x00002000
#define TWA_STATUS_UNEXPECTED_BITS 0x00F00000
/* For use with the %b printf format. */
#define TWA_STATUS_BITS_DESCRIPTION \
"\20\15CMD_Q_EMPTY\16MC_RDY\17RESP_Q_EMPTY\20CMD_Q_FULL\21RESP_INTR\22CMD_INTR\23ATTN_INTR\24HOST_INTR\25PCI_ABRT\26MC_ERR\27Q_ERR\30PCI_PERR\n"
/* Detect inconsistencies in the status register. */
#define TWA_STATUS_ERRORS(x) \
((x & TWA_STATUS_UNEXPECTED_BITS) && \
(x & TWA_STATUS_MICROCONTROLLER_READY))
/* PCI related defines. */
#define TWA_IO_CONFIG_REG 0x10
#define TWA_DEVICE_NAME "3ware 9000 series Storage Controller"
#define TWA_VENDOR_ID 0x13C1
#define TWA_DEVICE_ID_9K 0x1002
#define TWA_PCI_CONFIG_CLEAR_PARITY_ERROR 0xc100
#define TWA_PCI_CONFIG_CLEAR_PCI_ABORT 0x2000
/* Command packet opcodes. */
#define TWA_OP_NOP 0x00
#define TWA_OP_INIT_CONNECTION 0x01
#define TWA_OP_READ 0x02
#define TWA_OP_WRITE 0x03
#define TWA_OP_READVERIFY 0x04
#define TWA_OP_VERIFY 0x05
#define TWA_OP_ZEROUNIT 0x08
#define TWA_OP_REPLACEUNIT 0x09
#define TWA_OP_HOTSWAP 0x0A
#define TWA_OP_SELFTESTS 0x0B
#define TWA_OP_SYNC_PARAM 0x0C
#define TWA_OP_REORDER_UNITS 0x0D
#define TWA_OP_FLUSH 0x0E
#define TWA_OP_EXECUTE_SCSI_COMMAND 0x10
#define TWA_OP_ATA_PASSTHROUGH 0x11
#define TWA_OP_GET_PARAM 0x12
#define TWA_OP_SET_PARAM 0x13
#define TWA_OP_CREATEUNIT 0x14
#define TWA_OP_DELETEUNIT 0x15
#define TWA_OP_DOWNLOAD_FIRMWARE 0x16
#define TWA_OP_REBUILDUNIT 0x17
#define TWA_OP_POWER_MANAGEMENT 0x18
#define TWA_OP_REMOTE_PRINT 0x1B
#define TWA_OP_RESET_FIRMWARE 0x1C
#define TWA_OP_DEBUG 0x1D
#define TWA_OP_DIAGNOSTICS 0x1F
/* Misc defines. */
#define TWA_ALIGNMENT 0x4
#define TWA_MAX_UNITS 16
#define TWA_INIT_MESSAGE_CREDITS 0x100
#define TWA_SHUTDOWN_MESSAGE_CREDITS 0x001
#define TWA_64BIT_SG_ADDRESSES 0x00000001
#define TWA_EXTENDED_INIT_CONNECT 0x00000002
#define TWA_BASE_MODE 1
#define TWA_BASE_FW_SRL 24
#define TWA_BASE_FW_BRANCH 0
#define TWA_BASE_FW_BUILD 1
#define TWA_CURRENT_FW_SRL 28
#define TWA_CURRENT_FW_BRANCH 4
#define TWA_CURRENT_FW_BUILD 9
#define TWA_9000_ARCH_ID 0x5 /* 9000 series controllers */
#define TWA_CTLR_FW_SAME_OR_NEWER 0x00000001
#define TWA_CTLR_FW_COMPATIBLE 0x00000002
#define TWA_BUNDLED_FW_SAFE_TO_FLASH 0x00000004
#define TWA_CTLR_FW_RECOMMENDS_FLASH 0x00000008
#define NUM_FW_IMAGE_CHUNKS 5
#define TWA_MAX_IO_SIZE 0x20000 /* 128K */
/* #define TWA_MAX_SG_ELEMENTS defined above */
#define TWA_MAX_ATA_SG_ELEMENTS 60
#define TWA_Q_LENGTH TWA_INIT_MESSAGE_CREDITS
#define TWA_MAX_RESET_TRIES 3
#define TWA_SECTOR_SIZE 0x200 /* generic I/O bufffer */
#define TWA_SENSE_DATA_LENGTH 18
#define TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED 0x010a
#define TWA_ERROR_UNIT_OFFLINE 0x0128
#define TWA_ERROR_MORE_DATA 0x0231
/* Scatter/Gather list entry. */
struct twa_sg {
#if defined(_KERNEL)
bus_addr_t address;
#else
u_int32_t xx_address_xx; /* Fail if userland tries to use this */
#endif
u_int32_t length;
} __attribute__ ((packed));
/* 7000 structures. */
struct twa_command_init_connect {
u_int8_t opcode:5; /* TWA_OP_INITCONNECTION */
u_int8_t res1:3;
u_int8_t size;
u_int8_t request_id;
u_int8_t res2;
u_int8_t status;
u_int8_t flags;
u_int16_t message_credits;
u_int32_t features;
u_int16_t fw_srl;
u_int16_t fw_arch_id;
u_int16_t fw_branch;
u_int16_t fw_build;
u_int32_t result;
}__attribute__ ((packed));
struct twa_command_download_firmware {
u_int8_t opcode:5; /* TWA_DOWNLOAD_FIRMWARE */
u_int8_t sgl_offset:3;
u_int8_t size;
u_int8_t request_id;
u_int8_t unit;
u_int8_t status;
u_int8_t flags;
u_int16_t param;
struct twa_sg sgl[TWA_MAX_SG_ELEMENTS];
} __attribute__ ((packed));
struct twa_command_reset_firmware {
u_int8_t opcode:5; /* TWA_OP_RESET_FIRMWARE */
u_int8_t res1:3;
u_int8_t size;
u_int8_t request_id;
u_int8_t unit;
u_int8_t status;
u_int8_t flags;
u_int8_t res2;
u_int8_t param;
} __attribute__ ((packed));
struct twa_command_io {
u_int8_t opcode:5; /* TWA_OP_READ/TWA_OP_WRITE */
u_int8_t sgl_offset:3;
u_int8_t size;
u_int8_t request_id;
u_int8_t unit:4;
u_int8_t host_id:4;
u_int8_t status;
u_int8_t flags;
u_int16_t block_count;
u_int32_t lba;
struct twa_sg sgl[TWA_MAX_SG_ELEMENTS];
} __attribute__ ((packed));
struct twa_command_hotswap {
u_int8_t opcode:5; /* TWA_OP_HOTSWAP */
u_int8_t res1:3;
u_int8_t size;
u_int8_t request_id;
u_int8_t unit:4;
u_int8_t host_id:4;
u_int8_t status;
u_int8_t flags;
u_int8_t action;
#define TWA_OP_HOTSWAP_REMOVE 0x00 /* remove assumed-degraded unit */
#define TWA_OP_HOTSWAP_ADD_CBOD 0x01 /* add CBOD to empty port */
#define TWA_OP_HOTSWAP_ADD_SPARE 0x02 /* add spare to empty port */
u_int8_t aport;
} __attribute__ ((packed));
struct twa_command_param {
u_int8_t opcode:5; /* TWA_OP_GETPARAM, TWA_OP_SETPARAM */
u_int8_t sgl_offset:3;
u_int8_t size;
u_int8_t request_id;
u_int8_t unit:4;
u_int8_t host_id:4;
u_int8_t status;
u_int8_t flags;
u_int16_t param_count;
struct twa_sg sgl[TWA_MAX_SG_ELEMENTS];
} __attribute__ ((packed));
struct twa_command_rebuildunit {
u_int8_t opcode:5; /* TWA_OP_REBUILDUNIT */
u_int8_t res1:3;
u_int8_t size;
u_int8_t request_id;
u_int8_t src_unit:4;
u_int8_t host_id:4;
u_int8_t status;
u_int8_t flags;
u_int8_t action:7;
#define TWA_OP_REBUILDUNIT_NOP 0
#define TWA_OP_REBUILDUNIT_STOP 2 /* stop all rebuilds */
#define TWA_OP_REBUILDUNIT_START 4 /* start rebuild with lowest unit */
#define TWA_OP_REBUILDUNIT_STARTUNIT 5 /* rebuild src_unit (not supported) */
u_int8_t cs:1; /* request state change on src_unit */
u_int8_t logical_subunit; /* for RAID10 rebuild of logical subunit */
} __attribute__ ((packed));
struct twa_command_ata {
u_int8_t opcode:5; /* TWA_OP_ATA_PASSTHROUGH */
u_int8_t sgl_offset:3;
u_int8_t size;
u_int8_t request_id;
u_int8_t unit:4;
u_int8_t host_id:4;
u_int8_t status;
u_int8_t flags;
u_int16_t param;
u_int16_t features;
u_int16_t sector_count;
u_int16_t sector_num;
u_int16_t cylinder_lo;
u_int16_t cylinder_hi;
u_int8_t drive_head;
u_int8_t command;
struct twa_sg sgl[TWA_MAX_ATA_SG_ELEMENTS];
} __attribute__ ((packed));
struct twa_command_generic {
u_int8_t opcode:5;
u_int8_t sgl_offset:3;
u_int8_t size;
u_int8_t request_id;
u_int8_t unit:4;
u_int8_t host_id:4;
u_int8_t status;
u_int8_t flags;
#define TWA_FLAGS_SUCCESS 0x00
#define TWA_FLAGS_INFORMATIONAL 0x01
#define TWA_FLAGS_WARNING 0x02
#define TWA_FLAGS_FATAL 0x03
#define TWA_FLAGS_PERCENTAGE (1<<8) /* bits 0-6 indicate completion percentage */
u_int16_t count; /* block count, parameter count, message credits */
} __attribute__ ((packed));
/* Command packet - must be TWA_ALIGNMENT aligned. */
union twa_command_7k {
struct twa_command_init_connect init_connect;
struct twa_command_download_firmware download_fw;
struct twa_command_reset_firmware reset_fw;
struct twa_command_io io;
struct twa_command_hotswap hotswap;
struct twa_command_param param;
struct twa_command_rebuildunit rebuildunit;
struct twa_command_ata ata;
struct twa_command_generic generic;
} __attribute__ ((packed));
/* 9000 structures. */
/* Command Packet. */
struct twa_command_9k {
struct {
u_int8_t opcode:5;
u_int8_t reserved:3;
} command;
u_int8_t unit;
u_int16_t request_id;
u_int8_t status;
u_int8_t sgl_offset; /* offset (in bytes) to sg_list, from the end of sgl_entries */
u_int16_t sgl_entries;
u_int8_t cdb[16];
struct twa_sg sg_list[TWA_MAX_SG_ELEMENTS];
u_int8_t padding[32];
} __attribute__ ((packed));
/* Command packet header. */
struct twa_command_header {
u_int8_t sense_data[TWA_SENSE_DATA_LENGTH];
struct {
int8_t reserved[4];
u_int16_t error;
u_int8_t padding;
struct {
u_int8_t severity:3;
u_int8_t reserved:5;
} substatus_block;
} status_block;
u_int8_t err_specific_desc[98];
struct {
u_int8_t size_header;
u_int16_t reserved;
u_int8_t size_sense;
} header_desc;
u_int8_t reserved[2];
} __attribute__ ((packed));
/* Full command packet. */
struct twa_command_packet {
struct twa_command_header cmd_hdr;
union {
union twa_command_7k cmd_pkt_7k;
struct twa_command_9k cmd_pkt_9k;
} command;
} __attribute__ ((packed));
/* Response queue entry. */
union twa_response_queue {
struct {
u_int32_t undefined_1:4;
u_int32_t response_id:8;
u_int32_t undefined_2:20;
} u;
u_int32_t value;
} __attribute__ ((packed));
#define TWA_AEN_QUEUE_EMPTY 0x00
#define TWA_AEN_SOFT_RESET 0x01
#define TWA_AEN_SYNC_TIME_WITH_HOST 0x31
#define TWA_AEN_SEVERITY_ERROR 0x1
#define TWA_AEN_SEVERITY_WARNING 0x1
#define TWA_AEN_SEVERITY_INFO 0x1
#define TWA_AEN_SEVERITY_DEBUG 0x4
#define TWA_PARAM_DRIVESUMMARY 0x0002
#define TWA_PARAM_DRIVESTATUS 3
#define TWA_DRIVE_DETECTED 0x80
#define TWA_PARAM_DRIVE_TABLE 0x0200
#define TWA_PARAM_DRIVESIZEINDEX 2
#define TWA_PARAM_DRIVEMODELINDEX 3
#define TWA_PARAM_DRIVESIZE_LENGTH 4
#define TWA_PARAM_DRIVEMODEL_LENGTH 40
#define TWA_PARAM_VERSION 0x0402
#define TWA_PARAM_VERSION_Mon 2 /* monitor version [16] */
#define TWA_PARAM_VERSION_FW 3 /* firmware version [16] */
#define TWA_PARAM_VERSION_BIOS 4 /* BIOSs version [16] */
#define TWA_PARAM_VERSION_PCBA 5 /* PCB version [8] */
#define TWA_PARAM_VERSION_ATA 6 /* A-chip version [8] */
#define TWA_PARAM_VERSION_PCI 7 /* P-chip version [8] */
#define TWA_PARAM_CONTROLLER 0x0403
#define TWA_PARAM_CONTROLLER_PortCount 3 /* number of ports [1] */
#define TWA_PARAM_TIME_TABLE 0x40A
#define TWA_PARAM_TIME_SchedulerTime 0x3
#define TWA_9K_PARAM_DESCRIPTOR 0x8000
struct twa_param_9k {
u_int16_t table_id;
u_int8_t parameter_id;
u_int8_t reserved;
u_int16_t parameter_size_bytes;
u_int16_t parameter_actual_size_bytes;
u_int8_t data[1];
} __attribute__ ((packed));
#endif /* !_PCI_TWAREG_H_ */

228
sys/dev/pci/twavar.h Normal file
View File

@ -0,0 +1,228 @@
/* $wasabi: twavar.h,v 1.11 2006/04/27 17:12:39 wrstuden Exp $ */
/*
* Copyright (c) 2005-2006 Wasabi Systems, Inc.
* All rights reserved.
*
* Your Wasabi Systems License Agreement specifies the terms and
* conditions for use and redistribution.
*/
/*-
* Copyright (c) 2003-04 3ware, Inc.
* 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: src/sys/dev/twa/twa.h,v 1.4 2004/06/16 09:47:00 phk Exp $
*/
/*
* 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
*/
#ifndef _PCI_TWAVAR_H_
#define _PCI_TWAVAR_H_
#include "locators.h"
struct twa_callbacks {
void (*tcb_openings)(struct device *, int);
};
struct twa_drive {
uint32_t td_id;
uint64_t td_size;
struct device *td_dev;
const struct twa_callbacks *td_callbacks;
};
/* Per-controller structure. */
struct twa_softc {
struct device twa_dv;
bus_space_tag_t twa_bus_iot; /* bus space tag */
bus_space_handle_t twa_bus_ioh; /* bus space handle */
bus_dma_tag_t twa_dma_tag; /* data buffer DMA tag */
bus_dmamap_t twa_cmd_map; /* DMA map for the array of cmd pkts */
void *twa_ih; /* interrupt handle cookie */
caddr_t twa_cmds;
bus_addr_t twa_cmd_pkt_phys;/* phys addr of first of array of cmd pkts */
pci_chipset_tag_t pc;
pcitag_t tag;
/* Request queues and arrays. */
TAILQ_HEAD(, twa_request) twa_free; /* free request packets */
TAILQ_HEAD(, twa_request) twa_busy; /* requests busy in the controller */
TAILQ_HEAD(, twa_request) twa_pending; /* internal requests pending */
struct twa_request *twa_lookup[TWA_Q_LENGTH];/* requests indexed by request_id */
struct twa_request *twa_req_buf;
struct twa_command_packet *twa_cmd_pkt_buf;
struct twa_drive sc_units[TWA_MAX_UNITS];
/* AEN handler fields. */
struct tw_cl_event_packet *twa_aen_queue[TWA_Q_LENGTH];/* circular queue of AENs from firmware */
uint16_t working_srl; /* driver & firmware negotiated srl */
uint16_t working_branch; /* branch # of the firmware that the driver is compatible with */
uint16_t working_build; /* build # of the firmware that the driver is compatible with */
u_int32_t twa_operating_mode; /* base mode/current mode */
u_int32_t twa_aen_head; /* AEN queue head */
u_int32_t twa_aen_tail; /* AEN queue tail */
u_int32_t twa_current_sequence_id;/* index of the last event + 1 */
u_int32_t twa_aen_queue_overflow; /* indicates if unretrieved events were overwritten */
u_int32_t twa_aen_queue_wrapped; /* indicates if AEN queue ever wrapped */
/* Controller state. */
u_int32_t twa_state;
u_int32_t twa_sc_flags;
#ifdef TWA_DEBUG
struct twa_q_statistics twa_qstats[TWAQ_COUNT]; /* queue statistics */
#endif /* TWA_DEBUG */
struct _twa_ioctl_lock{
u_int32_t lock; /* lock state */
u_int32_t timeout; /* time at which the lock
* will become available,
* even if not released
*/
} twa_ioctl_lock; /* lock for use by user
* applications,
* for synchronization between
* ioctl calls
*/
int sc_openings;
int sc_nunits;
struct twa_request *sc_twa_request;
};
/* Possible values of tr->tr_status. */
#define TWA_CMD_SETUP 0x0 /* being assembled */
#define TWA_CMD_BUSY 0x1 /* submitted to controller */
#define TWA_CMD_PENDING 0x2 /* in pending queue */
#define TWA_CMD_COMPLETE 0x3 /* completed by controller */
/* Possible values of tr->tr_flags. */
#define TWA_CMD_DATA_IN (1 << 0)
#define TWA_CMD_DATA_OUT (1 << 1)
#define TWA_CMD_DATA_COPY_NEEDED (1 << 2)
#define TWA_CMD_SLEEP_ON_REQUEST (1 << 3)
#define TWA_CMD_IN_PROGRESS (1 << 4)
#define TWA_CMD_AEN (1 << 5)
#define TWA_CMD_AEN_BUSY (1 << 6)
/* Possible values of tr->tr_cmd_pkt_type. */
#define TWA_CMD_PKT_TYPE_7K (1<<0)
#define TWA_CMD_PKT_TYPE_9K (1<<1)
#define TWA_CMD_PKT_TYPE_INTERNAL (1<<2)
#define TWA_CMD_PKT_TYPE_IOCTL (1<<3)
#define TWA_CMD_PKT_TYPE_EXTERNAL (1<<4)
/* Possible values of sc->twa_state. */
#define TWA_STATE_INTR_ENABLED (1<<0) /* interrupts have been enabled */
#define TWA_STATE_SHUTDOWN (1<<1) /* controller is shut down */
#define TWA_STATE_OPEN (1<<2) /* control device is open */
#define TWA_STATE_SIMQ_FROZEN (1<<3) /* simq frozen */
#define TWA_STATE_REQUEST_WAIT (1<<4)
/* Possible values of sc->twa_ioctl_lock.lock. */
#define TWA_LOCK_FREE 0x0 /* lock is free */
#define TWA_LOCK_HELD 0x1 /* lock is held */
/* Driver's request packet. */
struct twa_request {
struct twa_command_packet *tr_command;
/* ptr to cmd pkt submitted to controller */
u_int32_t tr_request_id;
/* request id for tracking with firmware */
void *tr_data;
/* ptr to data being passed to firmware */
size_t tr_length;
/* length of buffer being passed to firmware */
void *tr_real_data;
/* ptr to, and length of data passed */
size_t tr_real_length;
/* to us from above, in case a buffer copy
* was done due to non-compliance to
* alignment requirements
*/
TAILQ_ENTRY(twa_request) tr_link;
/* to link this request in a list */
struct twa_softc *tr_sc;
/* controller that owns us */
u_int32_t tr_status;
/* command status */
u_int32_t tr_flags;
/* request flags */
u_int32_t tr_error;
/* error encountered before request submission */
u_int32_t tr_cmd_pkt_type;
/* request specific data to use during callback */
void (*tr_callback)(struct twa_request *tr);
/* callback handler */
bus_addr_t tr_cmd_phys;
/* physical address of command in controller space */
bus_dmamap_t tr_dma_map;
/* DMA map for data */
struct buf *bp;
struct ld_twa_softc *tr_ld_sc;
};
static __inline__ size_t twa_get_maxsegs(void) {
size_t max_segs = ((MAXPHYS + PAGE_SIZE - 1) / PAGE_SIZE) + 1;
#ifdef TWA_SG_SIZE
if (TWA_MAX_SG_ELEMENTS < max_segs)
max_segs = TWA_MAX_SG_ELEMENTS;
#endif
return max_segs;
}
static __inline__ size_t twa_get_maxxfer(size_t maxsegs) {
return (maxsegs - 1) * PAGE_SIZE;
}
struct twa_attach_args {
int twaa_unit;
};
#define twaacf_unit cf_loc[TWACF_UNIT]
struct twa_request *twa_get_request(struct twa_softc *, int);
struct twa_request *twa_get_request_wait(struct twa_softc *, int);
int twa_map_request(struct twa_request *);
void twa_register_callbacks(struct twa_softc *sc, int unit,
const struct twa_callbacks *);
void twa_request_wait_handler(struct twa_request *);
void twa_release_request(struct twa_request *);
/* Error/AEN message structure. */
struct twa_message {
u_int32_t code;
const char *message;
};
#endif /* !_PCI_TWAVAR_H_ */