twa: Remove

Belatedly remove twa(4). It was supposed to go before 13.0, but was
overlooked.

Sponsored by:		Netflix
Relnotes:		yes
Reviewed by:		scottl
Differential Revision:	https://reviews.freebsd.org/D33114
This commit is contained in:
Warner Losh 2021-11-25 00:21:41 -07:00
parent 0d5935af8f
commit 8722e05ae1
29 changed files with 0 additions and 8999 deletions

View file

@ -552,7 +552,6 @@ MAN= aac.4 \
${_tpm.4} \
tty.4 \
tun.4 \
twa.4 \
twe.4 \
tws.4 \
udp.4 \

View file

@ -1,140 +0,0 @@
.\"
.\" Copyright (c) 2004 3ware, Inc.
.\" 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 ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd May 9, 2007
.Dt TWA 4
.Os
.Sh NAME
.Nm twa
.Nd 3ware 9000/9500/9550/9650 series SATA RAID controllers driver
.Sh DEPRECATION NOTICE
The
.Nm
driver is not present in
.Fx 13.0 .
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device scbus"
.Cd "device twa"
.Ed
.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
twa_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
driver provides support for AMCC's 3ware 9000/9500/9550/9650 series
SATA controllers.
.Pp
These controllers are available in 4, 8, 12 or 16-port configurations,
and support the following RAID levels: 0, 1, 10, 5, 50.
The device nodes for the controllers are of the form
.Pa /dev/twa Ns Ar X ,
where
.Ar X
is the controller number.
The driver is implemented as a SCSI SIM
under CAM, and, as such, the logical units that it controls are accessible
via the device nodes,
.Pa /dev/da Ns Ar Y ,
where
.Ar Y
is the logical unit number.
.Sh HARDWARE
The
.Nm
driver supports the following SATA RAID controllers:
.Pp
.Bl -bullet -compact
.It
AMCC's 3ware 9500S-4LP
.It
AMCC's 3ware 9500S-8
.It
AMCC's 3ware 9500S-8MI
.It
AMCC's 3ware 9500S-12
.It
AMCC's 3ware 9500S-12MI
.It
AMCC's 3ware 9500SX-4LP
.It
AMCC's 3ware 9500SX-8LP
.It
AMCC's 3ware 9500SX-12
.It
AMCC's 3ware 9500SX-12MI
.It
AMCC's 3ware 9500SX-16ML
.It
AMCC's 3ware 9550SX-4LP
.It
AMCC's 3ware 9550SX-8LP
.It
AMCC's 3ware 9550SX-12
.It
AMCC's 3ware 9550SX-12MI
.It
AMCC's 3ware 9550SX-16ML
.It
AMCC's 3ware 9650SE-2LP
.It
AMCC's 3ware 9650SE-4LPML
.It
AMCC's 3ware 9650SE-8LPML
.It
AMCC's 3ware 9650SE-12ML
.It
AMCC's 3ware 9650SE-16ML
.It
AMCC's 3ware 9650SE-24M8
.El
.Sh DIAGNOSTICS
Whenever the driver encounters a command failure, it prints out an error code in
the format:
.Qq Li "ERROR: (<error source>: <error code>):" ,
followed by a text description of the error.
There are other error messages and warnings that the
driver prints out, depending on the kinds of errors that it encounters.
If the driver is compiled with
.Dv TWA_DEBUG
defined, it prints out a whole bunch of debug
messages, the quantity of which varies depending on the value assigned to
.Dv TWA_DEBUG
(0 to 10).
.Sh AUTHORS
The
.Nm
driver and manpage were written by
.An Vinod Kashyap Aq Mt vkashyap@FreeBSD.org .

View file

@ -182,7 +182,6 @@ device ses # Enclosure Services (SES and SAF-TE)
device arcmsr # Areca SATA II RAID
device ciss # Compaq Smart RAID 5*
device ips # IBM (Adaptec) ServeRAID
device twa # 3ware 9000 series PATA/SATA RAID
device smartpqi # Microsemi smartpqi driver
device tws # LSI 3ware 9750 SATA+SAS 6Gb/s RAID controller

View file

@ -406,13 +406,6 @@ device arcmsr # Areca SATA II RAID
#
device smartpqi
#
# 3ware 9000 series PATA/SATA RAID controller driver and options.
# The driver is implemented as a SIM, and so, needs the CAM infrastructure.
#
options TWA_DEBUG # 0-10; 10 prints the most messages.
device twa # 3ware 9000 series PATA/SATA RAID
#
# Adaptec FSA RAID controllers, including integrated DELL controllers,
# the Dell PERC 2/QC and the HP NetRAID-4M

View file

@ -3205,18 +3205,6 @@ dev/syscons/warp/warp_saver.c optional warp_saver
dev/tcp_log/tcp_log_dev.c optional tcp_blackbox inet | tcp_blackbox inet6
dev/tdfx/tdfx_pci.c optional tdfx pci
dev/ti/if_ti.c optional ti pci
dev/twa/tw_cl_init.c optional twa \
compile-with "${NORMAL_C} -I$S/dev/twa"
dev/twa/tw_cl_intr.c optional twa \
compile-with "${NORMAL_C} -I$S/dev/twa"
dev/twa/tw_cl_io.c optional twa \
compile-with "${NORMAL_C} -I$S/dev/twa"
dev/twa/tw_cl_misc.c optional twa \
compile-with "${NORMAL_C} -I$S/dev/twa"
dev/twa/tw_osl_cam.c optional twa \
compile-with "${NORMAL_C} -I$S/dev/twa"
dev/twa/tw_osl_freebsd.c optional twa \
compile-with "${NORMAL_C} -I$S/dev/twa"
dev/twe/twe.c optional twe
dev/twe/twe_freebsd.c optional twe
dev/tws/tws.c optional tws

View file

@ -43,8 +43,6 @@ AHD_DEBUG_OPTS opt_aic79xx.h
AHD_TMODE_ENABLE opt_aic79xx.h
AHD_REG_PRETTY_PRINT opt_aic79xx.h
TWA_DEBUG opt_twa.h
# Debugging options.
ALT_BREAK_TO_DEBUGGER opt_kdb.h
BREAK_TO_DEBUGGER opt_kdb.h

View file

@ -1,324 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
*/
#ifndef TW_CL_H
#define TW_CL_H
/*
* Common Layer internal macros, structures and functions.
*/
#define TW_CLI_SECTOR_SIZE 0x200
#define TW_CLI_REQUEST_TIMEOUT_PERIOD 60 /* seconds */
#define TW_CLI_RESET_TIMEOUT_PERIOD 60 /* seconds */
#define TW_CLI_MAX_RESET_ATTEMPTS 2
/* Possible values of ctlr->ioctl_lock.lock. */
#define TW_CLI_LOCK_FREE 0x0 /* lock is free */
#define TW_CLI_LOCK_HELD 0x1 /* lock is held */
/* Possible values of req->state. */
#define TW_CLI_REQ_STATE_INIT 0x0 /* being initialized */
#define TW_CLI_REQ_STATE_BUSY 0x1 /* submitted to controller */
#define TW_CLI_REQ_STATE_PENDING 0x2 /* in pending queue */
#define TW_CLI_REQ_STATE_COMPLETE 0x3 /* completed by controller */
/* Possible values of req->flags. */
#define TW_CLI_REQ_FLAGS_7K (1<<0) /* 7000 cmd pkt */
#define TW_CLI_REQ_FLAGS_9K (1<<1) /* 9000 cmd pkt */
#define TW_CLI_REQ_FLAGS_INTERNAL (1<<2) /* internal request */
#define TW_CLI_REQ_FLAGS_PASSTHRU (1<<3) /* passthru request */
#define TW_CLI_REQ_FLAGS_EXTERNAL (1<<4) /* external request */
#ifdef TW_OSL_PCI_CONFIG_ACCESSIBLE
/* Register offsets in PCI config space. */
#define TW_CLI_PCI_CONFIG_COMMAND_OFFSET 0x4 /* cmd register offset */
#define TW_CLI_PCI_CONFIG_STATUS_OFFSET 0x6 /* status register offset */
#endif /* TW_OSL_PCI_CONFIG_ACCESSIBLE */
#ifdef TW_OSL_DEBUG
struct tw_cli_q_stats {
TW_UINT32 cur_len;/* current # of entries in q */
TW_UINT32 max_len; /* max # of entries in q, ever reached */
};
#endif /* TW_OSL_DEBUG */
/* Queues of CL internal request context packets. */
#define TW_CLI_FREE_Q 0 /* free q */
#define TW_CLI_BUSY_Q 1 /* q of reqs submitted to fw */
#define TW_CLI_PENDING_Q 2 /* q of reqs deferred due to 'q full' */
#define TW_CLI_COMPLETE_Q 3 /* q of reqs completed by fw */
#define TW_CLI_RESET_Q 4 /* q of reqs reset by timeout */
#define TW_CLI_Q_COUNT 5 /* total number of queues */
/* CL's internal request context. */
struct tw_cli_req_context {
struct tw_cl_req_handle *req_handle;/* handle to track requests between
OSL & CL */
struct tw_cli_ctlr_context *ctlr; /* ptr to CL's controller context */
struct tw_cl_command_packet *cmd_pkt;/* ptr to ctlr cmd pkt */
TW_UINT64 cmd_pkt_phys; /* cmd pkt physical address */
TW_VOID *data; /* ptr to data being passed to fw */
TW_UINT32 length; /* length of data being passed to fw */
TW_UINT64 data_phys; /* physical address of data */
TW_UINT32 state; /* request state */
TW_UINT32 flags; /* request flags */
TW_UINT32 error_code; /* error encountered before submission
of request to fw, if any */
TW_VOID *orig_req; /* ptr to original request for use
during callback */
TW_VOID (*tw_cli_callback)(struct tw_cli_req_context *req);
/* CL internal callback */
TW_UINT32 request_id; /* request id for tracking with fw */
struct tw_cl_link link; /* to link this request in a list */
};
/* CL's internal controller context. */
struct tw_cli_ctlr_context {
struct tw_cl_ctlr_handle *ctlr_handle; /* handle to track ctlr between
OSL & CL. */
struct tw_cli_req_context *req_ctxt_buf;/* pointer to the array of CL's
internal request context pkts */
struct tw_cl_command_packet *cmd_pkt_buf;/* ptr to array of cmd pkts */
TW_UINT64 cmd_pkt_phys; /* phys addr of cmd_pkt_buf */
TW_UINT32 device_id; /* controller device id */
TW_UINT32 arch_id; /* controller architecture id */
TW_UINT8 active; /* Initialization done, and controller is active. */
TW_UINT8 interrupts_enabled; /* Interrupts on controller enabled. */
TW_UINT8 internal_req_busy; /* Data buffer for internal requests in use. */
TW_UINT8 get_more_aens; /* More AEN's need to be retrieved. */
TW_UINT8 reset_needed; /* Controller needs a soft reset. */
TW_UINT8 reset_in_progress; /* Controller is being reset. */
TW_UINT8 reset_phase1_in_progress; /* In 'phase 1' of reset. */
TW_UINT32 flags; /* controller settings */
TW_UINT32 sg_size_factor; /* SG element size should be a
multiple of this */
/* Request queues and arrays. */
struct tw_cl_link req_q_head[TW_CLI_Q_COUNT];
TW_UINT8 *internal_req_data;/* internal req data buf */
TW_UINT64 internal_req_data_phys;/* phys addr of internal
req data buf */
TW_UINT32 max_simult_reqs; /* max simultaneous requests
supported */
TW_UINT32 max_aens_supported;/* max AEN's supported */
/* AEN handler fields. */
struct tw_cl_event_packet *aen_queue; /* circular queue of AENs from
firmware/CL/OSL */
TW_UINT32 aen_head; /* AEN queue head */
TW_UINT32 aen_tail; /* AEN queue tail */
TW_UINT32 aen_cur_seq_id; /* index of the last event+1 */
TW_UINT32 aen_q_overflow; /* indicates if unretrieved
events were overwritten */
TW_UINT32 aen_q_wrapped; /* indicates if AEN queue ever
wrapped */
TW_UINT16 working_srl; /* driver & firmware negotiated
srl */
TW_UINT16 working_branch; /* branch # of the firmware
that the driver is compatible with */
TW_UINT16 working_build; /* build # of the firmware
that the driver is compatible with */
TW_UINT16 fw_on_ctlr_srl; /* srl of running firmware */
TW_UINT16 fw_on_ctlr_branch;/* branch # of running
firmware */
TW_UINT16 fw_on_ctlr_build;/* build # of running
firmware */
TW_UINT32 operating_mode; /* base mode/current mode */
TW_INT32 host_intr_pending;/* host intr processing
needed */
TW_INT32 attn_intr_pending;/* attn intr processing
needed */
TW_INT32 cmd_intr_pending;/* cmd intr processing
needed */
TW_INT32 resp_intr_pending;/* resp intr processing
needed */
TW_LOCK_HANDLE gen_lock_handle;/* general purpose lock */
TW_LOCK_HANDLE *gen_lock;/* ptr to general purpose lock */
TW_LOCK_HANDLE io_lock_handle; /* lock held during cmd
submission */
TW_LOCK_HANDLE *io_lock;/* ptr to lock held during cmd
submission */
#ifdef TW_OSL_CAN_SLEEP
TW_SLEEP_HANDLE sleep_handle; /* handle to co-ordinate sleeps
& wakeups */
#endif /* TW_OSL_CAN_SLEEP */
struct {
TW_UINT32 lock; /* lock state */
TW_TIME timeout; /* time at which the lock will
become available, even if not
explicitly released */
} ioctl_lock; /* lock for use by user applications, for
synchronization between ioctl calls */
#ifdef TW_OSL_DEBUG
struct tw_cli_q_stats q_stats[TW_CLI_Q_COUNT];/* queue statistics */
#endif /* TW_OSL_DEBUG */
};
/*
* Queue primitives
*/
#ifdef TW_OSL_DEBUG
#define TW_CLI_Q_INIT(ctlr, q_type) do { \
(ctlr)->q_stats[q_type].cur_len = 0; \
(ctlr)->q_stats[q_type].max_len = 0; \
} while (0)
#define TW_CLI_Q_INSERT(ctlr, q_type) do { \
struct tw_cli_q_stats *q_stats = &((ctlr)->q_stats[q_type]); \
\
if (++(q_stats->cur_len) > q_stats->max_len) \
q_stats->max_len = q_stats->cur_len; \
} while (0)
#define TW_CLI_Q_REMOVE(ctlr, q_type) \
(ctlr)->q_stats[q_type].cur_len--
#else /* TW_OSL_DEBUG */
#define TW_CLI_Q_INIT(ctlr, q_index)
#define TW_CLI_Q_INSERT(ctlr, q_index)
#define TW_CLI_Q_REMOVE(ctlr, q_index)
#endif /* TW_OSL_DEBUG */
/* Initialize a queue of requests. */
static __inline TW_VOID
tw_cli_req_q_init(struct tw_cli_ctlr_context *ctlr, TW_UINT8 q_type)
{
TW_CL_Q_INIT(&(ctlr->req_q_head[q_type]));
TW_CLI_Q_INIT(ctlr, q_type);
}
/* Insert the given request at the head of the given queue (q_type). */
static __inline TW_VOID
tw_cli_req_q_insert_head(struct tw_cli_req_context *req, TW_UINT8 q_type)
{
struct tw_cli_ctlr_context *ctlr = req->ctlr;
tw_osl_get_lock(ctlr->ctlr_handle, ctlr->gen_lock);
TW_CL_Q_INSERT_HEAD(&(ctlr->req_q_head[q_type]), &(req->link));
TW_CLI_Q_INSERT(ctlr, q_type);
tw_osl_free_lock(ctlr->ctlr_handle, ctlr->gen_lock);
}
/* Insert the given request at the tail of the given queue (q_type). */
static __inline TW_VOID
tw_cli_req_q_insert_tail(struct tw_cli_req_context *req, TW_UINT8 q_type)
{
struct tw_cli_ctlr_context *ctlr = req->ctlr;
tw_osl_get_lock(ctlr->ctlr_handle, ctlr->gen_lock);
TW_CL_Q_INSERT_TAIL(&(ctlr->req_q_head[q_type]), &(req->link));
TW_CLI_Q_INSERT(ctlr, q_type);
tw_osl_free_lock(ctlr->ctlr_handle, ctlr->gen_lock);
}
/* Remove and return the request at the head of the given queue (q_type). */
static __inline struct tw_cli_req_context *
tw_cli_req_q_remove_head(struct tw_cli_ctlr_context *ctlr, TW_UINT8 q_type)
{
struct tw_cli_req_context *req = TW_CL_NULL;
struct tw_cl_link *link;
tw_osl_get_lock(ctlr->ctlr_handle, ctlr->gen_lock);
if ((link = TW_CL_Q_FIRST_ITEM(&(ctlr->req_q_head[q_type]))) !=
TW_CL_NULL) {
req = TW_CL_STRUCT_HEAD(link,
struct tw_cli_req_context, link);
TW_CL_Q_REMOVE_ITEM(&(ctlr->req_q_head[q_type]), &(req->link));
TW_CLI_Q_REMOVE(ctlr, q_type);
}
tw_osl_free_lock(ctlr->ctlr_handle, ctlr->gen_lock);
return(req);
}
/* Remove the given request from the given queue (q_type). */
static __inline TW_VOID
tw_cli_req_q_remove_item(struct tw_cli_req_context *req, TW_UINT8 q_type)
{
struct tw_cli_ctlr_context *ctlr = req->ctlr;
tw_osl_get_lock(ctlr->ctlr_handle, ctlr->gen_lock);
TW_CL_Q_REMOVE_ITEM(&(ctlr->req_q_head[q_type]), &(req->link));
TW_CLI_Q_REMOVE(ctlr, q_type);
tw_osl_free_lock(ctlr->ctlr_handle, ctlr->gen_lock);
}
/* Create an event packet for an event/error posted by the controller. */
#define tw_cli_create_ctlr_event(ctlr, event_src, cmd_hdr) do { \
TW_UINT8 severity = \
GET_SEVERITY((cmd_hdr)->status_block.res__severity); \
\
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_TRUE, event_src, \
(cmd_hdr)->status_block.error, \
severity, \
tw_cli_severity_string_table[severity], \
(cmd_hdr)->err_specific_desc + \
tw_osl_strlen((cmd_hdr)->err_specific_desc) + 1, \
(cmd_hdr)->err_specific_desc); \
/* Print 18 bytes of sense information. */ \
tw_cli_dbg_printf(2, ctlr->ctlr_handle, \
tw_osl_cur_func(), \
"sense info: %x %x %x %x %x %x %x %x %x " \
"%x %x %x %x %x %x %x %x %x", \
(cmd_hdr)->sense_data[0], (cmd_hdr)->sense_data[1], \
(cmd_hdr)->sense_data[2], (cmd_hdr)->sense_data[3], \
(cmd_hdr)->sense_data[4], (cmd_hdr)->sense_data[5], \
(cmd_hdr)->sense_data[6], (cmd_hdr)->sense_data[7], \
(cmd_hdr)->sense_data[8], (cmd_hdr)->sense_data[9], \
(cmd_hdr)->sense_data[10], (cmd_hdr)->sense_data[11], \
(cmd_hdr)->sense_data[12], (cmd_hdr)->sense_data[13], \
(cmd_hdr)->sense_data[14], (cmd_hdr)->sense_data[15], \
(cmd_hdr)->sense_data[16], (cmd_hdr)->sense_data[17]); \
} while (0)
#endif /* TW_CL_H */

View file

@ -1,191 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
*/
#ifndef TW_CL_EXTERNS_H
#define TW_CL_EXTERNS_H
/*
* Data structures and functions global to the Common Layer.
*/
extern TW_INT8 tw_cli_fw_img[];
extern TW_INT32 tw_cli_fw_img_size;
extern TW_INT8 *tw_cli_severity_string_table[];
/* Do controller initialization. */
extern TW_INT32 tw_cli_start_ctlr(struct tw_cli_ctlr_context *ctlr);
/* Establish a logical connection with the firmware on the controller. */
extern TW_INT32 tw_cli_init_connection(struct tw_cli_ctlr_context *ctlr,
TW_UINT16 message_credits, TW_UINT32 set_features,
TW_UINT16 current_fw_srl, TW_UINT16 current_fw_arch_id,
TW_UINT16 current_fw_branch, TW_UINT16 current_fw_build,
TW_UINT16 *fw_on_ctlr_srl, TW_UINT16 *fw_on_ctlr_arch_id,
TW_UINT16 *fw_on_ctlr_branch, TW_UINT16 *fw_on_ctlr_build,
TW_UINT32 *init_connect_result);
/* Functions in tw_cl_io.c */
/* Submit a command packet to the firmware on the controller. */
extern TW_INT32 tw_cli_submit_cmd(struct tw_cli_req_context *req);
/* Get a firmware parameter. */
extern TW_INT32 tw_cli_get_param(struct tw_cli_ctlr_context *ctlr,
TW_INT32 table_id, TW_INT32 parameter_id, TW_VOID *param_data,
TW_INT32 size, TW_VOID (* callback)(struct tw_cli_req_context *req));
/* Set a firmware parameter. */
extern TW_INT32 tw_cli_set_param(struct tw_cli_ctlr_context *ctlr,
TW_INT32 table_id, TW_INT32 param_id, TW_INT32 param_size,
TW_VOID *data, TW_VOID (* callback)(struct tw_cli_req_context *req));
/* Submit a command to the firmware and poll for completion. */
extern TW_INT32 tw_cli_submit_and_poll_request(struct tw_cli_req_context *req,
TW_UINT32 timeout);
/* Soft reset the controller. */
extern TW_INT32 tw_cli_soft_reset(struct tw_cli_ctlr_context *ctlr);
extern int twa_setup_intr(struct twa_softc *sc);
extern int twa_teardown_intr(struct twa_softc *sc);
/* Send down a SCSI command to the firmware (usually, an internal Req Sense. */
extern TW_INT32 tw_cli_send_scsi_cmd(struct tw_cli_req_context *req,
TW_INT32 cmd);
/* Get an AEN from the firmware (by sending down a Req Sense). */
extern TW_INT32 tw_cli_get_aen(struct tw_cli_ctlr_context *ctlr);
/* Fill in the scatter/gather list. */
extern TW_VOID tw_cli_fill_sg_list(struct tw_cli_ctlr_context *ctlr,
TW_VOID *sgl_src, TW_VOID *sgl_dest, TW_INT32 num_sgl_entries);
/* Functions in tw_cl_intr.c */
/* Process a host interrupt. */
extern TW_VOID tw_cli_process_host_intr(struct tw_cli_ctlr_context *ctlr);
/* Process an attention interrupt. */
extern TW_VOID tw_cli_process_attn_intr(struct tw_cli_ctlr_context *ctlr);
/* Process a command interrupt. */
extern TW_VOID tw_cli_process_cmd_intr(struct tw_cli_ctlr_context *ctlr);
/* Process a response interrupt from the controller. */
extern TW_INT32 tw_cli_process_resp_intr(struct tw_cli_ctlr_context *ctlr);
/* Submit any requests in the pending queue to the firmware. */
extern TW_INT32 tw_cli_submit_pending_queue(struct tw_cli_ctlr_context *ctlr);
/* Process all requests in the complete queue. */
extern TW_VOID tw_cli_process_complete_queue(struct tw_cli_ctlr_context *ctlr);
/* CL internal callback for SCSI/fw passthru requests. */
extern TW_VOID tw_cli_complete_io(struct tw_cli_req_context *req);
/* Completion routine for SCSI requests. */
extern TW_VOID tw_cli_scsi_complete(struct tw_cli_req_context *req);
/* Callback for get/set param requests. */
extern TW_VOID tw_cli_param_callback(struct tw_cli_req_context *req);
/* Callback for Req Sense commands to get AEN's. */
extern TW_VOID tw_cli_aen_callback(struct tw_cli_req_context *req);
/* Decide what to do with a retrieved AEN. */
extern TW_UINT16 tw_cli_manage_aen(struct tw_cli_ctlr_context *ctlr,
struct tw_cli_req_context *req);
/* Enable controller interrupts. */
extern TW_VOID
tw_cli_enable_interrupts(struct tw_cli_ctlr_context *ctlr_handle);
/* Disable controller interrupts. */
extern TW_VOID
tw_cli_disable_interrupts(struct tw_cli_ctlr_context *ctlr_handle);
/* Functions in tw_cl_misc.c */
/* Print if dbg_level is appropriate (by calling OS Layer). */
extern TW_VOID tw_cli_dbg_printf(TW_UINT8 dbg_level,
struct tw_cl_ctlr_handle *ctlr_handle, const TW_INT8 *cur_func,
TW_INT8 *fmt, ...);
/* Describe meaning of each set bit in the given register. */
extern TW_INT8 *tw_cli_describe_bits(TW_UINT32 reg, TW_INT8 *str);
/* Complete all requests in the complete queue with a RESET status. */
extern TW_VOID tw_cli_drain_complete_queue(struct tw_cli_ctlr_context *ctlr);
/* Complete all requests in the busy queue with a RESET status. */
extern TW_VOID tw_cli_drain_busy_queue(struct tw_cli_ctlr_context *ctlr);
/* Complete all requests in the pending queue with a RESET status. */
extern TW_VOID tw_cli_drain_pending_queue(struct tw_cli_ctlr_context *ctlr);
/* Drain the controller response queue. */
extern TW_INT32 tw_cli_drain_response_queue(struct tw_cli_ctlr_context *ctlr);
/* Find a particular response in the controller response queue. */
extern TW_INT32 tw_cli_find_response(struct tw_cli_ctlr_context *ctlr,
TW_INT32 req_id);
/* Drain the controller AEN queue. */
extern TW_INT32 tw_cli_drain_aen_queue(struct tw_cli_ctlr_context *ctlr);
/* Determine if a given AEN has been posted by the firmware. */
extern TW_INT32 tw_cli_find_aen(struct tw_cli_ctlr_context *ctlr,
TW_UINT16 aen_code);
/* Poll for a given status to show up in the firmware status register. */
extern TW_INT32 tw_cli_poll_status(struct tw_cli_ctlr_context *ctlr,
TW_UINT32 status, TW_UINT32 timeout);
/* Get a free CL internal request context packet. */
extern struct tw_cli_req_context *
tw_cli_get_request(struct tw_cli_ctlr_context *ctlr
);
/* Notify OSL of controller info (fw/BIOS versions, etc.). */
extern TW_VOID tw_cli_notify_ctlr_info(struct tw_cli_ctlr_context *ctlr);
/* Make sure that the firmware status register reports a proper status. */
extern TW_INT32 tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr,
TW_UINT32 status_reg);
#endif /* TW_CL_EXTERNS_H */

View file

@ -1,418 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
*/
#ifndef TW_CL_FWIF_H
#define TW_CL_FWIF_H
/*
* Macros and data structures for interfacing with the firmware.
*/
/* 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
#define TWA_LARGE_RESPONSE_QUEUE_OFFSET 0x30
/* Control register bit definitions. */
#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_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_UNEXPECTED_BITS 0x00D00000
/* PCI related defines. */
#define TWA_IO_CONFIG_REG 0x10
#define TWA_PCI_CONFIG_CLEAR_PARITY_ERROR 0xc100
#define TWA_PCI_CONFIG_CLEAR_PCI_ABORT 0x2000
#define TWA_RESET_PHASE1_NOTIFICATION_RESPONSE 0xFFFF
#define TWA_RESET_PHASE1_WAIT_TIME_MS 500
/* Command packet opcodes. */
#define TWA_FW_CMD_NOP 0x00
#define TWA_FW_CMD_INIT_CONNECTION 0x01
#define TWA_FW_CMD_READ 0x02
#define TWA_FW_CMD_WRITE 0x03
#define TWA_FW_CMD_READVERIFY 0x04
#define TWA_FW_CMD_VERIFY 0x05
#define TWA_FW_CMD_ZEROUNIT 0x08
#define TWA_FW_CMD_REPLACEUNIT 0x09
#define TWA_FW_CMD_HOTSWAP 0x0A
#define TWA_FW_CMD_SELFTESTS 0x0B
#define TWA_FW_CMD_SYNC_PARAM 0x0C
#define TWA_FW_CMD_REORDER_UNITS 0x0D
#define TWA_FW_CMD_EXECUTE_SCSI 0x10
#define TWA_FW_CMD_ATA_PASSTHROUGH 0x11
#define TWA_FW_CMD_GET_PARAM 0x12
#define TWA_FW_CMD_SET_PARAM 0x13
#define TWA_FW_CMD_CREATEUNIT 0x14
#define TWA_FW_CMD_DELETEUNIT 0x15
#define TWA_FW_CMD_DOWNLOAD_FIRMWARE 0x16
#define TWA_FW_CMD_REBUILDUNIT 0x17
#define TWA_FW_CMD_POWER_MANAGEMENT 0x18
#define TWA_FW_CMD_REMOTE_PRINT 0x1B
#define TWA_FW_CMD_HARD_RESET_FIRMWARE 0x1C
#define TWA_FW_CMD_DEBUG 0x1D
#define TWA_FW_CMD_DIAGNOSTICS 0x1F
/* Misc defines. */
#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 41
#define TWA_CURRENT_FW_BRANCH_9K 4
#define TWA_CURRENT_FW_BUILD_9K 8
#define TWA_CURRENT_FW_BRANCH_9K_X 8
#define TWA_CURRENT_FW_BUILD_9K_X 4
#define TWA_MULTI_LUN_FW_SRL 28
#define TWA_ARCH_ID_9K 0x5 /* 9000 PCI controllers */
#define TWA_ARCH_ID_9K_X 0x6 /* 9000 PCI-X controllers */
#define TWA_CTLR_FW_SAME_OR_NEWER 0x00000001
#define TWA_CTLR_FW_COMPATIBLE 0x00000002
#define TWA_SENSE_DATA_LENGTH 18
#define TWA_ARCH_ID(device_id) \
(((device_id) == TW_CL_DEVICE_ID_9K) ? TWA_ARCH_ID_9K : \
TWA_ARCH_ID_9K_X)
#define TWA_CURRENT_FW_BRANCH(arch_id) \
(((arch_id) == TWA_ARCH_ID_9K) ? TWA_CURRENT_FW_BRANCH_9K : \
TWA_CURRENT_FW_BRANCH_9K_X)
#define TWA_CURRENT_FW_BUILD(arch_id) \
(((arch_id) == TWA_ARCH_ID_9K) ? TWA_CURRENT_FW_BUILD_9K : \
TWA_CURRENT_FW_BUILD_9K_X)
/*
* All SG addresses and DMA'able memory allocated by the OSL should be
* TWA_ALIGNMENT bytes aligned, and have a size that is a multiple of
* TWA_SG_ELEMENT_SIZE_FACTOR.
*/
#define TWA_ALIGNMENT(device_id) 0x4
#define TWA_SG_ELEMENT_SIZE_FACTOR(device_id) \
(((device_id) == TW_CL_DEVICE_ID_9K) ? 512 : 4)
/*
* Some errors of interest (in cmd_hdr->status_block.error) when a command
* is completed by the firmware with a bad status.
*/
#define TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED 0x010a
#define TWA_ERROR_UNIT_OFFLINE 0x0128
#define TWA_ERROR_MORE_DATA 0x0231
/* AEN codes of interest. */
#define TWA_AEN_QUEUE_EMPTY 0x00
#define TWA_AEN_SOFT_RESET 0x01
#define TWA_AEN_SYNC_TIME_WITH_HOST 0x31
/* Table #'s and id's of parameters of interest in firmware's param table. */
#define TWA_PARAM_VERSION_TABLE 0x0402
#define TWA_PARAM_VERSION_FW 3 /* firmware version [16] */
#define TWA_PARAM_VERSION_BIOS 4 /* BIOSs version [16] */
#define TWA_PARAM_CTLR_MODEL 8 /* Controller model [16] */
#define TWA_PARAM_CONTROLLER_TABLE 0x0403
#define TWA_PARAM_CONTROLLER_PORT_COUNT 3 /* number of ports [1] */
#define TWA_PARAM_TIME_TABLE 0x40A
#define TWA_PARAM_TIME_SCHED_TIME 0x3
#define TWA_9K_PARAM_DESCRIPTOR 0x8000
#pragma pack(1)
/* 7000 structures. */
struct tw_cl_command_init_connect {
TW_UINT8 res1__opcode; /* 3:5 */
TW_UINT8 size;
TW_UINT8 request_id;
TW_UINT8 res2;
TW_UINT8 status;
TW_UINT8 flags;
TW_UINT16 message_credits;
TW_UINT32 features;
TW_UINT16 fw_srl;
TW_UINT16 fw_arch_id;
TW_UINT16 fw_branch;
TW_UINT16 fw_build;
TW_UINT32 result;
};
/* Structure for downloading firmware onto the controller. */
struct tw_cl_command_download_firmware {
TW_UINT8 sgl_off__opcode;/* 3:5 */
TW_UINT8 size;
TW_UINT8 request_id;
TW_UINT8 unit;
TW_UINT8 status;
TW_UINT8 flags;
TW_UINT16 param;
TW_UINT8 sgl[1];
};
/* Structure for hard resetting the controller. */
struct tw_cl_command_reset_firmware {
TW_UINT8 res1__opcode; /* 3:5 */
TW_UINT8 size;
TW_UINT8 request_id;
TW_UINT8 unit;
TW_UINT8 status;
TW_UINT8 flags;
TW_UINT8 res2;
TW_UINT8 param;
};
/* Structure for sending get/set param commands. */
struct tw_cl_command_param {
TW_UINT8 sgl_off__opcode;/* 3:5 */
TW_UINT8 size;
TW_UINT8 request_id;
TW_UINT8 host_id__unit; /* 4:4 */
TW_UINT8 status;
TW_UINT8 flags;
TW_UINT16 param_count;
TW_UINT8 sgl[1];
};
/* Generic command packet. */
struct tw_cl_command_generic {
TW_UINT8 sgl_off__opcode;/* 3:5 */
TW_UINT8 size;
TW_UINT8 request_id;
TW_UINT8 host_id__unit; /* 4:4 */
TW_UINT8 status;
TW_UINT8 flags;
TW_UINT16 count; /* block cnt, parameter cnt, message credits */
};
/* Command packet header. */
struct tw_cl_command_header {
TW_UINT8 sense_data[TWA_SENSE_DATA_LENGTH];
struct {
TW_INT8 reserved[4];
TW_UINT16 error;
TW_UINT8 padding;
TW_UINT8 res__severity; /* 5:3 */
} status_block;
TW_UINT8 err_specific_desc[98];
struct {
TW_UINT8 size_header;
TW_UINT16 reserved;
TW_UINT8 size_sense;
} header_desc;
};
/* 7000 Command packet. */
union tw_cl_command_7k {
struct tw_cl_command_init_connect init_connect;
struct tw_cl_command_download_firmware download_fw;
struct tw_cl_command_reset_firmware reset_fw;
struct tw_cl_command_param param;
struct tw_cl_command_generic generic;
TW_UINT8 padding[1024 - sizeof(struct tw_cl_command_header)];
};
/* 9000 Command Packet. */
struct tw_cl_command_9k {
TW_UINT8 res__opcode; /* 3:5 */
TW_UINT8 unit;
TW_UINT16 lun_l4__req_id; /* 4:12 */
TW_UINT8 status;
TW_UINT8 sgl_offset; /* offset (in bytes) to sg_list, from the
end of sgl_entries */
TW_UINT16 lun_h4__sgl_entries;
TW_UINT8 cdb[16];
TW_UINT8 sg_list[872];/* total struct size =
1024-sizeof(cmd_hdr) */
};
/* Full command packet. */
struct tw_cl_command_packet {
struct tw_cl_command_header cmd_hdr;
union {
union tw_cl_command_7k cmd_pkt_7k;
struct tw_cl_command_9k cmd_pkt_9k;
} command;
};
/* Structure describing payload for get/set param commands. */
struct tw_cl_param_9k {
TW_UINT16 table_id;
TW_UINT8 parameter_id;
TW_UINT8 reserved;
TW_UINT16 parameter_size_bytes;
TW_UINT16 parameter_actual_size_bytes;
TW_UINT8 data[1];
};
#pragma pack()
/* Functions to read from, and write to registers */
#define TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle, value) \
tw_osl_write_reg(ctlr_handle, TWA_CONTROL_REGISTER_OFFSET, value, 4)
#define TW_CLI_READ_STATUS_REGISTER(ctlr_handle) \
tw_osl_read_reg(ctlr_handle, TWA_STATUS_REGISTER_OFFSET, 4)
#define TW_CLI_WRITE_COMMAND_QUEUE(ctlr_handle, value) do { \
if (ctlr->flags & TW_CL_64BIT_ADDRESSES) { \
/* First write the low 4 bytes, then the high 4. */ \
tw_osl_write_reg(ctlr_handle, TWA_COMMAND_QUEUE_OFFSET_LOW, \
(TW_UINT32)(value), 4); \
tw_osl_write_reg(ctlr_handle, TWA_COMMAND_QUEUE_OFFSET_HIGH,\
(TW_UINT32)(((TW_UINT64)value)>>32), 4); \
} else \
tw_osl_write_reg(ctlr_handle, TWA_COMMAND_QUEUE_OFFSET, \
(TW_UINT32)(value), 4); \
} while (0)
#define TW_CLI_READ_RESPONSE_QUEUE(ctlr_handle) \
tw_osl_read_reg(ctlr_handle, TWA_RESPONSE_QUEUE_OFFSET, 4)
#define TW_CLI_READ_LARGE_RESPONSE_QUEUE(ctlr_handle) \
tw_osl_read_reg(ctlr_handle, TWA_LARGE_RESPONSE_QUEUE_OFFSET, 4)
#define TW_CLI_SOFT_RESET(ctlr) \
TW_CLI_WRITE_CONTROL_REGISTER(ctlr, \
TWA_CONTROL_ISSUE_SOFT_RESET | \
TWA_CONTROL_CLEAR_HOST_INTERRUPT | \
TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT | \
TWA_CONTROL_MASK_COMMAND_INTERRUPT | \
TWA_CONTROL_MASK_RESPONSE_INTERRUPT | \
TWA_CONTROL_DISABLE_INTERRUPTS)
/* Detect inconsistencies in the status register. */
#define TW_CLI_STATUS_ERRORS(x) \
((x & TWA_STATUS_UNEXPECTED_BITS) && \
(x & TWA_STATUS_MICROCONTROLLER_READY))
/*
* Functions for making transparent, the bit fields in firmware
* interface structures.
*/
#define BUILD_SGL_OFF__OPCODE(sgl_off, opcode) \
((sgl_off << 5) & 0xE0) | (opcode & 0x1F) /* 3:5 */
#define BUILD_RES__OPCODE(res, opcode) \
((res << 5) & 0xE0) | (opcode & 0x1F) /* 3:5 */
#define BUILD_HOST_ID__UNIT(host_id, unit) \
((host_id << 4) & 0xF0) | (unit & 0xF) /* 4:4 */
#define BUILD_RES__SEVERITY(res, severity) \
((res << 3) & 0xF8) | (severity & 0x7) /* 5:3 */
#define BUILD_LUN_L4__REQ_ID(lun, req_id) \
(((lun << 12) & 0xF000) | (req_id & 0xFFF)) /* 4:12 */
#define BUILD_LUN_H4__SGL_ENTRIES(lun, sgl_entries) \
(((lun << 8) & 0xF000) | (sgl_entries & 0xFFF)) /* 4:12 */
#define GET_OPCODE(sgl_off__opcode) \
(sgl_off__opcode & 0x1F) /* 3:5 */
#define GET_SGL_OFF(sgl_off__opcode) \
((sgl_off__opcode >> 5) & 0x7) /* 3:5 */
#define GET_UNIT(host_id__unit) \
(host_id__unit & 0xF) /* 4:4 */
#define GET_HOST_ID(host_id__unit) \
((host_id__unit >> 4) & 0xF) /* 4:4 */
#define GET_SEVERITY(res__severity) \
(res__severity & 0x7) /* 5:3 */
#define GET_RESP_ID(undef2__resp_id__undef1) \
((undef2__resp_id__undef1 >> 4) & 0xFF) /* 20:8:4 */
#define GET_RESP_ID_9K_X(undef2__resp_id) \
((undef2__resp_id) & 0xFFF) /* 20:12 */
#define GET_LARGE_RESP_ID(misc__large_resp_id) \
((misc__large_resp_id) & 0xFFFF) /* 16:16 */
#define GET_REQ_ID(lun_l4__req_id) \
(lun_l4__req_id & 0xFFF) /* 4:12 */
#define GET_LUN_L4(lun_l4__req_id) \
((lun_l4__req_id >> 12) & 0xF) /* 4:12 */
#define GET_SGL_ENTRIES(lun_h4__sgl_entries) \
(lun_h4__sgl_entries & 0xFFF) /* 4:12 */
#define GET_LUN_H4(lun_h4__sgl_entries) \
((lun_h4__sgl_entries >> 12) & 0xF) /* 4:12 */
#endif /* TW_CL_FWIF_H */

View file

@ -1,696 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
* Modifications by: Manjunath Ranganathaiah
*/
/*
* Common Layer initialization functions.
*/
#include "tw_osl_share.h"
#include "tw_cl_share.h"
#include "tw_cl_fwif.h"
#include "tw_cl_ioctl.h"
#include "tw_cl.h"
#include "tw_cl_externs.h"
#include "tw_osl_ioctl.h"
/*
* Function name: tw_cl_ctlr_supported
* Description: Determines if a controller is supported.
*
* Input: vendor_id -- vendor id of the controller
* device_id -- device id of the controller
* Output: None
* Return value: TW_CL_TRUE-- controller supported
* TW_CL_FALSE-- controller not supported
*/
TW_INT32
tw_cl_ctlr_supported(TW_INT32 vendor_id, TW_INT32 device_id)
{
if ((vendor_id == TW_CL_VENDOR_ID) &&
((device_id == TW_CL_DEVICE_ID_9K) ||
(device_id == TW_CL_DEVICE_ID_9K_X) ||
(device_id == TW_CL_DEVICE_ID_9K_E) ||
(device_id == TW_CL_DEVICE_ID_9K_SA)))
return(TW_CL_TRUE);
return(TW_CL_FALSE);
}
/*
* Function name: tw_cl_get_pci_bar_info
* Description: Returns PCI BAR info.
*
* Input: device_id -- device id of the controller
* bar_type -- type of PCI BAR in question
* Output: bar_num -- PCI BAR number corresponding to bar_type
* bar0_offset -- byte offset from BAR 0 (0x10 in
* PCI config space)
* bar_size -- size, in bytes, of the BAR in question
* Return value: 0 -- success
* non-zero -- failure
*/
TW_INT32
tw_cl_get_pci_bar_info(TW_INT32 device_id, TW_INT32 bar_type,
TW_INT32 *bar_num, TW_INT32 *bar0_offset, TW_INT32 *bar_size)
{
TW_INT32 error = TW_OSL_ESUCCESS;
switch(device_id) {
case TW_CL_DEVICE_ID_9K:
switch(bar_type) {
case TW_CL_BAR_TYPE_IO:
*bar_num = 0;
*bar0_offset = 0;
*bar_size = 4;
break;
case TW_CL_BAR_TYPE_MEM:
*bar_num = 1;
*bar0_offset = 0x4;
*bar_size = 8;
break;
case TW_CL_BAR_TYPE_SBUF:
*bar_num = 2;
*bar0_offset = 0xC;
*bar_size = 8;
break;
}
break;
case TW_CL_DEVICE_ID_9K_X:
case TW_CL_DEVICE_ID_9K_E:
case TW_CL_DEVICE_ID_9K_SA:
switch(bar_type) {
case TW_CL_BAR_TYPE_IO:
*bar_num = 2;
*bar0_offset = 0x10;
*bar_size = 4;
break;
case TW_CL_BAR_TYPE_MEM:
*bar_num = 1;
*bar0_offset = 0x8;
*bar_size = 8;
break;
case TW_CL_BAR_TYPE_SBUF:
*bar_num = 0;
*bar0_offset = 0;
*bar_size = 8;
break;
}
break;
default:
error = TW_OSL_ENOTTY;
break;
}
return(error);
}
/*
* Function name: tw_cl_get_mem_requirements
* Description: Provides info about Common Layer requirements for a
* controller, given the controller type (in 'flags').
* Input: ctlr_handle -- controller handle
* flags -- more info passed by the OS Layer
* device_id -- device id of the controller
* max_simult_reqs -- maximum # of simultaneous
* requests that the OS Layer expects
* the Common Layer to support
* max_aens -- maximun # of AEN's needed to be supported
* Output: alignment -- alignment needed for all DMA'able
* buffers
* sg_size_factor -- every SG element should have a size
* that's a multiple of this number
* non_dma_mem_size -- # of bytes of memory needed for
* non-DMA purposes
* dma_mem_size -- # of bytes of DMA'able memory needed
* per_req_dma_mem_size -- # of bytes of DMA'able memory
* needed per request, if applicable
* per_req_non_dma_mem_size -- # of bytes of memory needed
* per request for non-DMA purposes,
* if applicable
* Output: None
* Return value: 0 -- success
* non-zero-- failure
*/
TW_INT32
tw_cl_get_mem_requirements(struct tw_cl_ctlr_handle *ctlr_handle,
TW_UINT32 flags, TW_INT32 device_id, TW_INT32 max_simult_reqs,
TW_INT32 max_aens, TW_UINT32 *alignment, TW_UINT32 *sg_size_factor,
TW_UINT32 *non_dma_mem_size, TW_UINT32 *dma_mem_size
)
{
if (device_id == 0)
device_id = TW_CL_DEVICE_ID_9K;
if (max_simult_reqs > TW_CL_MAX_SIMULTANEOUS_REQUESTS) {
tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1000, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Too many simultaneous requests to support!",
"requested = %d, supported = %d, error = %d\n",
max_simult_reqs, TW_CL_MAX_SIMULTANEOUS_REQUESTS,
TW_OSL_EBIG);
return(TW_OSL_EBIG);
}
*alignment = TWA_ALIGNMENT(device_id);
*sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR(device_id);
/*
* Total non-DMA memory needed is the sum total of memory needed for
* the controller context, request packets (including the 1 needed for
* CL internal requests), and event packets.
*/
*non_dma_mem_size = sizeof(struct tw_cli_ctlr_context) +
(sizeof(struct tw_cli_req_context) * max_simult_reqs) +
(sizeof(struct tw_cl_event_packet) * max_aens);
/*
* Total DMA'able memory needed is the sum total of memory needed for
* all command packets (including the 1 needed for CL internal
* requests), and memory needed to hold the payload for internal
* requests.
*/
*dma_mem_size = (sizeof(struct tw_cl_command_packet) *
(max_simult_reqs)) + (TW_CLI_SECTOR_SIZE);
return(0);
}
/*
* Function name: tw_cl_init_ctlr
* Description: Initializes driver data structures for the controller.
*
* Input: ctlr_handle -- controller handle
* flags -- more info passed by the OS Layer
* device_id -- device id of the controller
* max_simult_reqs -- maximum # of simultaneous requests
* that the OS Layer expects the Common
* Layer to support
* max_aens -- maximun # of AEN's needed to be supported
* non_dma_mem -- ptr to allocated non-DMA memory
* dma_mem -- ptr to allocated DMA'able memory
* dma_mem_phys -- physical address of dma_mem
* Output: None
* Return value: 0 -- success
* non-zero-- failure
*/
TW_INT32
tw_cl_init_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags,
TW_INT32 device_id, TW_INT32 max_simult_reqs, TW_INT32 max_aens,
TW_VOID *non_dma_mem, TW_VOID *dma_mem, TW_UINT64 dma_mem_phys
)
{
struct tw_cli_ctlr_context *ctlr;
struct tw_cli_req_context *req;
TW_UINT8 *free_non_dma_mem;
TW_INT32 error = TW_OSL_ESUCCESS;
TW_INT32 i;
tw_cli_dbg_printf(3, ctlr_handle, tw_osl_cur_func(), "entered");
if (flags & TW_CL_START_CTLR_ONLY) {
ctlr = (struct tw_cli_ctlr_context *)
(ctlr_handle->cl_ctlr_ctxt);
goto start_ctlr;
}
if (max_simult_reqs > TW_CL_MAX_SIMULTANEOUS_REQUESTS) {
tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1000, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Too many simultaneous requests to support!",
"requested = %d, supported = %d, error = %d\n",
max_simult_reqs, TW_CL_MAX_SIMULTANEOUS_REQUESTS,
TW_OSL_EBIG);
return(TW_OSL_EBIG);
}
if ((non_dma_mem == TW_CL_NULL) || (dma_mem == TW_CL_NULL)
) {
tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1001, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Insufficient memory for Common Layer's internal usage",
"error = %d\n", TW_OSL_ENOMEM);
return(TW_OSL_ENOMEM);
}
tw_osl_memzero(non_dma_mem, sizeof(struct tw_cli_ctlr_context) +
(sizeof(struct tw_cli_req_context) * max_simult_reqs) +
(sizeof(struct tw_cl_event_packet) * max_aens));
tw_osl_memzero(dma_mem,
(sizeof(struct tw_cl_command_packet) *
max_simult_reqs) +
TW_CLI_SECTOR_SIZE);
free_non_dma_mem = (TW_UINT8 *)non_dma_mem;
ctlr = (struct tw_cli_ctlr_context *)free_non_dma_mem;
free_non_dma_mem += sizeof(struct tw_cli_ctlr_context);
ctlr_handle->cl_ctlr_ctxt = ctlr;
ctlr->ctlr_handle = ctlr_handle;
ctlr->device_id = (TW_UINT32)device_id;
ctlr->arch_id = TWA_ARCH_ID(device_id);
ctlr->flags = flags;
ctlr->sg_size_factor = TWA_SG_ELEMENT_SIZE_FACTOR(device_id);
ctlr->max_simult_reqs = max_simult_reqs;
ctlr->max_aens_supported = max_aens;
/* Initialize queues of CL internal request context packets. */
tw_cli_req_q_init(ctlr, TW_CLI_FREE_Q);
tw_cli_req_q_init(ctlr, TW_CLI_BUSY_Q);
tw_cli_req_q_init(ctlr, TW_CLI_PENDING_Q);
tw_cli_req_q_init(ctlr, TW_CLI_COMPLETE_Q);
tw_cli_req_q_init(ctlr, TW_CLI_RESET_Q);
/* Initialize all locks used by CL. */
ctlr->gen_lock = &(ctlr->gen_lock_handle);
tw_osl_init_lock(ctlr_handle, "tw_cl_gen_lock", ctlr->gen_lock);
ctlr->io_lock = &(ctlr->io_lock_handle);
tw_osl_init_lock(ctlr_handle, "tw_cl_io_lock", ctlr->io_lock);
/* Initialize CL internal request context packets. */
ctlr->req_ctxt_buf = (struct tw_cli_req_context *)free_non_dma_mem;
free_non_dma_mem += (sizeof(struct tw_cli_req_context) *
max_simult_reqs);
ctlr->cmd_pkt_buf = (struct tw_cl_command_packet *)dma_mem;
ctlr->cmd_pkt_phys = dma_mem_phys;
ctlr->internal_req_data = (TW_UINT8 *)
(ctlr->cmd_pkt_buf +
max_simult_reqs);
ctlr->internal_req_data_phys = ctlr->cmd_pkt_phys +
(sizeof(struct tw_cl_command_packet) *
max_simult_reqs);
for (i = 0; i < max_simult_reqs; i++) {
req = &(ctlr->req_ctxt_buf[i]);
req->cmd_pkt = &(ctlr->cmd_pkt_buf[i]);
req->cmd_pkt_phys = ctlr->cmd_pkt_phys +
(i * sizeof(struct tw_cl_command_packet));
req->request_id = i;
req->ctlr = ctlr;
/* Insert request into the free queue. */
tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
}
/* Initialize the AEN queue. */
ctlr->aen_queue = (struct tw_cl_event_packet *)free_non_dma_mem;
start_ctlr:
/*
* Disable interrupts. Interrupts will be enabled in tw_cli_start_ctlr
* (only) if initialization succeeded.
*/
tw_cli_disable_interrupts(ctlr);
/* Initialize the controller. */
if ((error = tw_cli_start_ctlr(ctlr))) {
/* Soft reset the controller, and try one more time. */
tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1002, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Controller initialization failed. Retrying...",
"error = %d\n", error);
if ((error = tw_cli_soft_reset(ctlr))) {
tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1003, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Controller soft reset failed",
"error = %d\n", error);
return(error);
} else if ((error = tw_cli_start_ctlr(ctlr))) {
tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1004, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Controller initialization retry failed",
"error = %d\n", error);
return(error);
}
}
/* Notify some info about the controller to the OSL. */
tw_cli_notify_ctlr_info(ctlr);
/* Mark the controller active. */
ctlr->active = TW_CL_TRUE;
return(error);
}
/*
* Function name: tw_cli_start_ctlr
* Description: Establishes a logical connection with the controller.
* Determines whether or not the driver is compatible
* with the firmware on the controller, before proceeding
* to work with it.
*
* Input: ctlr -- ptr to per ctlr structure
* Output: None
* Return value: 0 -- success
* non-zero-- failure
*/
TW_INT32
tw_cli_start_ctlr(struct tw_cli_ctlr_context *ctlr)
{
TW_UINT16 fw_on_ctlr_srl = 0;
TW_UINT16 fw_on_ctlr_arch_id = 0;
TW_UINT16 fw_on_ctlr_branch = 0;
TW_UINT16 fw_on_ctlr_build = 0;
TW_UINT32 init_connect_result = 0;
TW_INT32 error = TW_OSL_ESUCCESS;
tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
/* Wait for the controller to become ready. */
if ((error = tw_cli_poll_status(ctlr,
TWA_STATUS_MICROCONTROLLER_READY,
TW_CLI_REQUEST_TIMEOUT_PERIOD))) {
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1009, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Microcontroller not ready",
"error = %d", error);
return(error);
}
/* Drain the response queue. */
if ((error = tw_cli_drain_response_queue(ctlr))) {
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x100A, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Can't drain response queue",
"error = %d", error);
return(error);
}
/* Establish a logical connection with the controller. */
if ((error = tw_cli_init_connection(ctlr,
(TW_UINT16)(ctlr->max_simult_reqs),
TWA_EXTENDED_INIT_CONNECT, TWA_CURRENT_FW_SRL,
(TW_UINT16)(ctlr->arch_id),
TWA_CURRENT_FW_BRANCH(ctlr->arch_id),
TWA_CURRENT_FW_BUILD(ctlr->arch_id),
&fw_on_ctlr_srl, &fw_on_ctlr_arch_id,
&fw_on_ctlr_branch, &fw_on_ctlr_build,
&init_connect_result))) {
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x100B, 0x2, TW_CL_SEVERITY_WARNING_STRING,
"Can't initialize connection in current mode",
"error = %d", error);
return(error);
}
{
/* See if we can at least work with the firmware on the
* controller in the current mode.
*/
if (init_connect_result & TWA_CTLR_FW_COMPATIBLE) {
/* Yes, we can. Make note of the operating mode. */
if (init_connect_result & TWA_CTLR_FW_SAME_OR_NEWER) {
ctlr->working_srl = TWA_CURRENT_FW_SRL;
ctlr->working_branch =
TWA_CURRENT_FW_BRANCH(ctlr->arch_id);
ctlr->working_build =
TWA_CURRENT_FW_BUILD(ctlr->arch_id);
} else {
ctlr->working_srl = fw_on_ctlr_srl;
ctlr->working_branch = fw_on_ctlr_branch;
ctlr->working_build = fw_on_ctlr_build;
}
} else {
/*
* No, we can't. See if we can at least work with
* it in the base mode.
*/
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1010, 0x2, TW_CL_SEVERITY_WARNING_STRING,
"Driver/Firmware mismatch. "
"Negotiating for base level...",
" ");
if ((error = tw_cli_init_connection(ctlr,
(TW_UINT16)(ctlr->max_simult_reqs),
TWA_EXTENDED_INIT_CONNECT,
TWA_BASE_FW_SRL,
(TW_UINT16)(ctlr->arch_id),
TWA_BASE_FW_BRANCH, TWA_BASE_FW_BUILD,
&fw_on_ctlr_srl, &fw_on_ctlr_arch_id,
&fw_on_ctlr_branch, &fw_on_ctlr_build,
&init_connect_result))) {
tw_cl_create_event(ctlr->ctlr_handle,
TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1011, 0x1,
TW_CL_SEVERITY_ERROR_STRING,
"Can't initialize connection in "
"base mode",
" ");
return(error);
}
if (!(init_connect_result & TWA_CTLR_FW_COMPATIBLE)) {
/*
* The firmware on the controller is not even
* compatible with our base mode. We cannot
* work with it. Bail...
*/
return(1);
}
/*
* We can work with this firmware, but only in
* base mode.
*/
ctlr->working_srl = TWA_BASE_FW_SRL;
ctlr->working_branch = TWA_BASE_FW_BRANCH;
ctlr->working_build = TWA_BASE_FW_BUILD;
ctlr->operating_mode = TWA_BASE_MODE;
}
ctlr->fw_on_ctlr_srl = fw_on_ctlr_srl;
ctlr->fw_on_ctlr_branch = fw_on_ctlr_branch;
ctlr->fw_on_ctlr_build = fw_on_ctlr_build;
}
/* Drain the AEN queue */
if ((error = tw_cli_drain_aen_queue(ctlr)))
/*
* We will just print that we couldn't drain the AEN queue.
* There's no need to bail out.
*/
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1014, 0x2, TW_CL_SEVERITY_WARNING_STRING,
"Can't drain AEN queue",
"error = %d", error);
/* Enable interrupts. */
tw_cli_enable_interrupts(ctlr);
return(TW_OSL_ESUCCESS);
}
/*
* Function name: tw_cl_shutdown_ctlr
* Description: Closes logical connection with the controller.
*
* Input: ctlr -- ptr to per ctlr structure
* flags -- more info passed by the OS Layer
* Output: None
* Return value: 0 -- success
* non-zero-- failure
*/
TW_INT32
tw_cl_shutdown_ctlr(struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags)
{
struct tw_cli_ctlr_context *ctlr =
(struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
TW_INT32 error;
tw_cli_dbg_printf(3, ctlr_handle, tw_osl_cur_func(), "entered");
/*
* Mark the controller as inactive, disable any further interrupts,
* and notify the controller that we are going down.
*/
ctlr->active = TW_CL_FALSE;
tw_cli_disable_interrupts(ctlr);
/* Let the controller know that we are going down. */
if ((error = tw_cli_init_connection(ctlr, TWA_SHUTDOWN_MESSAGE_CREDITS,
0, 0, 0, 0, 0, TW_CL_NULL, TW_CL_NULL, TW_CL_NULL,
TW_CL_NULL, TW_CL_NULL)))
tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1015, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Can't close connection with controller",
"error = %d", error);
if (flags & TW_CL_STOP_CTLR_ONLY)
goto ret;
/* Destroy all locks used by CL. */
tw_osl_destroy_lock(ctlr_handle, ctlr->gen_lock);
tw_osl_destroy_lock(ctlr_handle, ctlr->io_lock);
ret:
return(error);
}
/*
* Function name: tw_cli_init_connection
* Description: Sends init_connection cmd to firmware
*
* Input: ctlr -- ptr to per ctlr structure
* message_credits -- max # of requests that we might send
* down simultaneously. This will be
* typically set to 256 at init-time or
* after a reset, and to 1 at shutdown-time
* set_features -- indicates if we intend to use 64-bit
* sg, also indicates if we want to do a
* basic or an extended init_connection;
*
* Note: The following input/output parameters are valid, only in case of an
* extended init_connection:
*
* current_fw_srl -- srl of fw we are bundled
* with, if any; 0 otherwise
* current_fw_arch_id -- arch_id of fw we are bundled
* with, if any; 0 otherwise
* current_fw_branch -- branch # of fw we are bundled
* with, if any; 0 otherwise
* current_fw_build -- build # of fw we are bundled
* with, if any; 0 otherwise
* Output: fw_on_ctlr_srl -- srl of fw on ctlr
* fw_on_ctlr_arch_id -- arch_id of fw on ctlr
* fw_on_ctlr_branch -- branch # of fw on ctlr
* fw_on_ctlr_build -- build # of fw on ctlr
* init_connect_result -- result bitmap of fw response
* Return value: 0 -- success
* non-zero-- failure
*/
TW_INT32
tw_cli_init_connection(struct tw_cli_ctlr_context *ctlr,
TW_UINT16 message_credits, TW_UINT32 set_features,
TW_UINT16 current_fw_srl, TW_UINT16 current_fw_arch_id,
TW_UINT16 current_fw_branch, TW_UINT16 current_fw_build,
TW_UINT16 *fw_on_ctlr_srl, TW_UINT16 *fw_on_ctlr_arch_id,
TW_UINT16 *fw_on_ctlr_branch, TW_UINT16 *fw_on_ctlr_build,
TW_UINT32 *init_connect_result)
{
struct tw_cli_req_context *req;
struct tw_cl_command_init_connect *init_connect;
TW_INT32 error = TW_OSL_EBUSY;
tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
/* Get a request packet. */
if ((req = tw_cli_get_request(ctlr
)) == TW_CL_NULL)
goto out;
req->flags |= TW_CLI_REQ_FLAGS_INTERNAL;
/* Build the cmd pkt. */
init_connect = &(req->cmd_pkt->command.cmd_pkt_7k.init_connect);
req->cmd_pkt->cmd_hdr.header_desc.size_header = 128;
init_connect->res1__opcode =
BUILD_RES__OPCODE(0, TWA_FW_CMD_INIT_CONNECTION);
init_connect->request_id =
(TW_UINT8)(TW_CL_SWAP16(req->request_id));
init_connect->message_credits = TW_CL_SWAP16(message_credits);
init_connect->features = TW_CL_SWAP32(set_features);
if (ctlr->flags & TW_CL_64BIT_ADDRESSES)
init_connect->features |= TW_CL_SWAP32(TWA_64BIT_SG_ADDRESSES);
if (set_features & TWA_EXTENDED_INIT_CONNECT) {
/*
* Fill in the extra fields needed for an extended
* init_connect.
*/
init_connect->size = 6;
init_connect->fw_srl = TW_CL_SWAP16(current_fw_srl);
init_connect->fw_arch_id = TW_CL_SWAP16(current_fw_arch_id);
init_connect->fw_branch = TW_CL_SWAP16(current_fw_branch);
init_connect->fw_build = TW_CL_SWAP16(current_fw_build);
} else
init_connect->size = 3;
/* Submit the command, and wait for it to complete. */
error = tw_cli_submit_and_poll_request(req,
TW_CLI_REQUEST_TIMEOUT_PERIOD);
if (error)
goto out;
if ((error = init_connect->status)) {
#if 0
tw_cli_create_ctlr_event(ctlr,
TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
&(req->cmd_pkt->cmd_hdr));
#endif // 0
goto out;
}
if (set_features & TWA_EXTENDED_INIT_CONNECT) {
*fw_on_ctlr_srl = TW_CL_SWAP16(init_connect->fw_srl);
*fw_on_ctlr_arch_id = TW_CL_SWAP16(init_connect->fw_arch_id);
*fw_on_ctlr_branch = TW_CL_SWAP16(init_connect->fw_branch);
*fw_on_ctlr_build = TW_CL_SWAP16(init_connect->fw_build);
*init_connect_result = TW_CL_SWAP32(init_connect->result);
}
tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
return(error);
out:
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1016, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"init_connection failed",
"error = %d", error);
if (req)
tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
return(error);
}

View file

@ -1,724 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
* Modifications by: Manjunath Ranganathaiah
*/
/*
* Common Layer interrupt handling functions.
*/
#include "tw_osl_share.h"
#include "tw_cl_share.h"
#include "tw_cl_fwif.h"
#include "tw_cl_ioctl.h"
#include "tw_cl.h"
#include "tw_cl_externs.h"
#include "tw_osl_ioctl.h"
/*
* Function name: twa_interrupt
* Description: Interrupt handler. Determines the kind of interrupt,
* and returns TW_CL_TRUE if it recognizes the interrupt.
*
* Input: ctlr_handle -- controller handle
* Output: None
* Return value: TW_CL_TRUE -- interrupt recognized
* TW_CL_FALSE-- interrupt not recognized
*/
TW_INT32
tw_cl_interrupt(struct tw_cl_ctlr_handle *ctlr_handle)
{
struct tw_cli_ctlr_context *ctlr =
(struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
TW_UINT32 status_reg;
TW_INT32 rc = TW_CL_FALSE;
tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered");
/* If we don't have controller context, bail */
if (ctlr == NULL)
goto out;
/*
* Bail If we get an interrupt while resetting, or shutting down.
*/
if (ctlr->reset_in_progress || !(ctlr->active))
goto out;
/* Read the status register to determine the type of interrupt. */
status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
if (tw_cli_check_ctlr_state(ctlr, status_reg))
goto out;
/* Clear the interrupt. */
if (status_reg & TWA_STATUS_HOST_INTERRUPT) {
tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
"Host interrupt");
TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
TWA_CONTROL_CLEAR_HOST_INTERRUPT);
}
if (status_reg & TWA_STATUS_ATTENTION_INTERRUPT) {
tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
"Attention interrupt");
rc |= TW_CL_TRUE; /* request for a deferred isr call */
tw_cli_process_attn_intr(ctlr);
TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT);
}
if (status_reg & TWA_STATUS_COMMAND_INTERRUPT) {
tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
"Command interrupt");
rc |= TW_CL_TRUE; /* request for a deferred isr call */
tw_cli_process_cmd_intr(ctlr);
if ((TW_CL_Q_FIRST_ITEM(&(ctlr->req_q_head[TW_CLI_PENDING_Q]))) == TW_CL_NULL)
TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
TWA_CONTROL_MASK_COMMAND_INTERRUPT);
}
if (status_reg & TWA_STATUS_RESPONSE_INTERRUPT) {
tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(),
"Response interrupt");
rc |= TW_CL_TRUE; /* request for a deferred isr call */
tw_cli_process_resp_intr(ctlr);
}
out:
return(rc);
}
/*
* Function name: tw_cli_process_host_intr
* Description: This function gets called if we triggered an interrupt.
* We don't use it as of now.
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_process_host_intr(struct tw_cli_ctlr_context *ctlr)
{
tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
}
/*
* Function name: tw_cli_process_attn_intr
* Description: This function gets called if the fw posted an AEN
* (Asynchronous Event Notification). It fetches
* all the AEN's that the fw might have posted.
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_process_attn_intr(struct tw_cli_ctlr_context *ctlr)
{
TW_INT32 error;
tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
if ((error = tw_cli_get_aen(ctlr))) {
/*
* If the driver is already in the process of retrieveing AEN's,
* we will be returned TW_OSL_EBUSY. In this case,
* tw_cli_param_callback or tw_cli_aen_callback will eventually
* retrieve the AEN this attention interrupt is for. So, we
* don't need to print the failure.
*/
if (error != TW_OSL_EBUSY)
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1200, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Failed to fetch AEN",
"error = %d", error);
}
}
/*
* Function name: tw_cli_process_cmd_intr
* Description: This function gets called if we hit a queue full
* condition earlier, and the fw is now ready for
* new cmds. Submits any pending requests.
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_process_cmd_intr(struct tw_cli_ctlr_context *ctlr)
{
tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
/* Start any requests that might be in the pending queue. */
tw_cli_submit_pending_queue(ctlr);
/*
* If tw_cli_submit_pending_queue was unsuccessful due to a "cmd queue
* full" condition, cmd_intr will already have been unmasked by
* tw_cli_submit_cmd. We don't need to do it again... simply return.
*/
}
/*
* Function name: tw_cli_process_resp_intr
* Description: Looks for cmd completions from fw; queues cmds completed
* by fw into complete queue.
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
* Return value: 0 -- no ctlr error
* non-zero-- ctlr error
*/
TW_INT32
tw_cli_process_resp_intr(struct tw_cli_ctlr_context *ctlr)
{
TW_UINT32 resp;
struct tw_cli_req_context *req;
TW_INT32 error;
TW_UINT32 status_reg;
tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
for (;;) {
status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
if ((error = tw_cli_check_ctlr_state(ctlr, status_reg)))
break;
if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY) {
tw_cli_dbg_printf(7, ctlr->ctlr_handle,
tw_osl_cur_func(), "Response queue empty");
break;
}
/* Response queue is not empty. */
resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle);
{
req = &(ctlr->req_ctxt_buf[GET_RESP_ID(resp)]);
}
if (req->state != TW_CLI_REQ_STATE_BUSY) {
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1201, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Unposted command completed!!",
"request = %p, status = %d",
req, req->state);
#ifdef TW_OSL_DEBUG
tw_cl_print_ctlr_stats(ctlr->ctlr_handle);
#endif /* TW_OSL_DEBUG */
continue;
}
/*
* Remove the request from the busy queue, mark it as complete,
* and enqueue it in the complete queue.
*/
tw_cli_req_q_remove_item(req, TW_CLI_BUSY_Q);
req->state = TW_CLI_REQ_STATE_COMPLETE;
tw_cli_req_q_insert_tail(req, TW_CLI_COMPLETE_Q);
}
/* Complete this, and other requests in the complete queue. */
tw_cli_process_complete_queue(ctlr);
return(error);
}
/*
* Function name: tw_cli_submit_pending_queue
* Description: Kick starts any requests in the pending queue.
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
* Return value: 0 -- all pending requests submitted successfully
* non-zero-- otherwise
*/
TW_INT32
tw_cli_submit_pending_queue(struct tw_cli_ctlr_context *ctlr)
{
struct tw_cli_req_context *req;
TW_INT32 error = TW_OSL_ESUCCESS;
tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
/*
* Pull requests off the pending queue, and submit them.
*/
while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_PENDING_Q)) !=
TW_CL_NULL) {
if ((error = tw_cli_submit_cmd(req))) {
if (error == TW_OSL_EBUSY) {
tw_cli_dbg_printf(2, ctlr->ctlr_handle,
tw_osl_cur_func(),
"Requeueing pending request");
req->state = TW_CLI_REQ_STATE_PENDING;
/*
* Queue the request at the head of the pending
* queue, and break away, so we don't try to
* submit any more requests.
*/
tw_cli_req_q_insert_head(req, TW_CLI_PENDING_Q);
break;
} else {
tw_cl_create_event(ctlr->ctlr_handle,
TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1202, 0x1,
TW_CL_SEVERITY_ERROR_STRING,
"Could not start request "
"in pending queue",
"request = %p, opcode = 0x%x, "
"error = %d", req,
GET_OPCODE(req->cmd_pkt->
command.cmd_pkt_9k.res__opcode),
error);
/*
* Set the appropriate error and call the CL
* internal callback if there's one. If the
* request originator is polling for completion,
* he should be checking req->error to
* determine that the request did not go
* through. The request originators are
* responsible for the clean-up.
*/
req->error_code = error;
req->state = TW_CLI_REQ_STATE_COMPLETE;
if (req->tw_cli_callback)
req->tw_cli_callback(req);
error = TW_OSL_ESUCCESS;
}
}
}
return(error);
}
/*
* Function name: tw_cli_process_complete_queue
* Description: Calls the CL internal callback routine, if any, for
* each request in the complete queue.
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_process_complete_queue(struct tw_cli_ctlr_context *ctlr)
{
struct tw_cli_req_context *req;
tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
/*
* Pull commands off the completed list, dispatch them appropriately.
*/
while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_COMPLETE_Q)) !=
TW_CL_NULL) {
/* Call the CL internal callback, if there's one. */
if (req->tw_cli_callback)
req->tw_cli_callback(req);
}
}
/*
* Function name: tw_cli_complete_io
* Description: CL internal callback for SCSI/fw passthru requests.
*
* Input: req -- ptr to CL internal request context
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_complete_io(struct tw_cli_req_context *req)
{
struct tw_cli_ctlr_context *ctlr = req->ctlr;
struct tw_cl_req_packet *req_pkt =
(struct tw_cl_req_packet *)(req->orig_req);
tw_cli_dbg_printf(8, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
req_pkt->status = TW_CL_ERR_REQ_SUCCESS;
if (req->error_code) {
req_pkt->status = TW_CL_ERR_REQ_UNABLE_TO_SUBMIT_COMMAND;
goto out;
}
if (req->state != TW_CLI_REQ_STATE_COMPLETE) {
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1203, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"I/O completion on incomplete command!!",
"request = %p, status = %d",
req, req->state);
#ifdef TW_OSL_DEBUG
tw_cl_print_ctlr_stats(ctlr->ctlr_handle);
#endif /* TW_OSL_DEBUG */
return;
}
if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
/* Copy the command packet back into OSL's space. */
tw_osl_memcpy(req_pkt->gen_req_pkt.pt_req.cmd_pkt, req->cmd_pkt,
sizeof(struct tw_cl_command_packet));
} else
tw_cli_scsi_complete(req);
out:
req_pkt->tw_osl_callback(req->req_handle);
tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
}
/*
* Function name: tw_cli_scsi_complete
* Description: Completion routine for SCSI requests.
*
* Input: req -- ptr to CL internal request context
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_scsi_complete(struct tw_cli_req_context *req)
{
struct tw_cl_req_packet *req_pkt =
(struct tw_cl_req_packet *)(req->orig_req);
struct tw_cl_scsi_req_packet *scsi_req =
&(req_pkt->gen_req_pkt.scsi_req);
struct tw_cl_command_9k *cmd =
&(req->cmd_pkt->command.cmd_pkt_9k);
struct tw_cl_command_header *cmd_hdr;
TW_UINT16 error;
TW_UINT8 *cdb;
tw_cli_dbg_printf(8, req->ctlr->ctlr_handle, tw_osl_cur_func(),
"entered");
scsi_req->scsi_status = cmd->status;
if (! cmd->status)
return;
tw_cli_dbg_printf(1, req->ctlr->ctlr_handle, tw_osl_cur_func(),
"req_id = 0x%x, status = 0x%x",
GET_REQ_ID(cmd->lun_l4__req_id), cmd->status);
cmd_hdr = &(req->cmd_pkt->cmd_hdr);
error = cmd_hdr->status_block.error;
if ((error == TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) ||
(error == TWA_ERROR_UNIT_OFFLINE)) {
if (GET_LUN_L4(cmd->lun_l4__req_id))
req_pkt->status |= TW_CL_ERR_REQ_INVALID_LUN;
else
req_pkt->status |= TW_CL_ERR_REQ_INVALID_TARGET;
} else {
tw_cli_dbg_printf(2, req->ctlr->ctlr_handle,
tw_osl_cur_func(),
"cmd = %x %x %x %x %x %x %x",
GET_OPCODE(cmd->res__opcode),
GET_SGL_OFF(cmd->res__opcode),
cmd->unit,
cmd->lun_l4__req_id,
cmd->status,
cmd->sgl_offset,
cmd->lun_h4__sgl_entries);
cdb = (TW_UINT8 *)(cmd->cdb);
tw_cli_dbg_printf(2, req->ctlr->ctlr_handle,
tw_osl_cur_func(),
"cdb = %x %x %x %x %x %x %x %x "
"%x %x %x %x %x %x %x %x",
cdb[0], cdb[1], cdb[2], cdb[3],
cdb[4], cdb[5], cdb[6], cdb[7],
cdb[8], cdb[9], cdb[10], cdb[11],
cdb[12], cdb[13], cdb[14], cdb[15]);
#if 0
/*
* Print the error. Firmware doesn't yet support
* the 'Mode Sense' cmd. Don't print if the cmd
* is 'Mode Sense', and the error is 'Invalid field
* in CDB'.
*/
if (! ((cdb[0] == 0x1A) && (error == 0x10D)))
tw_cli_create_ctlr_event(req->ctlr,
TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
cmd_hdr);
#endif // 0
}
if (scsi_req->sense_data) {
tw_osl_memcpy(scsi_req->sense_data, cmd_hdr->sense_data,
TWA_SENSE_DATA_LENGTH);
scsi_req->sense_len = TWA_SENSE_DATA_LENGTH;
req_pkt->status |= TW_CL_ERR_REQ_AUTO_SENSE_VALID;
}
req_pkt->status |= TW_CL_ERR_REQ_SCSI_ERROR;
}
/*
* Function name: tw_cli_param_callback
* Description: Callback for get/set_param requests.
*
* Input: req -- ptr to completed request pkt
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_param_callback(struct tw_cli_req_context *req)
{
struct tw_cli_ctlr_context *ctlr = req->ctlr;
union tw_cl_command_7k *cmd =
&(req->cmd_pkt->command.cmd_pkt_7k);
TW_INT32 error;
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
/*
* If the request was never submitted to the controller, the function
* that sets req->error is responsible for calling tw_cl_create_event.
*/
if (! req->error_code)
if (cmd->param.status) {
#if 0
tw_cli_create_ctlr_event(ctlr,
TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
&(req->cmd_pkt->cmd_hdr));
#endif // 0
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1204, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"get/set_param failed",
"status = %d", cmd->param.status);
}
ctlr->internal_req_busy = TW_CL_FALSE;
tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
if ((ctlr->get_more_aens) && (!(ctlr->reset_in_progress))) {
ctlr->get_more_aens = TW_CL_FALSE;
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
"Fetching more AEN's");
if ((error = tw_cli_get_aen(ctlr)))
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1205, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Failed to fetch all AEN's from param_callback",
"error = %d", error);
}
}
/*
* Function name: tw_cli_aen_callback
* Description: Callback for requests to fetch AEN's.
*
* Input: req -- ptr to completed request pkt
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_aen_callback(struct tw_cli_req_context *req)
{
struct tw_cli_ctlr_context *ctlr = req->ctlr;
struct tw_cl_command_header *cmd_hdr;
struct tw_cl_command_9k *cmd =
&(req->cmd_pkt->command.cmd_pkt_9k);
TW_UINT16 aen_code = TWA_AEN_QUEUE_EMPTY;
TW_INT32 error;
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
"req_id = 0x%x, req error = %d, status = 0x%x",
GET_REQ_ID(cmd->lun_l4__req_id), req->error_code, cmd->status);
/*
* If the request was never submitted to the controller, the function
* that sets error is responsible for calling tw_cl_create_event.
*/
if (!(error = req->error_code))
if ((error = cmd->status)) {
cmd_hdr = (struct tw_cl_command_header *)
(&(req->cmd_pkt->cmd_hdr));
#if 0
tw_cli_create_ctlr_event(ctlr,
TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
cmd_hdr);
#endif // 0
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1206, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Request Sense failed",
"opcode = 0x%x, status = %d",
GET_OPCODE(cmd->res__opcode), cmd->status);
}
if (error) {
ctlr->internal_req_busy = TW_CL_FALSE;
tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
return;
}
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
"Request Sense command succeeded");
aen_code = tw_cli_manage_aen(ctlr, req);
if (aen_code != TWA_AEN_SYNC_TIME_WITH_HOST) {
ctlr->internal_req_busy = TW_CL_FALSE;
tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
if (aen_code != TWA_AEN_QUEUE_EMPTY)
if ((error = tw_cli_get_aen(ctlr)))
tw_cl_create_event(ctlr->ctlr_handle,
TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1207, 0x1,
TW_CL_SEVERITY_ERROR_STRING,
"Failed to fetch all AEN's",
"error = %d", error);
}
}
/*
* Function name: tw_cli_manage_aen
* Description: Handles AEN's.
*
* Input: ctlr -- ptr to CL internal ctlr context
* req -- ptr to CL internal request context
* Output: None
* Return value: None
*/
TW_UINT16
tw_cli_manage_aen(struct tw_cli_ctlr_context *ctlr,
struct tw_cli_req_context *req)
{
struct tw_cl_command_header *cmd_hdr;
TW_UINT16 aen_code;
TW_TIME local_time;
TW_TIME sync_time;
TW_UINT32 error;
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
cmd_hdr = (struct tw_cl_command_header *)(req->data);
aen_code = cmd_hdr->status_block.error;
switch (aen_code) {
case TWA_AEN_SYNC_TIME_WITH_HOST:
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
"Received AEN_SYNC_TIME");
/*
* Free the internal req pkt right here, since
* tw_cli_set_param will need it.
*/
ctlr->internal_req_busy = TW_CL_FALSE;
tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
/*
* We will use a callback in tw_cli_set_param only when
* interrupts are enabled and we can expect our callback
* to get called. Setting the get_more_aens
* flag will make the callback continue to try to retrieve
* more AEN's.
*/
if (ctlr->interrupts_enabled)
ctlr->get_more_aens = TW_CL_TRUE;
/* Calculate time (in seconds) since last Sunday 12.00 AM. */
local_time = tw_osl_get_local_time();
sync_time = (local_time - (3 * 86400)) % 604800;
if ((error = tw_cli_set_param(ctlr, TWA_PARAM_TIME_TABLE,
TWA_PARAM_TIME_SCHED_TIME, 4,
&sync_time,
(ctlr->interrupts_enabled)
? tw_cli_param_callback : TW_CL_NULL)))
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1208, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Unable to sync time with ctlr",
"error = %d", error);
break;
case TWA_AEN_QUEUE_EMPTY:
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
"AEN queue empty");
break;
default:
/* Queue the event. */
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
"Queueing AEN");
tw_cli_create_ctlr_event(ctlr,
TW_CL_MESSAGE_SOURCE_CONTROLLER_EVENT,
cmd_hdr);
break;
} /* switch */
return(aen_code);
}
/*
* Function name: tw_cli_enable_interrupts
* Description: Enables interrupts on the controller
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_enable_interrupts(struct tw_cli_ctlr_context *ctlr)
{
tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
ctlr->interrupts_enabled = TW_CL_TRUE;
TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT |
TWA_CONTROL_UNMASK_RESPONSE_INTERRUPT |
TWA_CONTROL_ENABLE_INTERRUPTS);
}
/*
* Function name: twa_setup
* Description: Disables interrupts on the controller
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_disable_interrupts(struct tw_cli_ctlr_context *ctlr)
{
tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
TWA_CONTROL_DISABLE_INTERRUPTS);
ctlr->interrupts_enabled = TW_CL_FALSE;
}

File diff suppressed because it is too large Load diff

View file

@ -1,104 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
*/
#ifndef TW_CL_IOCTL_H
#define TW_CL_IOCTL_H
/*
* Macros and structures for Common Layer handled ioctls.
*/
#define TW_CL_AEN_NOT_RETRIEVED 0x1
#define TW_CL_AEN_RETRIEVED 0x2
#define TW_CL_ERROR_AEN_NO_EVENTS 0x1003 /* No more events */
#define TW_CL_ERROR_AEN_OVERFLOW 0x1004 /* AEN overflow occurred */
#define TW_CL_ERROR_IOCTL_LOCK_NOT_HELD 0x1001 /* Not locked */
#define TW_CL_ERROR_IOCTL_LOCK_ALREADY_HELD 0x1002 /* Already locked */
#pragma pack(1)
/* Structure used to handle GET/RELEASE LOCK ioctls. */
struct tw_cl_lock_packet {
TW_UINT32 timeout_msec;
TW_UINT32 time_remaining_msec;
TW_UINT32 force_flag;
};
/* Structure used to handle GET COMPATIBILITY INFO ioctl. */
struct tw_cl_compatibility_packet {
TW_UINT8 driver_version[32];/* driver version */
TW_UINT16 working_srl; /* driver & firmware negotiated srl */
TW_UINT16 working_branch; /* branch # of the firmware that the
driver is compatible with */
TW_UINT16 working_build; /* build # of the firmware that the
driver is compatible with */
TW_UINT16 driver_srl_high;/* highest driver supported srl */
TW_UINT16 driver_branch_high;/* highest driver supported branch */
TW_UINT16 driver_build_high;/* highest driver supported build */
TW_UINT16 driver_srl_low;/* lowest driver supported srl */
TW_UINT16 driver_branch_low;/* lowest driver supported branch */
TW_UINT16 driver_build_low;/* lowest driver supported build */
TW_UINT16 fw_on_ctlr_srl; /* srl of running firmware */
TW_UINT16 fw_on_ctlr_branch;/* branch # of running firmware */
TW_UINT16 fw_on_ctlr_build;/* build # of running firmware */
};
/* Driver understandable part of the ioctl packet built by the API. */
struct tw_cl_driver_packet {
TW_UINT32 control_code;
TW_UINT32 status;
TW_UINT32 unique_id;
TW_UINT32 sequence_id;
TW_UINT32 os_status;
TW_UINT32 buffer_length;
};
/* ioctl packet built by the API. */
struct tw_cl_ioctl_packet {
struct tw_cl_driver_packet driver_pkt;
TW_INT8 padding[488];
struct tw_cl_command_packet cmd_pkt;
TW_INT8 data_buf[1];
};
#pragma pack()
#endif /* TW_CL_IOCTL_H */

View file

@ -1,991 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
* Modifications by: Manjunath Ranganathaiah
*/
/*
* Common Layer miscellaneous functions.
*/
#include "tw_osl_share.h"
#include "tw_cl_share.h"
#include "tw_cl_fwif.h"
#include "tw_cl_ioctl.h"
#include "tw_cl.h"
#include "tw_cl_externs.h"
#include "tw_osl_ioctl.h"
/* AEN severity table. */
TW_INT8 *tw_cli_severity_string_table[] = {
"None",
TW_CL_SEVERITY_ERROR_STRING,
TW_CL_SEVERITY_WARNING_STRING,
TW_CL_SEVERITY_INFO_STRING,
TW_CL_SEVERITY_DEBUG_STRING,
""
};
/*
* Function name: tw_cli_drain_complete_queue
* Description: This function gets called during a controller reset.
* It errors back to the OS Layer, all those requests that
* are in the complete queue, at the time of the reset.
* Any CL internal requests will be simply freed.
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_drain_complete_queue(struct tw_cli_ctlr_context *ctlr)
{
struct tw_cli_req_context *req;
struct tw_cl_req_packet *req_pkt;
tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
/* Walk the busy queue. */
while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_COMPLETE_Q)) !=
TW_CL_NULL) {
if (req->flags & TW_CLI_REQ_FLAGS_INTERNAL) {
/*
* It's an internal request. Set the appropriate
* error and call the CL internal callback if there's
* one. If the request originator is polling for
* completion, he should be checking req->error to
* determine that the request did not go through.
* The request originators are responsible for the
* clean-up.
*/
req->error_code = TW_CL_ERR_REQ_BUS_RESET;
if (req->tw_cli_callback)
req->tw_cli_callback(req);
} else if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
/* It's a passthru request. Complete it. */
if ((req_pkt = req->orig_req) != TW_CL_NULL) {
req_pkt->status = TW_CL_ERR_REQ_BUS_RESET;
if (req_pkt->tw_osl_callback)
req_pkt->tw_osl_callback(req->req_handle);
}
tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
} else {
/* It's an external (SCSI) request. Add it to the reset queue. */
tw_osl_untimeout(req->req_handle);
tw_cli_req_q_insert_tail(req, TW_CLI_RESET_Q);
}
} /* End of while loop */
}
/*
* Function name: tw_cli_drain_busy_queue
* Description: This function gets called during a controller reset.
* It errors back to the OS Layer, all those requests that
* were pending with the firmware, at the time of the
* reset.
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_drain_busy_queue(struct tw_cli_ctlr_context *ctlr)
{
struct tw_cli_req_context *req;
struct tw_cl_req_packet *req_pkt;
tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
/* Walk the busy queue. */
while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_BUSY_Q)) !=
TW_CL_NULL) {
if (req->flags & TW_CLI_REQ_FLAGS_INTERNAL) {
/*
* It's an internal request. Set the appropriate
* error and call the CL internal callback if there's
* one. If the request originator is polling for
* completion, he should be checking req->error to
* determine that the request did not go through.
* The request originators are responsible for the
* clean-up.
*/
req->error_code = TW_CL_ERR_REQ_BUS_RESET;
if (req->tw_cli_callback)
req->tw_cli_callback(req);
} else if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
/* It's a passthru request. Complete it. */
if ((req_pkt = req->orig_req) != TW_CL_NULL) {
req_pkt->status = TW_CL_ERR_REQ_BUS_RESET;
if (req_pkt->tw_osl_callback)
req_pkt->tw_osl_callback(req->req_handle);
}
tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
} else {
/* It's an external (SCSI) request. Add it to the reset queue. */
tw_osl_untimeout(req->req_handle);
tw_cli_req_q_insert_tail(req, TW_CLI_RESET_Q);
}
} /* End of while loop */
}
/*
* Function name: tw_cli_drain_pending_queue
* Description: This function gets called during a controller reset.
* It errors back to the OS Layer, all those requests that
* were in the pending queue, at the time of the reset.
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_drain_pending_queue(struct tw_cli_ctlr_context *ctlr)
{
struct tw_cli_req_context *req;
struct tw_cl_req_packet *req_pkt;
tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
/*
* Pull requests off the pending queue, and complete them.
*/
while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_PENDING_Q)) !=
TW_CL_NULL) {
if (req->flags & TW_CLI_REQ_FLAGS_INTERNAL) {
/*
* It's an internal request. Set the appropriate
* error and call the CL internal callback if there's
* one. If the request originator is polling for
* completion, he should be checking req->error to
* determine that the request did not go through.
* The request originators are responsible for the
* clean-up.
*/
req->error_code = TW_CL_ERR_REQ_BUS_RESET;
if (req->tw_cli_callback)
req->tw_cli_callback(req);
} else if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
/* It's a passthru request. Complete it. */
if ((req_pkt = req->orig_req) != TW_CL_NULL) {
req_pkt->status = TW_CL_ERR_REQ_BUS_RESET;
if (req_pkt->tw_osl_callback)
req_pkt->tw_osl_callback(req->req_handle);
}
tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
} else {
/* It's an external (SCSI) request. Add it to the reset queue. */
tw_osl_untimeout(req->req_handle);
tw_cli_req_q_insert_tail(req, TW_CLI_RESET_Q);
}
} /* End of while loop */
}
/*
* Function name: tw_cli_drain_response_queue
* Description: Drain the controller response queue.
*
* Input: ctlr -- ptr to per ctlr structure
* Output: None
* Return value: 0 -- success
* non-zero-- failure
*/
TW_INT32
tw_cli_drain_response_queue(struct tw_cli_ctlr_context *ctlr)
{
TW_UINT32 resp;
TW_UINT32 status_reg;
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
for (;;) {
status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
return(TW_OSL_ESUCCESS); /* no more response queue entries */
resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle);
}
}
/*
* Function name: tw_cli_find_response
* Description: Find a particular response in the ctlr response queue.
*
* Input: ctlr -- ptr to per ctlr structure
* req_id -- request id of the response to look for
* Output: None
* Return value: 0 -- success
* non-zero-- failure
*/
TW_INT32
tw_cli_find_response(struct tw_cli_ctlr_context *ctlr, TW_INT32 req_id)
{
TW_UINT32 resp;
TW_INT32 resp_id;
TW_UINT32 status_reg;
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
for (;;) {
status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
return(TW_OSL_ENOTTY); /* no more response queue entries */
if (ctlr->device_id == TW_CL_DEVICE_ID_9K) {
resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle);
resp_id = GET_RESP_ID(resp);
} else {
resp = TW_CLI_READ_LARGE_RESPONSE_QUEUE(
ctlr->ctlr_handle);
resp_id = GET_LARGE_RESP_ID(resp);
}
if (resp_id == req_id)
return(TW_OSL_ESUCCESS); /* found the req_id */
}
}
/*
* Function name: tw_cli_drain_aen_queue
* Description: Fetches all un-retrieved AEN's posted by fw.
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
* Return value: 0 -- success
* non-zero-- failure
*/
TW_INT32
tw_cli_drain_aen_queue(struct tw_cli_ctlr_context *ctlr)
{
struct tw_cli_req_context *req;
struct tw_cl_command_header *cmd_hdr;
TW_TIME end_time;
TW_UINT16 aen_code;
TW_INT32 error;
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
for (;;) {
if ((req = tw_cli_get_request(ctlr
)) == TW_CL_NULL) {
error = TW_OSL_EBUSY;
break;
}
req->flags |= TW_CLI_REQ_FLAGS_INTERNAL;
req->tw_cli_callback = TW_CL_NULL;
if ((error = tw_cli_send_scsi_cmd(req,
0x03 /* REQUEST_SENSE */))) {
tw_cli_dbg_printf(1, ctlr->ctlr_handle,
tw_osl_cur_func(),
"Cannot send command to fetch aen");
break;
}
end_time = tw_osl_get_local_time() +
TW_CLI_REQUEST_TIMEOUT_PERIOD;
do {
if ((error = req->error_code))
/*
* This will take care of completion due to
* a reset, or a failure in
* tw_cli_submit_pending_queue.
*/
goto out;
tw_cli_process_resp_intr(req->ctlr);
if ((req->state != TW_CLI_REQ_STATE_BUSY) &&
(req->state != TW_CLI_REQ_STATE_PENDING))
break;
} while (tw_osl_get_local_time() <= end_time);
if (req->state != TW_CLI_REQ_STATE_COMPLETE) {
error = TW_OSL_ETIMEDOUT;
break;
}
if ((error = req->cmd_pkt->command.cmd_pkt_9k.status)) {
cmd_hdr = &req->cmd_pkt->cmd_hdr;
#if 0
tw_cli_create_ctlr_event(ctlr,
TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
cmd_hdr);
#endif // 0
break;
}
aen_code = tw_cli_manage_aen(ctlr, req);
if (aen_code == TWA_AEN_QUEUE_EMPTY)
break;
if (aen_code == TWA_AEN_SYNC_TIME_WITH_HOST)
continue;
ctlr->internal_req_busy = TW_CL_FALSE;
tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
}
out:
if (req) {
if (req->data)
ctlr->internal_req_busy = TW_CL_FALSE;
tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
}
return(error);
}
/*
* Function name: tw_cli_find_aen
* Description: Reports whether a given AEN ever occurred.
*
* Input: ctlr -- ptr to CL internal ctlr context
* aen_code-- AEN to look for
* Output: None
* Return value: 0 -- success
* non-zero-- failure
*/
TW_INT32
tw_cli_find_aen(struct tw_cli_ctlr_context *ctlr, TW_UINT16 aen_code)
{
TW_UINT32 last_index;
TW_INT32 i;
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
if (ctlr->aen_q_wrapped)
last_index = ctlr->aen_head;
else
last_index = 0;
i = ctlr->aen_head;
do {
i = (i + ctlr->max_aens_supported - 1) %
ctlr->max_aens_supported;
if (ctlr->aen_queue[i].aen_code == aen_code)
return(TW_OSL_ESUCCESS);
} while (i != last_index);
return(TW_OSL_EGENFAILURE);
}
/*
* Function name: tw_cli_poll_status
* Description: Poll for a given status to show up in the firmware
* status register.
*
* Input: ctlr -- ptr to CL internal ctlr context
* status -- status to look for
* timeout -- max # of seconds to wait before giving up
* Output: None
* Return value: 0 -- success
* non-zero-- failure
*/
TW_INT32
tw_cli_poll_status(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status,
TW_UINT32 timeout)
{
TW_TIME end_time;
TW_UINT32 status_reg;
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
end_time = tw_osl_get_local_time() + timeout;
do {
status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
if ((status_reg & status) == status)
/* got the required bit(s) */
return(TW_OSL_ESUCCESS);
tw_osl_delay(1000);
} while (tw_osl_get_local_time() <= end_time);
return(TW_OSL_ETIMEDOUT);
}
/*
* Function name: tw_cl_create_event
* Description: Creates and queues ctlr/CL/OSL AEN's to be
* supplied to user-space tools on request.
* Also notifies OS Layer.
* Input: ctlr -- ptr to CL internal ctlr context
* queue_event-- TW_CL_TRUE --> queue event;
* TW_CL_FALSE--> don't queue event
* (simply notify OSL)
* event_src -- source of event
* event_code -- AEN/error code
* severity -- severity of event
* severity_str--Text description of severity
* event_desc -- standard string related to the event/error
* event_specific_desc -- format string for additional
* info about the event
* ... -- additional arguments conforming to the format
* specified by event_specific_desc
* Output: None
* Return value: None
*/
TW_VOID
tw_cl_create_event(struct tw_cl_ctlr_handle *ctlr_handle,
TW_UINT8 queue_event, TW_UINT8 event_src, TW_UINT16 event_code,
TW_UINT8 severity, TW_UINT8 *severity_str, TW_UINT8 *event_desc,
TW_UINT8 *event_specific_desc, ...)
{
struct tw_cli_ctlr_context *ctlr = ctlr_handle->cl_ctlr_ctxt;
struct tw_cl_event_packet event_pkt;
struct tw_cl_event_packet *event;
TW_UINT32 aen_head;
va_list ap;
tw_cli_dbg_printf(8, ctlr_handle, tw_osl_cur_func(), "entered");
if ((ctlr) && (queue_event)) {
/* Protect access to ctlr->aen_head. */
tw_osl_get_lock(ctlr_handle, ctlr->gen_lock);
aen_head = ctlr->aen_head;
ctlr->aen_head = (aen_head + 1) % ctlr->max_aens_supported;
/* Queue the event. */
event = &(ctlr->aen_queue[aen_head]);
tw_osl_memzero(event->parameter_data,
sizeof(event->parameter_data));
if (event->retrieved == TW_CL_AEN_NOT_RETRIEVED)
ctlr->aen_q_overflow = TW_CL_TRUE;
event->sequence_id = ++(ctlr->aen_cur_seq_id);
if ((aen_head + 1) == ctlr->max_aens_supported) {
tw_cli_dbg_printf(4, ctlr->ctlr_handle,
tw_osl_cur_func(), "AEN queue wrapped");
ctlr->aen_q_wrapped = TW_CL_TRUE;
}
/* Free access to ctlr->aen_head. */
tw_osl_free_lock(ctlr_handle, ctlr->gen_lock);
} else {
event = &event_pkt;
tw_osl_memzero(event, sizeof(struct tw_cl_event_packet));
}
event->event_src = event_src;
event->time_stamp_sec = (TW_UINT32)tw_osl_get_local_time();
event->aen_code = event_code;
event->severity = severity;
tw_osl_strcpy(event->severity_str, severity_str);
event->retrieved = TW_CL_AEN_NOT_RETRIEVED;
va_start(ap, event_specific_desc);
tw_osl_vsprintf(event->parameter_data, event_specific_desc, ap);
va_end(ap);
event->parameter_len =
(TW_UINT8)(tw_osl_strlen(event->parameter_data));
tw_osl_strcpy(event->parameter_data + event->parameter_len + 1,
event_desc);
event->parameter_len += (1 + tw_osl_strlen(event_desc));
tw_cli_dbg_printf(4, ctlr_handle, tw_osl_cur_func(),
"event = %x %x %x %x %x %x %x\n %s",
event->sequence_id,
event->time_stamp_sec,
event->aen_code,
event->severity,
event->retrieved,
event->repeat_count,
event->parameter_len,
event->parameter_data);
tw_osl_notify_event(ctlr_handle, event);
}
/*
* Function name: tw_cli_get_request
* Description: Gets a request pkt from the free queue.
*
* Input: ctlr -- ptr to CL internal ctlr context
* req_pkt -- ptr to OSL built req_pkt, if there's one
* Output: None
* Return value: ptr to request pkt -- success
* TW_CL_NULL -- failure
*/
struct tw_cli_req_context *
tw_cli_get_request(struct tw_cli_ctlr_context *ctlr
)
{
struct tw_cli_req_context *req;
tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
{
/* Get a free request packet. */
req = tw_cli_req_q_remove_head(ctlr, TW_CLI_FREE_Q);
}
/* Initialize some fields to their defaults. */
if (req) {
req->req_handle = TW_CL_NULL;
req->data = TW_CL_NULL;
req->length = 0;
req->data_phys = 0;
req->state = TW_CLI_REQ_STATE_INIT; /* req being initialized */
req->flags = 0;
req->error_code = 0;
req->orig_req = TW_CL_NULL;
req->tw_cli_callback = TW_CL_NULL;
/*
* Look at the status field in the command packet to see how
* it completed the last time it was used, and zero out only
* the portions that might have changed. Note that we don't
* care to zero out the sglist.
*/
if (req->cmd_pkt->command.cmd_pkt_9k.status)
tw_osl_memzero(req->cmd_pkt,
sizeof(struct tw_cl_command_header) +
28 /* max bytes before sglist */);
else
tw_osl_memzero(&(req->cmd_pkt->command),
28 /* max bytes before sglist */);
}
return(req);
}
/*
* Function name: tw_cli_dbg_printf
* Description: Calls OSL print function if dbg_level is appropriate
*
* Input: dbg_level -- Determines whether or not to print
* ctlr_handle -- controller handle
* cur_func -- text name of calling function
* fmt -- format string for the arguments to follow
* ... -- variable number of arguments, to be printed
* based on the fmt string
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_dbg_printf(TW_UINT8 dbg_level,
struct tw_cl_ctlr_handle *ctlr_handle, const TW_INT8 *cur_func,
TW_INT8 *fmt, ...)
{
#ifdef TW_OSL_DEBUG
TW_INT8 print_str[256];
va_list ap;
tw_osl_memzero(print_str, 256);
if (dbg_level <= TW_OSL_DEBUG_LEVEL_FOR_CL) {
tw_osl_sprintf(print_str, "%s: ", cur_func);
va_start(ap, fmt);
tw_osl_vsprintf(print_str + tw_osl_strlen(print_str), fmt, ap);
va_end(ap);
tw_osl_strcpy(print_str + tw_osl_strlen(print_str), "\n");
tw_osl_dbg_printf(ctlr_handle, "%s", print_str);
}
#endif /* TW_OSL_DEBUG */
}
/*
* Function name: tw_cli_notify_ctlr_info
* Description: Notify OSL of controller info (fw/BIOS versions, etc.).
*
* Input: ctlr -- ptr to CL internal ctlr context
* Output: None
* Return value: None
*/
TW_VOID
tw_cli_notify_ctlr_info(struct tw_cli_ctlr_context *ctlr)
{
TW_INT8 fw_ver[16];
TW_INT8 bios_ver[16];
TW_INT8 ctlr_model[16];
TW_INT32 error[3];
TW_UINT8 num_ports = 0;
tw_cli_dbg_printf(5, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
/* Get the port count. */
error[0] = tw_cli_get_param(ctlr, TWA_PARAM_CONTROLLER_TABLE,
TWA_PARAM_CONTROLLER_PORT_COUNT, &num_ports,
1, TW_CL_NULL);
/* Get the firmware and BIOS versions. */
error[0] = tw_cli_get_param(ctlr, TWA_PARAM_VERSION_TABLE,
TWA_PARAM_VERSION_FW, fw_ver, 16, TW_CL_NULL);
error[1] = tw_cli_get_param(ctlr, TWA_PARAM_VERSION_TABLE,
TWA_PARAM_VERSION_BIOS, bios_ver, 16, TW_CL_NULL);
error[2] = tw_cli_get_param(ctlr, TWA_PARAM_VERSION_TABLE,
TWA_PARAM_CTLR_MODEL, ctlr_model, 16, TW_CL_NULL);
tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
0x1300, 0x3, TW_CL_SEVERITY_INFO_STRING,
"Controller details:",
"Model %.16s, %d ports, Firmware %.16s, BIOS %.16s",
error[2]?(TW_INT8 *)TW_CL_NULL:ctlr_model,
num_ports,
error[0]?(TW_INT8 *)TW_CL_NULL:fw_ver,
error[1]?(TW_INT8 *)TW_CL_NULL:bios_ver);
}
/*
* Function name: tw_cli_check_ctlr_state
* Description: Makes sure that the fw status register reports a
* proper status.
*
* Input: ctlr -- ptr to CL internal ctlr context
* status_reg-- value in the status register
* Output: None
* Return value: 0 -- no errors
* non-zero-- errors
*/
TW_INT32
tw_cli_check_ctlr_state(struct tw_cli_ctlr_context *ctlr, TW_UINT32 status_reg)
{
struct tw_cl_ctlr_handle *ctlr_handle = ctlr->ctlr_handle;
TW_INT32 error = TW_OSL_ESUCCESS;
tw_cli_dbg_printf(8, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
/* Check if the 'micro-controller ready' bit is not set. */
if (!(status_reg & TWA_STATUS_MICROCONTROLLER_READY)) {
TW_INT8 desc[200];
tw_osl_memzero(desc, 200);
if (!(ctlr->reset_phase1_in_progress)) {
tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
0x1301, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Missing expected status bit(s)",
"status reg = 0x%x; Missing bits: %s",
status_reg,
tw_cli_describe_bits(
TWA_STATUS_MICROCONTROLLER_READY,
desc));
error = TW_OSL_EGENFAILURE;
}
}
/* Check if any error bits are set. */
if ((status_reg & TWA_STATUS_UNEXPECTED_BITS) != 0) {
TW_INT8 desc[200];
tw_osl_memzero(desc, 200);
/* Skip queue error msgs during 9650SE/9690SA reset */
if (((ctlr->device_id != TW_CL_DEVICE_ID_9K_E) &&
(ctlr->device_id != TW_CL_DEVICE_ID_9K_SA)) ||
(!(ctlr->reset_in_progress)) ||
((status_reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT) == 0))
tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
0x1302, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Unexpected status bit(s)",
"status reg = 0x%x Unexpected bits: %s",
status_reg & TWA_STATUS_UNEXPECTED_BITS,
tw_cli_describe_bits(status_reg &
TWA_STATUS_UNEXPECTED_BITS, desc));
if (status_reg & TWA_STATUS_PCI_PARITY_ERROR_INTERRUPT) {
tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
0x1303, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"PCI parity error: clearing... "
"Re-seat/move/replace card",
"status reg = 0x%x %s",
status_reg,
tw_cli_describe_bits(status_reg, desc));
TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
TWA_CONTROL_CLEAR_PARITY_ERROR);
#ifdef TW_OSL_PCI_CONFIG_ACCESSIBLE
tw_osl_write_pci_config(ctlr->ctlr_handle,
TW_CLI_PCI_CONFIG_STATUS_OFFSET,
TWA_PCI_CONFIG_CLEAR_PARITY_ERROR, 2);
#endif /* TW_OSL_PCI_CONFIG_ACCESSIBLE */
}
if (status_reg & TWA_STATUS_PCI_ABORT_INTERRUPT) {
tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
0x1304, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"PCI abort: clearing... ",
"status reg = 0x%x %s",
status_reg,
tw_cli_describe_bits(status_reg, desc));
TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
TWA_CONTROL_CLEAR_PCI_ABORT);
#ifdef TW_OSL_PCI_CONFIG_ACCESSIBLE
tw_osl_write_pci_config(ctlr->ctlr_handle,
TW_CLI_PCI_CONFIG_STATUS_OFFSET,
TWA_PCI_CONFIG_CLEAR_PCI_ABORT, 2);
#endif /* TW_OSL_PCI_CONFIG_ACCESSIBLE */
}
if (status_reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT) {
/* Skip queue error msgs during 9650SE/9690SA reset */
if (((ctlr->device_id != TW_CL_DEVICE_ID_9K_E) &&
(ctlr->device_id != TW_CL_DEVICE_ID_9K_SA)) ||
(!(ctlr->reset_in_progress)))
tw_cl_create_event(ctlr_handle, TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT,
0x1305, 0x1, TW_CL_SEVERITY_ERROR_STRING,
"Controller queue error: clearing... ",
"status reg = 0x%x %s",
status_reg,
tw_cli_describe_bits(status_reg, desc));
TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
TWA_CONTROL_CLEAR_QUEUE_ERROR);
}
}
return(error);
}
/*
* Function name: tw_cli_describe_bits
* Description: Given the value of the status register, returns a
* string describing the meaning of each set bit.
*
* Input: reg -- status register value
* Output: Pointer to a string describing each set bit
* Return value: Pointer to the string describing each set bit
*/
TW_INT8 *
tw_cli_describe_bits(TW_UINT32 reg, TW_INT8 *str)
{
tw_osl_strcpy(str, "[");
if (reg & TWA_STATUS_COMMAND_QUEUE_EMPTY)
tw_osl_strcpy(&str[tw_osl_strlen(str)], "CMD_Q_EMPTY,");
if (reg & TWA_STATUS_MICROCONTROLLER_READY)
tw_osl_strcpy(&str[tw_osl_strlen(str)], "MC_RDY,");
if (reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY)
tw_osl_strcpy(&str[tw_osl_strlen(str)], "RESP_Q_EMPTY,");
if (reg & TWA_STATUS_COMMAND_QUEUE_FULL)
tw_osl_strcpy(&str[tw_osl_strlen(str)], "CMD_Q_FULL,");
if (reg & TWA_STATUS_RESPONSE_INTERRUPT)
tw_osl_strcpy(&str[tw_osl_strlen(str)], "RESP_INTR,");
if (reg & TWA_STATUS_COMMAND_INTERRUPT)
tw_osl_strcpy(&str[tw_osl_strlen(str)], "CMD_INTR,");
if (reg & TWA_STATUS_ATTENTION_INTERRUPT)
tw_osl_strcpy(&str[tw_osl_strlen(str)], "ATTN_INTR,");
if (reg & TWA_STATUS_HOST_INTERRUPT)
tw_osl_strcpy(&str[tw_osl_strlen(str)], "HOST_INTR,");
if (reg & TWA_STATUS_PCI_ABORT_INTERRUPT)
tw_osl_strcpy(&str[tw_osl_strlen(str)], "PCI_ABRT,");
if (reg & TWA_STATUS_QUEUE_ERROR_INTERRUPT)
tw_osl_strcpy(&str[tw_osl_strlen(str)], "Q_ERR,");
if (reg & TWA_STATUS_PCI_PARITY_ERROR_INTERRUPT)
tw_osl_strcpy(&str[tw_osl_strlen(str)], "PCI_PERR");
tw_osl_strcpy(&str[tw_osl_strlen(str)], "]");
return(str);
}
#ifdef TW_OSL_DEBUG
/*
* Function name: tw_cl_print_ctlr_stats
* Description: Prints the current status of the controller.
*
* Input: ctlr_handle-- controller handle
* Output: None
* Return value: None
*/
TW_VOID
tw_cl_print_ctlr_stats(struct tw_cl_ctlr_handle *ctlr_handle)
{
struct tw_cli_ctlr_context *ctlr =
(struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
TW_UINT32 status_reg;
TW_INT8 desc[200];
tw_cli_dbg_printf(7, ctlr->ctlr_handle, "", "entered");
/* Print current controller details. */
tw_cli_dbg_printf(0, ctlr_handle, "", "cl_ctlr_ctxt = %p", ctlr);
tw_osl_memzero(desc, 200);
status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
tw_cli_dbg_printf(0, ctlr_handle, "", "status reg = 0x%x %s",
status_reg, tw_cli_describe_bits(status_reg, desc));
tw_cli_dbg_printf(0, ctlr_handle, "", "CLq type current max");
tw_cli_dbg_printf(0, ctlr_handle, "", "free %04d %04d",
ctlr->q_stats[TW_CLI_FREE_Q].cur_len,
ctlr->q_stats[TW_CLI_FREE_Q].max_len);
tw_cli_dbg_printf(0, ctlr_handle, "", "busy %04d %04d",
ctlr->q_stats[TW_CLI_BUSY_Q].cur_len,
ctlr->q_stats[TW_CLI_BUSY_Q].max_len);
tw_cli_dbg_printf(0, ctlr_handle, "", "pending %04d %04d",
ctlr->q_stats[TW_CLI_PENDING_Q].cur_len,
ctlr->q_stats[TW_CLI_PENDING_Q].max_len);
tw_cli_dbg_printf(0, ctlr_handle, "", "complete %04d %04d",
ctlr->q_stats[TW_CLI_COMPLETE_Q].cur_len,
ctlr->q_stats[TW_CLI_COMPLETE_Q].max_len);
tw_cli_dbg_printf(0, ctlr_handle, "", "AEN queue head %d tail %d",
ctlr->aen_head, ctlr->aen_tail);
}
/*
* Function name: tw_cl_reset_stats
* Description: Resets CL maintained statistics for the controller.
*
* Input: ctlr_handle-- controller handle
* Output: None
* Return value: None
*/
TW_VOID
tw_cl_reset_stats(struct tw_cl_ctlr_handle *ctlr_handle)
{
struct tw_cli_ctlr_context *ctlr =
(struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
tw_cli_dbg_printf(7, ctlr_handle, tw_osl_cur_func(), "entered");
ctlr->q_stats[TW_CLI_FREE_Q].max_len = 0;
ctlr->q_stats[TW_CLI_BUSY_Q].max_len = 0;
ctlr->q_stats[TW_CLI_PENDING_Q].max_len = 0;
ctlr->q_stats[TW_CLI_COMPLETE_Q].max_len = 0;
}
/*
* Function name: tw_cli_print_req_info
* Description: Prints CL internal details of a given request.
*
* Input: req -- ptr to CL internal request context
* Output: None
* Return value: None
*/
TW_VOID
tw_cl_print_req_info(struct tw_cl_req_handle *req_handle)
{
struct tw_cli_req_context *req = req_handle->cl_req_ctxt;
struct tw_cli_ctlr_context *ctlr = req->ctlr;
struct tw_cl_ctlr_handle *ctlr_handle = ctlr->ctlr_handle;
struct tw_cl_command_packet *cmd_pkt = req->cmd_pkt;
struct tw_cl_command_9k *cmd9k;
union tw_cl_command_7k *cmd7k;
TW_UINT8 *cdb;
TW_VOID *sgl;
TW_UINT32 sgl_entries;
TW_UINT32 i;
tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
"CL details for request:");
tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
"req_handle = %p, ctlr = %p,\n"
"cmd_pkt = %p, cmd_pkt_phys = 0x%llx,\n"
"data = %p, length = 0x%x, data_phys = 0x%llx,\n"
"state = 0x%x, flags = 0x%x, error = 0x%x,\n"
"orig_req = %p, callback = %p, req_id = 0x%x,\n"
"next_req = %p, prev_req = %p",
req_handle, ctlr,
cmd_pkt, req->cmd_pkt_phys,
req->data, req->length, req->data_phys,
req->state, req->flags, req->error_code,
req->orig_req, req->tw_cli_callback, req->request_id,
req->link.next, req->link.prev);
if (req->flags & TW_CLI_REQ_FLAGS_9K) {
cmd9k = &(cmd_pkt->command.cmd_pkt_9k);
sgl = cmd9k->sg_list;
sgl_entries = TW_CL_SWAP16(
GET_SGL_ENTRIES(cmd9k->lun_h4__sgl_entries));
tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
"9K cmd: opcode = 0x%x, unit = 0x%x, req_id = 0x%x,\n"
"status = 0x%x, sgl_offset = 0x%x, sgl_entries = 0x%x",
GET_OPCODE(cmd9k->res__opcode),
cmd9k->unit,
TW_CL_SWAP16(GET_REQ_ID(cmd9k->lun_l4__req_id)),
cmd9k->status,
cmd9k->sgl_offset,
sgl_entries);
cdb = (TW_UINT8 *)(cmd9k->cdb);
tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
"CDB: %x %x %x %x %x %x %x %x"
"%x %x %x %x %x %x %x %x",
cdb[0], cdb[1], cdb[2], cdb[3],
cdb[4], cdb[5], cdb[6], cdb[7],
cdb[8], cdb[9], cdb[10], cdb[11],
cdb[12], cdb[13], cdb[14], cdb[15]);
} else {
cmd7k = &(cmd_pkt->command.cmd_pkt_7k);
sgl = cmd7k->param.sgl;
sgl_entries = (cmd7k->generic.size -
GET_SGL_OFF(cmd7k->generic.sgl_off__opcode)) /
((ctlr->flags & TW_CL_64BIT_ADDRESSES) ? 3 : 2);
tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
"7K cmd: opcode = 0x%x, sgl_offset = 0x%x,\n"
"size = 0x%x, req_id = 0x%x, unit = 0x%x,\n"
"status = 0x%x, flags = 0x%x, count = 0x%x",
GET_OPCODE(cmd7k->generic.sgl_off__opcode),
GET_SGL_OFF(cmd7k->generic.sgl_off__opcode),
cmd7k->generic.size,
TW_CL_SWAP16(cmd7k->generic.request_id),
GET_UNIT(cmd7k->generic.host_id__unit),
cmd7k->generic.status,
cmd7k->generic.flags,
TW_CL_SWAP16(cmd7k->generic.count));
}
tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(), "SG entries:");
if (ctlr->flags & TW_CL_64BIT_ADDRESSES) {
struct tw_cl_sg_desc64 *sgl64 = (struct tw_cl_sg_desc64 *)sgl;
for (i = 0; i < sgl_entries; i++) {
tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
"0x%llx 0x%x",
sgl64[i].address, sgl64[i].length);
}
} else {
struct tw_cl_sg_desc32 *sgl32 = (struct tw_cl_sg_desc32 *)sgl;
for (i = 0; i < sgl_entries; i++) {
tw_cli_dbg_printf(0, ctlr_handle, tw_osl_cur_func(),
"0x%x 0x%x",
sgl32[i].address, sgl32[i].length);
}
}
}
#endif /* TW_OSL_DEBUG */

View file

@ -1,535 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
* Modifications by: Manjunath Ranganathaiah
*/
#ifndef TW_CL_SHARE_H
#define TW_CL_SHARE_H
/*
* Macros, structures and functions shared between OSL and CL,
* and defined by CL.
*/
#define TW_CL_NULL ((TW_VOID *)0)
#define TW_CL_TRUE 1
#define TW_CL_FALSE 0
#define TW_CL_VENDOR_ID 0x13C1 /* 3ware vendor id */
#define TW_CL_DEVICE_ID_9K 0x1002 /* 9000 PCI series device id */
#define TW_CL_DEVICE_ID_9K_X 0x1003 /* 9000 PCI-X series device id */
#define TW_CL_DEVICE_ID_9K_E 0x1004 /* 9000 PCIe series device id */
#define TW_CL_DEVICE_ID_9K_SA 0x1005 /* 9000 PCIe SAS series device id */
#define TW_CL_BAR_TYPE_IO 1 /* I/O base address */
#define TW_CL_BAR_TYPE_MEM 2 /* memory base address */
#define TW_CL_BAR_TYPE_SBUF 3 /* SBUF base address */
#ifdef TW_OSL_ENCLOSURE_SUPPORT
#define TW_CL_MAX_NUM_UNITS 65 /* max # of units we support
-- enclosure target id is 64 */
#else /* TW_OSL_ENCLOSURE_SUPPORT */
#define TW_CL_MAX_NUM_UNITS 32 /* max # of units we support */
#endif /* TW_OSL_ENCLOSURE_SUPPORT */
#define TW_CL_MAX_NUM_LUNS 255 /* max # of LUN's we support */
#define TW_CL_MAX_IO_SIZE 0x20000 /* 128K */
/*
* Though we can support 256 simultaneous requests, we advertise as capable
* of supporting only 255, since we want to keep one CL internal request
* context packet always available for internal requests.
*/
#define TW_CL_MAX_SIMULTANEOUS_REQUESTS 256 /* max simult reqs supported */
#define TW_CL_MAX_32BIT_SG_ELEMENTS 109 /* max 32-bit sg elements */
#define TW_CL_MAX_64BIT_SG_ELEMENTS 72 /* max 64-bit sg elements */
/* Possible values of ctlr->flags */
#define TW_CL_64BIT_ADDRESSES (1<<0) /* 64 bit cmdpkt & SG addresses */
#define TW_CL_64BIT_SG_LENGTH (1<<1) /* 64 bit SG length */
#define TW_CL_START_CTLR_ONLY (1<<2) /* Start ctlr only */
#define TW_CL_STOP_CTLR_ONLY (1<<3) /* Stop ctlr only */
#define TW_CL_DEFERRED_INTR_USED (1<<5) /* OS Layer uses deferred intr */
/* Possible error values from the Common Layer. */
#define TW_CL_ERR_REQ_SUCCESS 0
#define TW_CL_ERR_REQ_GENERAL_FAILURE (1<<0)
#define TW_CL_ERR_REQ_INVALID_TARGET (1<<1)
#define TW_CL_ERR_REQ_INVALID_LUN (1<<2)
#define TW_CL_ERR_REQ_SCSI_ERROR (1<<3)
#define TW_CL_ERR_REQ_AUTO_SENSE_VALID (1<<4)
#define TW_CL_ERR_REQ_BUS_RESET (1<<5)
#define TW_CL_ERR_REQ_UNABLE_TO_SUBMIT_COMMAND (1<<6)
/* Possible values of req_pkt->flags */
#define TW_CL_REQ_RETRY_ON_BUSY (1<<0)
#define TW_CL_REQ_CALLBACK_FOR_SGLIST (1<<1)
#define TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR 3
#define TW_CL_MESSAGE_SOURCE_CONTROLLER_EVENT 4
#define TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR 21
#define TW_CL_MESSAGE_SOURCE_COMMON_LAYER_EVENT 22
#define TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER 5
#define TW_CL_MESSAGE_SOURCE_FREEBSD_OS 8
#define TW_CL_MESSAGE_SOURCE_WINDOWS_DRIVER 7
#define TW_CL_MESSAGE_SOURCE_WINDOWS_OS 10
#define TW_CL_SEVERITY_ERROR 0x1
#define TW_CL_SEVERITY_WARNING 0x2
#define TW_CL_SEVERITY_INFO 0x3
#define TW_CL_SEVERITY_DEBUG 0x4
#define TW_CL_SEVERITY_ERROR_STRING "ERROR"
#define TW_CL_SEVERITY_WARNING_STRING "WARNING"
#define TW_CL_SEVERITY_INFO_STRING "INFO"
#define TW_CL_SEVERITY_DEBUG_STRING "DEBUG"
/*
* Structure, a pointer to which is used as the controller handle in
* communications between the OS Layer and the Common Layer.
*/
struct tw_cl_ctlr_handle {
TW_VOID *osl_ctlr_ctxt; /* OSL's ctlr context */
TW_VOID *cl_ctlr_ctxt; /* CL's ctlr context */
};
/*
* Structure, a pointer to which is used as the request handle in
* communications between the OS Layer and the Common Layer.
*/
struct tw_cl_req_handle {
TW_VOID *osl_req_ctxt; /* OSL's request context */
TW_VOID *cl_req_ctxt; /* CL's request context */
TW_UINT8 is_io; /* Only freeze/release simq for IOs */
};
/* Structure used to describe SCSI requests to CL. */
struct tw_cl_scsi_req_packet {
TW_UINT32 unit; /* unit # to send cmd to */
TW_UINT32 lun; /* LUN to send cmd to */
TW_UINT8 *cdb; /* ptr to SCSI cdb */
TW_UINT32 cdb_len; /* # of valid cdb bytes */
TW_UINT32 sense_len; /* # of bytes of valid sense info */
TW_UINT8 *sense_data; /* ptr to sense data, if any */
TW_UINT32 scsi_status; /* SCSI status returned by fw */
TW_UINT32 sgl_entries; /* # of SG descriptors */
TW_UINT8 *sg_list; /* ptr to SG list */
};
/* Structure used to describe pass through command packets to CL. */
struct tw_cl_passthru_req_packet {
TW_UINT8 *cmd_pkt; /* ptr to passthru cmd pkt */
TW_UINT32 cmd_pkt_length; /* size of cmd pkt */
TW_UINT32 sgl_entries; /* # of SG descriptors */
TW_UINT8 *sg_list; /* ptr to SG list */
};
/* Request packet submitted to the Common Layer, by the OS Layer. */
struct tw_cl_req_packet {
TW_UINT32 cmd; /* Common Layer cmd */
TW_UINT32 flags; /* flags describing request */
TW_UINT32 status; /* Common Layer returned status */
TW_VOID (*tw_osl_callback)(struct tw_cl_req_handle *req_handle);
/* OSL routine to be called by CL on req completion */
TW_VOID (*tw_osl_sgl_callback)(
struct tw_cl_req_handle *req_handle, TW_VOID *sg_list,
TW_UINT32 *num_sgl_entries);
/* OSL callback to get SG list. */
union {
struct tw_cl_scsi_req_packet scsi_req; /* SCSI req */
struct tw_cl_passthru_req_packet pt_req;/*Passthru req*/
} gen_req_pkt;
};
#pragma pack(1)
/*
* Packet that describes an AEN/error generated by the controller,
* Common Layer, or even the OS Layer.
*/
struct tw_cl_event_packet {
TW_UINT32 sequence_id;
TW_UINT32 time_stamp_sec;
TW_UINT16 aen_code;
TW_UINT8 severity;
TW_UINT8 retrieved;
TW_UINT8 repeat_count;
TW_UINT8 parameter_len;
TW_UINT8 parameter_data[98];
TW_UINT32 event_src;
TW_UINT8 severity_str[20];
};
#pragma pack()
/* Structure to link 2 adjacent elements in a list. */
struct tw_cl_link {
struct tw_cl_link *next;
struct tw_cl_link *prev;
};
#pragma pack(1)
/* Scatter/Gather list entry with 32 bit addresses. */
struct tw_cl_sg_desc32 {
TW_UINT32 address;
TW_UINT32 length;
};
/* Scatter/Gather list entry with 64 bit addresses. */
struct tw_cl_sg_desc64 {
TW_UINT64 address;
TW_UINT32 length;
};
#pragma pack()
/* Byte swap functions. Valid only if running on big endian platforms. */
#ifdef TW_OSL_BIG_ENDIAN
#define TW_CL_SWAP16_WITH_CAST(x) \
((x << 8) | (x >> 8))
#define TW_CL_SWAP32_WITH_CAST(x) \
((x << 24) | ((x << 8) & (0xFF0000)) | \
((x >> 8) & (0xFF00)) | (x >> 24))
#define TW_CL_SWAP64_WITH_CAST(x) \
((((TW_UINT64)(TW_CL_SWAP32(((TW_UINT32 *)(&(x)))[1]))) << 32) |\
((TW_UINT32)(TW_CL_SWAP32(((TW_UINT32 *)(&(x)))[0]))))
#else /* TW_OSL_BIG_ENDIAN */
#define TW_CL_SWAP16_WITH_CAST(x) x
#define TW_CL_SWAP32_WITH_CAST(x) x
#define TW_CL_SWAP64_WITH_CAST(x) x
#endif /* TW_OSL_BIG_ENDIAN */
#define TW_CL_SWAP16(x) TW_CL_SWAP16_WITH_CAST((TW_UINT16)(x))
#define TW_CL_SWAP32(x) TW_CL_SWAP32_WITH_CAST((TW_UINT32)(x))
#define TW_CL_SWAP64(x) TW_CL_SWAP64_WITH_CAST((TW_UINT64)(x))
/* Queue manipulation functions. */
/* Initialize a queue. */
#define TW_CL_Q_INIT(head) do { \
(head)->prev = (head)->next = head; \
} while (0)
/* Insert an item at the head of the queue. */
#define TW_CL_Q_INSERT_HEAD(head, item) do { \
(item)->next = (head)->next; \
(item)->prev = head; \
(head)->next->prev = item; \
(head)->next = item; \
} while (0)
/* Insert an item at the tail of the queue. */
#define TW_CL_Q_INSERT_TAIL(head, item) do { \
(item)->next = head; \
(item)->prev = (head)->prev; \
(head)->prev->next = item; \
(head)->prev = item; \
} while (0)
/* Remove an item from the head of the queue. */
#define TW_CL_Q_REMOVE_ITEM(head, item) do { \
(item)->prev->next = (item)->next; \
(item)->next->prev = (item)->prev; \
} while (0)
/* Retrieve the item at the head of the queue. */
#define TW_CL_Q_FIRST_ITEM(head) \
(((head)->next != head) ? ((head)->next) : TW_CL_NULL)
/* Retrieve the item at the tail of the queue. */
#define TW_CL_Q_LAST_ITEM(head) \
(((head)->prev != head) ? ((head)->prev) : TW_CL_NULL)
/* Retrieve the item next to a given item in the queue. */
#define TW_CL_Q_NEXT_ITEM(head, item) \
(((item)->next != head) ? ((item)->next) : TW_CL_NULL)
/* Retrieve the item previous to a given item in the queue. */
#define TW_CL_Q_PREV_ITEM(head, item) \
(((item)->prev != head) ? ((item)->prev) : TW_CL_NULL)
/* Determine the offset of a field from the head of the structure it is in. */
#define TW_CL_STRUCT_OFFSET(struct_type, field) \
(TW_INT8 *)(&((struct_type *)0)->field)
/*
* Determine the address of the head of a structure, given the address of a
* field within it.
*/
#define TW_CL_STRUCT_HEAD(addr, struct_type, field) \
(struct_type *)((TW_INT8 *)addr - \
TW_CL_STRUCT_OFFSET(struct_type, field))
#ifndef TW_BUILDING_API
#include "tw_osl_inline.h"
/*
* The following are extern declarations of OS Layer defined functions called
* by the Common Layer. If any function has been defined as a macro in
* tw_osl_share.h, we will not make the extern declaration here.
*/
#ifndef tw_osl_breakpoint
/* Allows setting breakpoints in the CL code for debugging purposes. */
extern TW_VOID tw_osl_breakpoint(TW_VOID);
#endif
#ifndef tw_osl_timeout
/* Start OS timeout() routine after controller reset sequence */
extern TW_VOID tw_osl_timeout(struct tw_cl_req_handle *req_handle);
#endif
#ifndef tw_osl_untimeout
/* Stop OS timeout() routine during controller reset sequence */
extern TW_VOID tw_osl_untimeout(struct tw_cl_req_handle *req_handle);
#endif
#ifndef tw_osl_cur_func
/* Text name of current function. */
extern TW_INT8 *tw_osl_cur_func(TW_VOID);
#endif
#ifdef TW_OSL_DEBUG
#ifndef tw_osl_dbg_printf
/* Print to syslog/event log/debug console, as applicable. */
extern TW_INT32 tw_osl_dbg_printf(struct tw_cl_ctlr_handle *ctlr_handle,
const TW_INT8 *fmt, ...);
#endif
#endif /* TW_OSL_DEBUG */
#ifndef tw_osl_delay
/* Cause a delay of usecs micro-seconds. */
extern TW_VOID tw_osl_delay(TW_INT32 usecs);
#endif
#ifndef tw_osl_destroy_lock
/* Create/initialize a lock for CL's use. */
extern TW_VOID tw_osl_destroy_lock(struct tw_cl_ctlr_handle *ctlr_handle,
TW_LOCK_HANDLE *lock);
#endif
#ifndef tw_osl_free_lock
/* Free a previously held lock. */
extern TW_VOID tw_osl_free_lock(struct tw_cl_ctlr_handle *ctlr_handle,
TW_LOCK_HANDLE *lock);
#endif
#ifndef tw_osl_get_local_time
/* Get local time. */
extern TW_TIME tw_osl_get_local_time(TW_VOID);
#endif
#ifndef tw_osl_get_lock
/* Acquire a lock. */
extern TW_VOID tw_osl_get_lock(struct tw_cl_ctlr_handle *ctlr_handle,
TW_LOCK_HANDLE *lock);
#endif
#ifndef tw_osl_init_lock
/* Create/initialize a lock for CL's use. */
extern TW_VOID tw_osl_init_lock(struct tw_cl_ctlr_handle *ctlr_handle,
TW_INT8 *lock_name, TW_LOCK_HANDLE *lock);
#endif
#ifndef tw_osl_memcpy
/* Copy 'size' bytes from 'src' to 'dest'. */
extern TW_VOID tw_osl_memcpy(TW_VOID *src, TW_VOID *dest, TW_INT32 size);
#endif
#ifndef tw_osl_memzero
/* Zero 'size' bytes starting at 'addr'. */
extern TW_VOID tw_osl_memzero(TW_VOID *addr, TW_INT32 size);
#endif
#ifndef tw_osl_notify_event
/* Notify OSL of a controller/CL (or even OSL) event. */
extern TW_VOID tw_osl_notify_event(struct tw_cl_ctlr_handle *ctlr_handle,
struct tw_cl_event_packet *event);
#endif
#ifdef TW_OSL_PCI_CONFIG_ACCESSIBLE
#ifndef tw_osl_read_pci_config
/* Read 'size' bytes from 'offset' in the PCI config space. */
extern TW_UINT32 tw_osl_read_pci_config(
struct tw_cl_ctlr_handle *ctlr_handle, TW_INT32 offset, TW_INT32 size);
#endif
#endif /* TW_OSL_PCI_CONFIG_ACCESSIBLE */
#ifndef tw_osl_read_reg
/* Read 'size' bytes at 'offset' from base address of this controller. */
extern TW_UINT32 tw_osl_read_reg(struct tw_cl_ctlr_handle *ctlr_handle,
TW_INT32 offset, TW_INT32 size);
#endif
#ifndef tw_osl_scan_bus
/* Request OSL for a bus scan. */
extern TW_VOID tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle);
#endif
#ifdef TW_OSL_CAN_SLEEP
#ifndef tw_osl_sleep
/* Sleep for 'timeout' ms or until woken up (by tw_osl_wakeup). */
extern TW_INT32 tw_osl_sleep(struct tw_cl_ctlr_handle *ctlr_handle,
TW_SLEEP_HANDLE *sleep_handle, TW_INT32 timeout);
#endif
#endif /* TW_OSL_CAN_SLEEP */
#ifndef tw_osl_sprintf
/* Standard sprintf. */
extern TW_INT32 tw_osl_sprintf(TW_INT8 *dest, const TW_INT8 *fmt, ...);
#endif
#ifndef tw_osl_strcpy
/* Copy string 'src' to 'dest'. */
extern TW_INT8 *tw_osl_strcpy(TW_INT8 *dest, TW_INT8 *src);
#endif
#ifndef tw_osl_strlen
/* Return length of string pointed at by 'str'. */
extern TW_INT32 tw_osl_strlen(TW_VOID *str);
#endif
#ifndef tw_osl_vsprintf
/* Standard vsprintf. */
extern TW_INT32 tw_osl_vsprintf(TW_INT8 *dest, const TW_INT8 *fmt, va_list ap);
#endif
#ifdef TW_OSL_CAN_SLEEP
#ifndef tw_osl_wakeup
/* Wake up a thread sleeping by a call to tw_osl_sleep. */
extern TW_VOID tw_osl_wakeup(struct tw_cl_ctlr_handle *ctlr_handle,
TW_SLEEP_HANDLE *sleep_handle);
#endif
#endif /* TW_OSL_CAN_SLEEP */
#ifdef TW_OSL_PCI_CONFIG_ACCESSIBLE
#ifndef tw_osl_write_pci_config
/* Write 'value' of 'size' bytes at 'offset' in the PCI config space. */
extern TW_VOID tw_osl_write_pci_config(struct tw_cl_ctlr_handle *ctlr_handle,
TW_INT32 offset, TW_INT32 value, TW_INT32 size);
#endif
#endif /* TW_OSL_PCI_CONFIG_ACCESSIBLE */
#ifndef tw_osl_write_reg
/*
* Write 'value' of 'size' (max 4) bytes at 'offset' from base address of
* this controller.
*/
extern TW_VOID tw_osl_write_reg(struct tw_cl_ctlr_handle *ctlr_handle,
TW_INT32 offset, TW_INT32 value, TW_INT32 size);
#endif
/* Functions in the Common Layer */
/* Creates and queues AEN's. Also notifies OS Layer. */
extern TW_VOID tw_cl_create_event(struct tw_cl_ctlr_handle *ctlr_handle,
TW_UINT8 queue_event, TW_UINT8 event_src, TW_UINT16 event_code,
TW_UINT8 severity, TW_UINT8 *severity_str, TW_UINT8 *event_desc,
TW_UINT8 *event_specific_desc, ...);
/* Indicates whether a ctlr is supported by CL. */
extern TW_INT32 tw_cl_ctlr_supported(TW_INT32 vendor_id, TW_INT32 device_id);
/* Submit a firmware cmd packet. */
extern TW_INT32 tw_cl_fw_passthru(struct tw_cl_ctlr_handle *ctlr_handle,
struct tw_cl_req_packet *req_pkt, struct tw_cl_req_handle *req_handle);
/* Find out how much memory CL needs. */
extern TW_INT32 tw_cl_get_mem_requirements(
struct tw_cl_ctlr_handle *ctlr_handle, TW_UINT32 flags,
TW_INT32 device_id, TW_INT32 max_simult_reqs, TW_INT32 max_aens,
TW_UINT32 *alignment, TW_UINT32 *sg_size_factor,
TW_UINT32 *non_dma_mem_size, TW_UINT32 *dma_mem_size
);
/* Return PCI BAR info. */
extern TW_INT32 tw_cl_get_pci_bar_info(TW_INT32 device_id, TW_INT32 bar_type,
TW_INT32 *bar_num, TW_INT32 *bar0_offset, TW_INT32 *bar_size);
/* Initialize Common Layer for a given controller. */
extern TW_INT32 tw_cl_init_ctlr(struct tw_cl_ctlr_handle *ctlr_handle,
TW_UINT32 flags, TW_INT32 device_id, TW_INT32 max_simult_reqs,
TW_INT32 max_aens, TW_VOID *non_dma_mem, TW_VOID *dma_mem,
TW_UINT64 dma_mem_phys
);
extern TW_VOID tw_cl_set_reset_needed(struct tw_cl_ctlr_handle *ctlr_handle);
extern TW_INT32 tw_cl_is_reset_needed(struct tw_cl_ctlr_handle *ctlr_handle);
extern TW_INT32 tw_cl_is_active(struct tw_cl_ctlr_handle *ctlr_handle);
/* CL's interrupt handler. */
extern TW_INT32 tw_cl_interrupt(struct tw_cl_ctlr_handle *ctlr_handle);
/* CL's ioctl handler. */
extern TW_INT32 tw_cl_ioctl(struct tw_cl_ctlr_handle *ctlr_handle,
u_long cmd, TW_VOID *buf);
#ifdef TW_OSL_DEBUG
/* Print CL's state/statistics for a controller. */
extern TW_VOID tw_cl_print_ctlr_stats(struct tw_cl_ctlr_handle *ctlr_handle);
/* Prints CL internal details of a given request. */
extern TW_VOID tw_cl_print_req_info(struct tw_cl_req_handle *req_handle);
#endif /* TW_OSL_DEBUG */
/* Soft reset controller. */
extern TW_INT32 tw_cl_reset_ctlr(struct tw_cl_ctlr_handle *ctlr_handle);
#ifdef TW_OSL_DEBUG
/* Reset CL's statistics for a controller. */
extern TW_VOID tw_cl_reset_stats(struct tw_cl_ctlr_handle *ctlr_handle);
#endif /* TW_OSL_DEBUG */
/* Stop a controller. */
extern TW_INT32 tw_cl_shutdown_ctlr(struct tw_cl_ctlr_handle *ctlr_handle,
TW_UINT32 flags);
/* Submit a SCSI I/O request. */
extern TW_INT32 tw_cl_start_io(struct tw_cl_ctlr_handle *ctlr_handle,
struct tw_cl_req_packet *req_pkt, struct tw_cl_req_handle *req_handle);
#endif /* TW_BUILDING_API */
#endif /* TW_CL_SHARE_H */

View file

@ -1,298 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap.
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
* Modifications by: Manjunath Ranganathaiah
*/
#ifndef TW_OSL_H
#define TW_OSL_H
/*
* OS Layer internal macros, structures and functions.
*/
#define TW_OSLI_DEVICE_NAME "3ware 9000 series Storage Controller"
#define TW_OSLI_MALLOC_CLASS M_TWA
#define TW_OSLI_MAX_NUM_REQUESTS TW_CL_MAX_SIMULTANEOUS_REQUESTS
/* Reserve two command packets. One for ioctls and one for AENs */
#define TW_OSLI_MAX_NUM_IOS (TW_OSLI_MAX_NUM_REQUESTS - 2)
#define TW_OSLI_MAX_NUM_AENS 0x100
#ifdef PAE
#define TW_OSLI_DMA_BOUNDARY (1u << 31)
#else
#define TW_OSLI_DMA_BOUNDARY ((bus_size_t)((uint64_t)1 << 32))
#endif
/* Possible values of req->state. */
#define TW_OSLI_REQ_STATE_INIT 0x0 /* being initialized */
#define TW_OSLI_REQ_STATE_BUSY 0x1 /* submitted to CL */
#define TW_OSLI_REQ_STATE_PENDING 0x2 /* in pending queue */
#define TW_OSLI_REQ_STATE_COMPLETE 0x3 /* completed by CL */
/* Possible values of req->flags. */
#define TW_OSLI_REQ_FLAGS_DATA_IN (1<<0) /* read request */
#define TW_OSLI_REQ_FLAGS_DATA_OUT (1<<1) /* write request */
#define TW_OSLI_REQ_FLAGS_DATA_COPY_NEEDED (1<<2)/* data in ccb is misaligned,
have to copy to/from private buffer */
#define TW_OSLI_REQ_FLAGS_MAPPED (1<<3) /* request has been mapped */
#define TW_OSLI_REQ_FLAGS_IN_PROGRESS (1<<4) /* bus_dmamap_load returned
EINPROGRESS */
#define TW_OSLI_REQ_FLAGS_PASSTHRU (1<<5) /* pass through request */
#define TW_OSLI_REQ_FLAGS_SLEEPING (1<<6) /* owner sleeping on this cmd */
#define TW_OSLI_REQ_FLAGS_FAILED (1<<7) /* bus_dmamap_load() failed */
#define TW_OSLI_REQ_FLAGS_CCB (1<<8) /* req is ccb. */
#ifdef TW_OSL_DEBUG
struct tw_osli_q_stats {
TW_UINT32 cur_len; /* current # of items in q */
TW_UINT32 max_len; /* max value reached by q_length */
};
#endif /* TW_OSL_DEBUG */
/* Queues of OSL internal request context packets. */
#define TW_OSLI_FREE_Q 0 /* free q */
#define TW_OSLI_BUSY_Q 1 /* q of reqs submitted to CL */
#define TW_OSLI_Q_COUNT 2 /* total number of queues */
/* Driver's request packet. */
struct tw_osli_req_context {
struct tw_cl_req_handle req_handle;/* tag to track req b/w OSL & CL */
struct mtx ioctl_wake_timeout_lock_handle;/* non-spin lock used to detect ioctl timeout */
struct mtx *ioctl_wake_timeout_lock;/* ptr to above lock */
struct twa_softc *ctlr; /* ptr to OSL's controller context */
TW_VOID *data; /* ptr to data being passed to CL */
TW_UINT32 length; /* length of buf being passed to CL */
TW_UINT64 deadline;/* request timeout (in absolute time) */
/*
* ptr to, and length of data passed to us from above, in case a buffer
* copy was done due to non-compliance to alignment requirements
*/
TW_VOID *real_data;
TW_UINT32 real_length;
TW_UINT32 state; /* request state */
TW_UINT32 flags; /* request flags */
/* error encountered before request submission to CL */
TW_UINT32 error_code;
/* ptr to orig req for use during callback */
TW_VOID *orig_req;
struct tw_cl_link link; /* to link this request in a list */
bus_dmamap_t dma_map;/* DMA map for data */
struct tw_cl_req_packet req_pkt;/* req pkt understood by CL */
};
/* Per-controller structure. */
struct twa_softc {
struct tw_cl_ctlr_handle ctlr_handle;
struct tw_osli_req_context *req_ctx_buf;
/* Controller state. */
TW_UINT8 open;
TW_UINT32 flags;
TW_INT32 device_id;
TW_UINT32 alignment;
TW_UINT32 sg_size_factor;
TW_VOID *non_dma_mem;
TW_VOID *dma_mem;
TW_UINT64 dma_mem_phys;
/* Request queues and arrays. */
struct tw_cl_link req_q_head[TW_OSLI_Q_COUNT];
struct task deferred_intr_callback;/* taskqueue function */
struct mtx io_lock_handle;/* general purpose lock */
struct mtx *io_lock;/* ptr to general purpose lock */
struct mtx q_lock_handle; /* queue manipulation lock */
struct mtx *q_lock;/* ptr to queue manipulation lock */
struct mtx sim_lock_handle;/* sim lock shared with cam */
struct mtx *sim_lock;/* ptr to sim lock */
struct callout watchdog_callout[2]; /* For command timeout */
TW_UINT32 watchdog_index;
#ifdef TW_OSL_DEBUG
struct tw_osli_q_stats q_stats[TW_OSLI_Q_COUNT];/* queue statistics */
#endif /* TW_OSL_DEBUG */
device_t bus_dev; /* bus device */
struct cdev *ctrl_dev; /* control device */
struct resource *reg_res; /* register interface window */
TW_INT32 reg_res_id; /* register resource id */
bus_space_handle_t bus_handle; /* bus space handle */
bus_space_tag_t bus_tag; /* bus space tag */
bus_dma_tag_t parent_tag; /* parent DMA tag */
bus_dma_tag_t cmd_tag; /* DMA tag for CL's DMA'able mem */
bus_dma_tag_t dma_tag; /* data buffer DMA tag */
bus_dma_tag_t ioctl_tag; /* ioctl data buffer DMA tag */
bus_dmamap_t cmd_map; /* DMA map for CL's DMA'able mem */
bus_dmamap_t ioctl_map; /* DMA map for ioctl data buffers */
struct resource *irq_res; /* interrupt resource */
TW_INT32 irq_res_id; /* register resource id */
TW_VOID *intr_handle; /* interrupt handle */
struct sysctl_ctx_list sysctl_ctxt; /* sysctl context */
struct sysctl_oid *sysctl_tree; /* sysctl oid */
struct cam_sim *sim; /* sim for this controller */
struct cam_path *path; /* peripheral, path, tgt, lun
associated with this controller */
};
/*
* Queue primitives.
*/
#ifdef TW_OSL_DEBUG
#define TW_OSLI_Q_INIT(sc, q_type) do { \
(sc)->q_stats[q_type].cur_len = 0; \
(sc)->q_stats[q_type].max_len = 0; \
} while(0)
#define TW_OSLI_Q_INSERT(sc, q_type) do { \
struct tw_osli_q_stats *q_stats = &((sc)->q_stats[q_type]); \
\
if (++(q_stats->cur_len) > q_stats->max_len) \
q_stats->max_len = q_stats->cur_len; \
} while(0)
#define TW_OSLI_Q_REMOVE(sc, q_type) \
(sc)->q_stats[q_type].cur_len--
#else /* TW_OSL_DEBUG */
#define TW_OSLI_Q_INIT(sc, q_index)
#define TW_OSLI_Q_INSERT(sc, q_index)
#define TW_OSLI_Q_REMOVE(sc, q_index)
#endif /* TW_OSL_DEBUG */
/* Initialize a queue of requests. */
static __inline TW_VOID
tw_osli_req_q_init(struct twa_softc *sc, TW_UINT8 q_type)
{
TW_CL_Q_INIT(&(sc->req_q_head[q_type]));
TW_OSLI_Q_INIT(sc, q_type);
}
/* Insert the given request at the head of the given queue (q_type). */
static __inline TW_VOID
tw_osli_req_q_insert_head(struct tw_osli_req_context *req, TW_UINT8 q_type)
{
mtx_lock_spin(req->ctlr->q_lock);
TW_CL_Q_INSERT_HEAD(&(req->ctlr->req_q_head[q_type]), &(req->link));
TW_OSLI_Q_INSERT(req->ctlr, q_type);
mtx_unlock_spin(req->ctlr->q_lock);
}
/* Insert the given request at the tail of the given queue (q_type). */
static __inline TW_VOID
tw_osli_req_q_insert_tail(struct tw_osli_req_context *req, TW_UINT8 q_type)
{
mtx_lock_spin(req->ctlr->q_lock);
TW_CL_Q_INSERT_TAIL(&(req->ctlr->req_q_head[q_type]), &(req->link));
TW_OSLI_Q_INSERT(req->ctlr, q_type);
mtx_unlock_spin(req->ctlr->q_lock);
}
/* Remove and return the request at the head of the given queue (q_type). */
static __inline struct tw_osli_req_context *
tw_osli_req_q_remove_head(struct twa_softc *sc, TW_UINT8 q_type)
{
struct tw_osli_req_context *req = NULL;
struct tw_cl_link *link;
mtx_lock_spin(sc->q_lock);
if ((link = TW_CL_Q_FIRST_ITEM(&(sc->req_q_head[q_type]))) !=
TW_CL_NULL) {
req = TW_CL_STRUCT_HEAD(link,
struct tw_osli_req_context, link);
TW_CL_Q_REMOVE_ITEM(&(sc->req_q_head[q_type]), &(req->link));
TW_OSLI_Q_REMOVE(sc, q_type);
}
mtx_unlock_spin(sc->q_lock);
return(req);
}
/* Remove the given request from the given queue (q_type). */
static __inline TW_VOID
tw_osli_req_q_remove_item(struct tw_osli_req_context *req, TW_UINT8 q_type)
{
mtx_lock_spin(req->ctlr->q_lock);
TW_CL_Q_REMOVE_ITEM(&(req->ctlr->req_q_head[q_type]), &(req->link));
TW_OSLI_Q_REMOVE(req->ctlr, q_type);
mtx_unlock_spin(req->ctlr->q_lock);
}
#ifdef TW_OSL_DEBUG
extern TW_INT32 TW_DEBUG_LEVEL_FOR_OSL;
#define tw_osli_dbg_dprintf(dbg_level, sc, fmt, args...) \
if (dbg_level <= TW_DEBUG_LEVEL_FOR_OSL) \
device_printf(sc->bus_dev, "%s: " fmt "\n", \
__func__, ##args)
#define tw_osli_dbg_printf(dbg_level, fmt, args...) \
if (dbg_level <= TW_DEBUG_LEVEL_FOR_OSL) \
printf("%s: " fmt "\n", __func__, ##args)
#else /* TW_OSL_DEBUG */
#define tw_osli_dbg_dprintf(dbg_level, sc, fmt, args...)
#define tw_osli_dbg_printf(dbg_level, fmt, args...)
#endif /* TW_OSL_DEBUG */
/* For regular printing. */
#define twa_printf(sc, fmt, args...) \
device_printf(((struct twa_softc *)(sc))->bus_dev, fmt, ##args)
/* For printing in the "consistent error reporting" format. */
#define tw_osli_printf(sc, err_specific_desc, args...) \
device_printf((sc)->bus_dev, \
"%s: (0x%02X: 0x%04X): %s: " err_specific_desc "\n", ##args)
#endif /* TW_OSL_H */

View file

@ -1,663 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap.
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
* Modifications by: Manjunath Ranganathaiah
*/
/*
* FreeBSD CAM related functions.
*/
#include <dev/twa/tw_osl_includes.h>
#include <cam/cam.h>
#include <cam/cam_ccb.h>
#include <cam/cam_sim.h>
#include <cam/cam_xpt_sim.h>
#include <cam/cam_debug.h>
#include <cam/cam_periph.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>
static TW_VOID twa_action(struct cam_sim *sim, union ccb *ccb);
static TW_VOID twa_poll(struct cam_sim *sim);
static TW_INT32 tw_osli_execute_scsi(struct tw_osli_req_context *req,
union ccb *ccb);
/*
* Function name: tw_osli_cam_attach
* Description: Attaches the driver to CAM.
*
* Input: sc -- ptr to OSL internal ctlr context
* Output: None
* Return value: 0 -- success
* non-zero-- failure
*/
TW_INT32
tw_osli_cam_attach(struct twa_softc *sc)
{
struct cam_devq *devq;
tw_osli_dbg_dprintf(3, sc, "entered");
/*
* Create the device queue for our SIM.
*/
if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) {
tw_osli_printf(sc, "error = %d",
TW_CL_SEVERITY_ERROR_STRING,
TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
0x2100,
"Failed to create SIM device queue",
ENOMEM);
return(ENOMEM);
}
/*
* Create a SIM entry. Though we can support TW_OSLI_MAX_NUM_REQUESTS
* simultaneous requests, we claim to be able to handle only
* TW_OSLI_MAX_NUM_IOS (two less), so that we always have a request
* packet available to service ioctls and AENs.
*/
tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
device_get_unit(sc->bus_dev), sc->sim_lock,
TW_OSLI_MAX_NUM_IOS, 1, devq);
if (sc->sim == NULL) {
cam_simq_free(devq);
tw_osli_printf(sc, "error = %d",
TW_CL_SEVERITY_ERROR_STRING,
TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
0x2101,
"Failed to create a SIM entry",
ENOMEM);
return(ENOMEM);
}
/*
* Register the bus.
*/
tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
mtx_lock(sc->sim_lock);
if (xpt_bus_register(sc->sim, sc->bus_dev, 0) != CAM_SUCCESS) {
cam_sim_free(sc->sim, TRUE);
sc->sim = NULL; /* so cam_detach will not try to free it */
tw_osli_printf(sc, "error = %d",
TW_CL_SEVERITY_ERROR_STRING,
TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
0x2102,
"Failed to register the bus",
ENXIO);
mtx_unlock(sc->sim_lock);
return(ENXIO);
}
tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path");
if (xpt_create_path(&sc->path, NULL,
cam_sim_path(sc->sim),
CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
xpt_bus_deregister(cam_sim_path (sc->sim));
/* Passing TRUE to cam_sim_free will free the devq as well. */
cam_sim_free(sc->sim, TRUE);
tw_osli_printf(sc, "error = %d",
TW_CL_SEVERITY_ERROR_STRING,
TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
0x2103,
"Failed to create path",
ENXIO);
mtx_unlock(sc->sim_lock);
return(ENXIO);
}
mtx_unlock(sc->sim_lock);
tw_osli_dbg_dprintf(3, sc, "exiting");
return(0);
}
/*
* Function name: tw_osli_cam_detach
* Description: Detaches the driver from CAM.
*
* Input: sc -- ptr to OSL internal ctlr context
* Output: None
* Return value: None
*/
TW_VOID
tw_osli_cam_detach(struct twa_softc *sc)
{
tw_osli_dbg_dprintf(3, sc, "entered");
mtx_lock(sc->sim_lock);
if (sc->path)
xpt_free_path(sc->path);
if (sc->sim) {
xpt_bus_deregister(cam_sim_path(sc->sim));
/* Passing TRUE to cam_sim_free will free the devq as well. */
cam_sim_free(sc->sim, TRUE);
}
/* It's ok have 1 hold count while destroying the mutex */
mtx_destroy(sc->sim_lock);
}
/*
* Function name: tw_osli_execute_scsi
* Description: Build a fw cmd, based on a CAM style ccb, and
* send it down.
*
* Input: req -- ptr to OSL internal request context
* ccb -- ptr to CAM style ccb
* Output: None
* Return value: 0 -- success
* non-zero-- failure
*/
TW_INT32
tw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
{
struct twa_softc *sc = req->ctlr;
struct tw_cl_req_packet *req_pkt;
struct tw_cl_scsi_req_packet *scsi_req;
struct ccb_hdr *ccb_h = &(ccb->ccb_h);
struct ccb_scsiio *csio = &(ccb->csio);
TW_INT32 error;
tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x",
csio->cdb_io.cdb_bytes[0]);
if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) {
tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %jx",
ccb_h->path_id, ccb_h->target_id,
(uintmax_t)ccb_h->target_lun);
ccb_h->status |= CAM_TID_INVALID;
xpt_done(ccb);
return(1);
}
if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) {
tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %jx",
ccb_h->path_id, ccb_h->target_id,
(uintmax_t)ccb_h->target_lun);
ccb_h->status |= CAM_LUN_INVALID;
xpt_done(ccb);
return(1);
}
if(ccb_h->flags & CAM_CDB_PHYS) {
tw_osli_printf(sc, "",
TW_CL_SEVERITY_ERROR_STRING,
TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
0x2105,
"Physical CDB address!");
ccb_h->status = CAM_REQ_INVALID;
xpt_done(ccb);
return(1);
}
/*
* We are going to work on this request. Mark it as enqueued (though
* we don't actually queue it...)
*/
ccb_h->status |= CAM_SIM_QUEUED;
if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
if(ccb_h->flags & CAM_DIR_IN)
req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN;
else
req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT;
}
/* Build the CL understood request packet for SCSI cmds. */
req_pkt = &req->req_pkt;
req_pkt->status = 0;
req_pkt->tw_osl_callback = tw_osl_complete_io;
scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
scsi_req->unit = ccb_h->target_id;
scsi_req->lun = ccb_h->target_lun;
scsi_req->sense_len = 0;
scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data);
scsi_req->scsi_status = 0;
if(ccb_h->flags & CAM_CDB_POINTER)
scsi_req->cdb = csio->cdb_io.cdb_ptr;
else
scsi_req->cdb = csio->cdb_io.cdb_bytes;
scsi_req->cdb_len = csio->cdb_len;
if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) {
tw_osli_printf(sc, "size = %d",
TW_CL_SEVERITY_ERROR_STRING,
TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
0x2106,
"I/O size too big",
csio->dxfer_len);
ccb_h->status = CAM_REQ_TOO_BIG;
ccb_h->status &= ~CAM_SIM_QUEUED;
xpt_done(ccb);
return(1);
}
if ((ccb_h->flags & CAM_DATA_MASK) == CAM_DATA_VADDR) {
if ((req->length = csio->dxfer_len) != 0) {
req->data = csio->data_ptr;
scsi_req->sgl_entries = 1;
}
} else
req->flags |= TW_OSLI_REQ_FLAGS_CCB;
req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
/*
* twa_map_load_data_callback will fill in the SGL,
* and submit the I/O.
*/
error = tw_osli_map_request(req);
if ((error) && (req->flags & TW_OSLI_REQ_FLAGS_FAILED)) {
req->deadline = 0;
ccb_h->status = CAM_REQ_CMP_ERR;
ccb_h->status &= ~CAM_SIM_QUEUED;
xpt_done(ccb);
}
return(error);
}
/*
* Function name: twa_action
* Description: Driver entry point for CAM's use.
*
* Input: sim -- sim corresponding to the ctlr
* ccb -- ptr to CAM request
* Output: None
* Return value: None
*/
TW_VOID
twa_action(struct cam_sim *sim, union ccb *ccb)
{
struct twa_softc *sc = (struct twa_softc *)cam_sim_softc(sim);
struct ccb_hdr *ccb_h = &(ccb->ccb_h);
switch (ccb_h->func_code) {
case XPT_SCSI_IO: /* SCSI I/O */
{
struct tw_osli_req_context *req;
req = tw_osli_get_request(sc);
if (req == NULL) {
tw_osli_dbg_dprintf(2, sc, "Cannot get request pkt.");
/*
* Freeze the simq to maintain ccb ordering. The next
* ccb that gets completed will unfreeze the simq.
*/
ccb_h->status &= ~CAM_SIM_QUEUED;
ccb_h->status |= CAM_REQUEUE_REQ;
xpt_done(ccb);
break;
}
if ((tw_cl_is_reset_needed(&(req->ctlr->ctlr_handle)))) {
ccb_h->status &= ~CAM_SIM_QUEUED;
ccb_h->status |= CAM_REQUEUE_REQ;
xpt_done(ccb);
tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
break;
}
req->req_handle.osl_req_ctxt = req;
req->req_handle.is_io = TW_CL_TRUE;
req->orig_req = ccb;
if (tw_osli_execute_scsi(req, ccb))
tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
break;
}
case XPT_ABORT:
tw_osli_dbg_dprintf(2, sc, "Abort request.");
ccb_h->status = CAM_UA_ABORT;
xpt_done(ccb);
break;
case XPT_RESET_BUS:
tw_cl_create_event(&(sc->ctlr_handle), TW_CL_FALSE,
TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
"Received Reset Bus request from CAM",
" ");
tw_cl_set_reset_needed(&(sc->ctlr_handle));
ccb_h->status = CAM_REQ_CMP;
xpt_done(ccb);
break;
case XPT_SET_TRAN_SETTINGS:
tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS");
/*
* This command is not supported, since it's very specific
* to SCSI, and we are doing ATA.
*/
ccb_h->status = CAM_FUNC_NOTAVAIL;
xpt_done(ccb);
break;
case XPT_GET_TRAN_SETTINGS:
{
struct ccb_trans_settings *cts = &ccb->cts;
struct ccb_trans_settings_scsi *scsi =
&cts->proto_specific.scsi;
struct ccb_trans_settings_spi *spi =
&cts->xport_specific.spi;
cts->protocol = PROTO_SCSI;
cts->protocol_version = SCSI_REV_2;
cts->transport = XPORT_SPI;
cts->transport_version = 2;
spi->valid = CTS_SPI_VALID_DISC;
spi->flags = CTS_SPI_FLAGS_DISC_ENB;
scsi->valid = CTS_SCSI_VALID_TQ;
scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
ccb_h->status = CAM_REQ_CMP;
xpt_done(ccb);
break;
}
case XPT_CALC_GEOMETRY:
tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
cam_calc_geometry(&ccb->ccg, 1/* extended */);
xpt_done(ccb);
break;
case XPT_PATH_INQ: /* Path inquiry -- get twa properties */
{
struct ccb_pathinq *path_inq = &ccb->cpi;
tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");
path_inq->version_num = 1;
path_inq->hba_inquiry = 0;
path_inq->target_sprt = 0;
path_inq->hba_misc = 0;
path_inq->hba_eng_cnt = 0;
path_inq->max_target = TW_CL_MAX_NUM_UNITS;
path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
path_inq->unit_number = cam_sim_unit(sim);
path_inq->bus_id = cam_sim_bus(sim);
path_inq->initiator_id = TW_CL_MAX_NUM_UNITS;
path_inq->base_transfer_speed = 100000;
strlcpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
strlcpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
strlcpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
path_inq->transport = XPORT_SPI;
path_inq->transport_version = 2;
path_inq->protocol = PROTO_SCSI;
path_inq->protocol_version = SCSI_REV_2;
path_inq->maxio = TW_CL_MAX_IO_SIZE;
ccb_h->status = CAM_REQ_CMP;
xpt_done(ccb);
break;
}
default:
tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
ccb_h->status = CAM_REQ_INVALID;
xpt_done(ccb);
break;
}
}
/*
* Function name: twa_poll
* Description: Driver entry point called when interrupts are not
* available.
*
* Input: sim -- sim corresponding to the controller
* Output: None
* Return value: None
*/
TW_VOID
twa_poll(struct cam_sim *sim)
{
struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
tw_cl_interrupt(&(sc->ctlr_handle));
tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
}
/*
* Function name: tw_osli_request_bus_scan
* Description: Requests CAM for a scan of the bus.
*
* Input: sc -- ptr to per ctlr structure
* Output: None
* Return value: 0 -- success
* non-zero-- failure
*/
TW_INT32
tw_osli_request_bus_scan(struct twa_softc *sc)
{
union ccb *ccb;
tw_osli_dbg_dprintf(3, sc, "entering");
/* If we get here before sc->sim is initialized, return an error. */
if (!(sc->sim))
return(ENXIO);
if ((ccb = xpt_alloc_ccb()) == NULL)
return(ENOMEM);
mtx_lock(sc->sim_lock);
if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(sc->sim),
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
xpt_free_ccb(ccb);
mtx_unlock(sc->sim_lock);
return(EIO);
}
xpt_rescan(ccb);
mtx_unlock(sc->sim_lock);
return(0);
}
/*
* Function name: tw_osli_disallow_new_requests
* Description: Calls the appropriate CAM function, so as to freeze
* the flow of new requests from CAM to this controller.
*
* Input: sc -- ptr to OSL internal ctlr context
* req_handle -- ptr to request handle sent by OSL.
* Output: None
* Return value: None
*/
TW_VOID
tw_osli_disallow_new_requests(struct twa_softc *sc,
struct tw_cl_req_handle *req_handle)
{
/* Only freeze/release the simq for IOs */
if (req_handle->is_io) {
struct tw_osli_req_context *req = req_handle->osl_req_ctxt;
union ccb *ccb = (union ccb *)(req->orig_req);
xpt_freeze_simq(sc->sim, 1);
ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
}
}
/*
* Function name: tw_osl_timeout
* Description: Call to timeout().
*
* Input: req_handle -- ptr to request handle sent by OSL.
* Output: None
* Return value: None
*/
TW_VOID
tw_osl_timeout(struct tw_cl_req_handle *req_handle)
{
struct tw_osli_req_context *req = req_handle->osl_req_ctxt;
union ccb *ccb = (union ccb *)(req->orig_req);
struct ccb_hdr *ccb_h = &(ccb->ccb_h);
req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
}
/*
* Function name: tw_osl_untimeout
* Description: Inverse of call to timeout().
*
* Input: req_handle -- ptr to request handle sent by OSL.
* Output: None
* Return value: None
*/
TW_VOID
tw_osl_untimeout(struct tw_cl_req_handle *req_handle)
{
struct tw_osli_req_context *req = req_handle->osl_req_ctxt;
req->deadline = 0;
}
/*
* Function name: tw_osl_scan_bus
* Description: CL calls this function to request for a bus scan.
*
* Input: ctlr_handle -- ptr to controller handle
* Output: None
* Return value: None
*/
TW_VOID
tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
{
struct twa_softc *sc = ctlr_handle->osl_ctlr_ctxt;
TW_INT32 error;
if ((error = tw_osli_request_bus_scan(sc)))
tw_osli_printf(sc, "error = %d",
TW_CL_SEVERITY_ERROR_STRING,
TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
0x2109,
"Bus scan request to CAM failed",
error);
}
/*
* Function name: tw_osl_complete_io
* Description: Called to complete CAM scsi requests.
*
* Input: req_handle -- ptr to request handle
* Output: None
* Return value: None
*/
TW_VOID
tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
{
struct tw_osli_req_context *req = req_handle->osl_req_ctxt;
struct tw_cl_req_packet *req_pkt =
(struct tw_cl_req_packet *)(&req->req_pkt);
struct tw_cl_scsi_req_packet *scsi_req;
struct twa_softc *sc = req->ctlr;
union ccb *ccb = (union ccb *)(req->orig_req);
tw_osli_dbg_dprintf(10, sc, "entering");
if (req->state != TW_OSLI_REQ_STATE_BUSY)
tw_osli_printf(sc, "request = %p, status = %d",
TW_CL_SEVERITY_ERROR_STRING,
TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
0x210A,
"Unposted command completed!!",
req, req->state);
/*
* Remove request from the busy queue. Just mark it complete.
* There's no need to move it into the complete queue as we are
* going to be done with it right now.
*/
req->state = TW_OSLI_REQ_STATE_COMPLETE;
tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
tw_osli_unmap_request(req);
req->deadline = 0;
if (req->error_code) {
/* This request never got submitted to the firmware. */
if (req->error_code == EBUSY) {
/*
* Cmd queue is full, or the Common Layer is out of
* resources. The simq will already have been frozen.
* When this ccb gets completed will unfreeze the simq.
*/
ccb->ccb_h.status |= CAM_REQUEUE_REQ;
}
else if (req->error_code == EFBIG)
ccb->ccb_h.status = CAM_REQ_TOO_BIG;
else
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
} else {
scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
ccb->ccb_h.status = CAM_REQ_CMP;
else {
if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
ccb->ccb_h.status |= CAM_SEL_TIMEOUT;
else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
ccb->ccb_h.status |= (CAM_REQUEUE_REQ | CAM_SCSI_BUS_RESET);
/*
* If none of the above errors occurred, simply
* mark completion error.
*/
if (ccb->ccb_h.status == 0)
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
ccb->csio.sense_len = scsi_req->sense_len;
ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
}
}
ccb->csio.scsi_status = scsi_req->scsi_status;
}
ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
mtx_lock(sc->sim_lock);
xpt_done(ccb);
mtx_unlock(sc->sim_lock);
if (! req->error_code)
/* twa_action will free the request otherwise */
tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
}

View file

@ -1,86 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap.
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
*/
#ifndef TW_OSL_EXTERNS_H
#define TW_OSL_EXTERNS_H
/*
* Data structures and functions global to the OS Layer.
*/
/* External data structures. */
extern int mp_ncpus;
/* Functions in tw_osl_freebsd.c */
/* Build a firmware passthru cmd pkt, and submit it to CL. */
extern TW_INT32 tw_osli_fw_passthru(struct twa_softc *sc, TW_INT8 *buf);
/* Get an OSL internal request context packet. */
extern struct tw_osli_req_context *tw_osli_get_request(struct twa_softc *sc);
/* Map data to DMA'able memory. */
extern TW_INT32 tw_osli_map_request(struct tw_osli_req_context *req);
/* Undo mapping. */
extern TW_VOID tw_osli_unmap_request(struct tw_osli_req_context *req);
/* Functions in tw_osl_cam.c */
/* Attach to CAM. */
extern TW_INT32 tw_osli_cam_attach(struct twa_softc *sc);
/* Detach from CAM. */
extern TW_VOID tw_osli_cam_detach(struct twa_softc *sc);
/* Request CAM for a bus scan. */
extern TW_INT32 tw_osli_request_bus_scan(struct twa_softc *sc);
/* Freeze ccb flow from CAM. */
extern TW_VOID tw_osli_disallow_new_requests(struct twa_softc *sc,
struct tw_cl_req_handle *req_handle);
/* OSL's completion routine for SCSI I/O's. */
extern TW_VOID tw_osl_complete_io(struct tw_cl_req_handle *req_handle);
/* OSL's completion routine for passthru requests. */
extern TW_VOID tw_osl_complete_passthru(struct tw_cl_req_handle *req_handle);
#endif /* TW_OSL_EXTERNS_H */

File diff suppressed because it is too large Load diff

View file

@ -1,76 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap.
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
*/
#ifndef TW_OSL_INCLUDES_H
#define TW_OSL_INCLUDES_H
/*
* All header files needed by the OS Layer.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/clock.h>
#include <sys/disk.h>
#include <sys/stat.h>
#include <sys/devicestat.h>
#include <sys/taskqueue.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <machine/stdarg.h>
#include <vm/vm.h>
#include <sys/rman.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/twa/tw_osl_share.h>
#include <dev/twa/tw_cl_share.h>
#include <dev/twa/tw_osl_externs.h>
#endif /* TW_OSL_INCLUDES_H */

View file

@ -1,309 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap.
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
*/
#ifndef TW_OSL_INLINE_H
#define TW_OSL_INLINE_H
/*
* Inline functions shared between OSL and CL, and defined by OSL.
*/
#include <dev/twa/tw_osl.h>
/*
* Function name: tw_osl_init_lock
* Description: Initializes a lock.
*
* Input: ctlr_handle -- ptr to controller handle
* lock_name -- string indicating name of the lock
* Output: lock -- ptr to handle to the initialized lock
* Return value: None
*/
#define tw_osl_init_lock(ctlr_handle, lock_name, lock) \
mtx_init(lock, lock_name, NULL, MTX_SPIN)
/*
* Function name: tw_osl_destroy_lock
* Description: Destroys a previously initialized lock.
*
* Input: ctlr_handle -- ptr to controller handle
* lock -- ptr to handle to the lock to be
* destroyed
* Output: None
* Return value: None
*/
#define tw_osl_destroy_lock(ctlr_handle, lock) \
mtx_destroy(lock)
/*
* Function name: tw_osl_get_lock
* Description: Acquires the specified lock.
*
* Input: ctlr_handle -- ptr to controller handle
* lock -- ptr to handle to the lock to be
* acquired
* Output: None
* Return value: None
*/
#define tw_osl_get_lock(ctlr_handle, lock) \
mtx_lock_spin(lock)
/*
* Function name: tw_osl_free_lock
* Description: Frees a previously acquired lock.
*
* Input: ctlr_handle -- ptr to controller handle
* lock -- ptr to handle to the lock to be freed
* Output: None
* Return value: None
*/
#define tw_osl_free_lock(ctlr_handle, lock) \
mtx_unlock_spin(lock)
#ifdef TW_OSL_DEBUG
/*
* Function name: tw_osl_dbg_printf
* Description: Prints passed info (prefixed by ctlr name)to syslog
*
* Input: ctlr_handle -- controller handle
* fmt -- format string for the arguments to follow
* ... -- variable number of arguments, to be printed
* based on the fmt string
* Output: None
* Return value: Number of bytes printed
*/
#define tw_osl_dbg_printf(ctlr_handle, fmt, args...) \
twa_printf((ctlr_handle->osl_ctlr_ctxt), fmt, ##args)
#endif /* TW_OSL_DEBUG */
/*
* Function name: tw_osl_notify_event
* Description: Prints passed event info (prefixed by ctlr name)
* to syslog
*
* Input: ctlr_handle -- controller handle
* event -- ptr to a packet describing the event/error
* Output: None
* Return value: None
*/
#define tw_osl_notify_event(ctlr_handle, event) \
twa_printf((ctlr_handle->osl_ctlr_ctxt), \
"%s: (0x%02X: 0x%04X): %s: %s\n", \
event->severity_str, \
event->event_src, \
event->aen_code, \
event->parameter_data + \
strlen(event->parameter_data) + 1, \
event->parameter_data)
/*
* Function name: tw_osl_read_reg
* Description: Reads a register on the controller
*
* Input: ctlr_handle -- controller handle
* offset -- offset from Base Address
* size -- # of bytes to read
* Output: None
* Return value: Value read
*/
#define tw_osl_read_reg tw_osl_read_reg_inline
static __inline TW_UINT32
tw_osl_read_reg_inline(struct tw_cl_ctlr_handle *ctlr_handle,
TW_INT32 offset, TW_INT32 size)
{
bus_space_tag_t bus_tag =
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_tag;
bus_space_handle_t bus_handle =
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_handle;
if (size == 4)
return((TW_UINT32)bus_space_read_4(bus_tag, bus_handle,
offset));
else if (size == 2)
return((TW_UINT32)bus_space_read_2(bus_tag, bus_handle,
offset));
else
return((TW_UINT32)bus_space_read_1(bus_tag, bus_handle,
offset));
}
/*
* Function name: tw_osl_write_reg
* Description: Writes to a register on the controller
*
* Input: ctlr_handle -- controller handle
* offset -- offset from Base Address
* value -- value to write
* size -- # of bytes to write
* Output: None
* Return value: None
*/
#define tw_osl_write_reg tw_osl_write_reg_inline
static __inline TW_VOID
tw_osl_write_reg_inline(struct tw_cl_ctlr_handle *ctlr_handle,
TW_INT32 offset, TW_INT32 value, TW_INT32 size)
{
bus_space_tag_t bus_tag =
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_tag;
bus_space_handle_t bus_handle =
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_handle;
if (size == 4)
bus_space_write_4(bus_tag, bus_handle, offset, value);
else if (size == 2)
bus_space_write_2(bus_tag, bus_handle, offset, (TW_INT16)value);
else
bus_space_write_1(bus_tag, bus_handle, offset, (TW_INT8)value);
}
#ifdef TW_OSL_PCI_CONFIG_ACCESSIBLE
/*
* Function name: tw_osl_read_pci_config
* Description: Reads from the PCI config space.
*
* Input: sc -- ptr to per ctlr structure
* offset -- register offset
* size -- # of bytes to be read
* Output: None
* Return value: Value read
*/
#define tw_osl_read_pci_config(ctlr_handle, offset, size) \
pci_read_config( \
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_dev, \
offset, size)
/*
* Function name: tw_osl_write_pci_config
* Description: Writes to the PCI config space.
*
* Input: sc -- ptr to per ctlr structure
* offset -- register offset
* value -- value to write
* size -- # of bytes to be written
* Output: None
* Return value: None
*/
#define tw_osl_write_pci_config(ctlr_handle, offset, value, size) \
pci_write_config( \
((struct twa_softc *)(ctlr_handle->osl_ctlr_ctxt))->bus_dev, \
offset/*PCIR_STATUS*/, value, size)
#endif /* TW_OSL_PCI_CONFIG_ACCESSIBLE */
/*
* Function name: tw_osl_get_local_time
* Description: Gets the local time
*
* Input: None
* Output: None
* Return value: local time
*/
#define tw_osl_get_local_time() \
(time_second - utc_offset())
/*
* Function name: tw_osl_delay
* Description: Spin for the specified time
*
* Input: usecs -- micro-seconds to spin
* Output: None
* Return value: None
*/
#define tw_osl_delay(usecs) DELAY(usecs)
#ifdef TW_OSL_CAN_SLEEP
/*
* Function name: tw_osl_sleep
* Description: Sleep for the specified time, or until woken up
*
* Input: ctlr_handle -- controller handle
* sleep_handle -- handle to sleep on
* timeout -- time period (in ms) to sleep
* Output: None
* Return value: 0 -- successfully woken up
* EWOULDBLOCK -- time out
* ERESTART -- woken up by a signal
*/
#define tw_osl_sleep(ctlr_handle, sleep_handle, timeout) \
tsleep((TW_VOID *)sleep_handle, PRIBIO, NULL, timeout)
/*
* Function name: tw_osl_wakeup
* Description: Wake up a sleeping process
*
* Input: ctlr_handle -- controller handle
* sleep_handle -- handle of sleeping process to be
woken up
* Output: None
* Return value: None
*/
#define tw_osl_wakeup(ctlr_handle, sleep_handle) \
wakeup_one(sleep_handle)
#endif /* TW_OSL_CAN_SLEEP */
/* Allows setting breakpoints in the CL code for debugging purposes. */
#define tw_osl_breakpoint() breakpoint()
/* Text name of current function. */
#define tw_osl_cur_func() __func__
/* Copy 'size' bytes from 'src' to 'dest'. */
#define tw_osl_memcpy(dest, src, size) bcopy(src, dest, size)
/* Zero 'size' bytes starting at 'addr'. */
#define tw_osl_memzero bzero
/* Standard sprintf. */
#define tw_osl_sprintf sprintf
/* Copy string 'src' to 'dest'. */
#define tw_osl_strcpy strcpy
/* Return length of string pointed at by 'str'. */
#define tw_osl_strlen strlen
/* Standard vsprintf. */
#define tw_osl_vsprintf vsprintf
#endif /* TW_OSL_INLINE_H */

View file

@ -1,108 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap.
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
*/
#ifndef TW_OSL_IOCTL_H
#define TW_OSL_IOCTL_H
/*
* Macros and structures for OS Layer/Common Layer handled ioctls.
*/
#include <dev/twa/tw_cl_fwif.h>
#include <dev/twa/tw_cl_ioctl.h>
#pragma pack(1)
/*
* 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 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 tw_osli_ioctl_no_data_buf {
struct tw_cl_driver_packet driver_pkt;
TW_VOID *pdata; /* points to data_buf */
TW_INT8 padding[488 - sizeof(TW_VOID *)];
struct tw_cl_command_packet cmd_pkt;
} TW_OSLI_IOCTL_NO_DATA_BUF;
#pragma pack()
/* ioctl cmds handled by the OS Layer */
#define TW_OSL_IOCTL_SCAN_BUS \
_IO('T', 200)
#define TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH \
_IOWR('T', 202, TW_OSLI_IOCTL_NO_DATA_BUF)
#include <sys/ioccom.h>
#pragma pack(1)
typedef struct tw_osli_ioctl_with_payload {
struct tw_cl_driver_packet driver_pkt;
TW_INT8 padding[488];
struct tw_cl_command_packet cmd_pkt;
union {
struct tw_cl_event_packet event_pkt;
struct tw_cl_lock_packet lock_pkt;
struct tw_cl_compatibility_packet compat_pkt;
TW_INT8 data_buf[1];
} payload;
} TW_OSLI_IOCTL_WITH_PAYLOAD;
#pragma pack()
/* ioctl cmds handled by the Common Layer */
#define TW_CL_IOCTL_GET_FIRST_EVENT \
_IOWR('T', 203, TW_OSLI_IOCTL_WITH_PAYLOAD)
#define TW_CL_IOCTL_GET_LAST_EVENT \
_IOWR('T', 204, TW_OSLI_IOCTL_WITH_PAYLOAD)
#define TW_CL_IOCTL_GET_NEXT_EVENT \
_IOWR('T', 205, TW_OSLI_IOCTL_WITH_PAYLOAD)
#define TW_CL_IOCTL_GET_PREVIOUS_EVENT \
_IOWR('T', 206, TW_OSLI_IOCTL_WITH_PAYLOAD)
#define TW_CL_IOCTL_GET_LOCK \
_IOWR('T', 207, TW_OSLI_IOCTL_WITH_PAYLOAD)
#define TW_CL_IOCTL_RELEASE_LOCK \
_IOWR('T', 208, TW_OSLI_IOCTL_WITH_PAYLOAD)
#define TW_CL_IOCTL_GET_COMPATIBILITY_INFO \
_IOWR('T', 209, TW_OSLI_IOCTL_WITH_PAYLOAD)
#endif /* TW_OSL_IOCTL_H */

View file

@ -1,107 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap.
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
*/
#ifndef TW_OSL_SHARE_H
#define TW_OSL_SHARE_H
/*
* Macros, structures and functions shared between OSL and CL,
* and defined by OSL.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/clock.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sysctl.h>
#include <sys/bus.h>
#include <sys/taskqueue.h>
#include <machine/bus.h>
#include <machine/endian.h>
#include <machine/stdarg.h>
#include <dev/pci/pcivar.h>
#include <dev/twa/tw_osl_types.h>
#include "opt_twa.h"
#ifdef TWA_DEBUG
#define TW_OSL_DEBUG TWA_DEBUG
#endif
#ifdef TWA_ENCLOSURE_SUPPORT
#define TW_OSL_ENCLOSURE_SUPPORT
#endif
#define TW_OSL_DRIVER_VERSION_STRING "3.80.06.003"
#define TW_OSL_CAN_SLEEP
#ifdef TW_OSL_CAN_SLEEP
typedef TW_VOID *TW_SLEEP_HANDLE;
#endif /* TW_OSL_CAN_SLEEP */
#define TW_OSL_PCI_CONFIG_ACCESSIBLE
#if _BYTE_ORDER == _BIG_ENDIAN
#define TW_OSL_BIG_ENDIAN
#else
#define TW_OSL_LITTLE_ENDIAN
#endif
#ifdef TW_OSL_DEBUG
extern TW_INT32 TW_OSL_DEBUG_LEVEL_FOR_CL;
#endif /* TW_OSL_DEBUG */
/* Possible return codes from/to Common Layer functions. */
#define TW_OSL_ESUCCESS 0 /* success */
#define TW_OSL_EGENFAILURE 1 /* general failure */
#define TW_OSL_ENOMEM ENOMEM /* insufficient memory */
#define TW_OSL_EIO EIO /* I/O error */
#define TW_OSL_ETIMEDOUT ETIMEDOUT /* time out */
#define TW_OSL_ENOTTY ENOTTY /* invalid command */
#define TW_OSL_EBUSY EBUSY /* busy -- try later */
#define TW_OSL_EBIG EFBIG /* request too big */
#define TW_OSL_EWOULDBLOCK EWOULDBLOCK /* sleep timed out */
#define TW_OSL_ERESTART ERESTART /* sleep terminated by a signal */
#endif /* TW_OSL_SHARE_H */

View file

@ -1,60 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2004-07 Applied Micro Circuits Corporation.
* Copyright (c) 2004-05 Vinod Kashyap.
* 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$
*/
/*
* AMCC'S 3ware driver for 9000 series storage controllers.
*
* Author: Vinod Kashyap
* Modifications by: Adam Radford
*/
#ifndef TW_OSL_TYPES_H
#define TW_OSL_TYPES_H
/*
* typedefs shared between OSL and CL, and defined by OSL.
*/
typedef void TW_VOID;
typedef char TW_INT8;
typedef unsigned char TW_UINT8;
typedef short TW_INT16;
typedef unsigned short TW_UINT16;
typedef int TW_INT32;
typedef unsigned int TW_UINT32;
typedef long long TW_INT64;
typedef unsigned long long TW_UINT64;
typedef time_t TW_TIME;
typedef struct mtx TW_LOCK_HANDLE;
#endif /* TW_OSL_TYPES_H */

View file

@ -156,7 +156,6 @@ device ses # Enclosure Services (SES and SAF-TE)
device arcmsr # Areca SATA II RAID
device ciss # Compaq Smart RAID 5*
device ips # IBM (Adaptec) ServeRAID
device twa # 3ware 9000 series PATA/SATA RAID
device tws # LSI 3ware 9750 SATA+SAS 6Gb/s RAID controller
# RAID controllers

View file

@ -614,13 +614,6 @@ device pst
#
device arcmsr # Areca SATA II RAID
#
# 3ware 9000 series PATA/SATA RAID controller driver and options.
# The driver is implemented as a SIM, and so, needs the CAM infrastructure.
#
options TWA_DEBUG # 0-10; 10 prints the most messages.
device twa # 3ware 9000 series PATA/SATA RAID
#
# Adaptec FSA RAID controllers, including integrated DELL controllers,
# the Dell PERC 2/QC and the HP NetRAID-4M

View file

@ -361,7 +361,6 @@ SUBDIR= \
tmpfs \
${_toecore} \
${_tpm} \
${_twa} \
twe \
tws \
uart \
@ -719,7 +718,6 @@ _s3= s3
_sdhci_acpi= sdhci_acpi
_superio= superio
_tpm= tpm
_twa= twa
_vesa= vesa
_viawd= viawd
_vmd= vmd

View file

@ -1,47 +0,0 @@
# $FreeBSD$
#
# Copyright (c) 2004-06 Applied Micro Circuits Corporation.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 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.
#
#
# 3ware driver for 9000 series storage controllers.
#
# Author: Vinod Kashyap
# Modifications by: Adam Radford
#
KMOD = twa
.PATH: ${SRCTOP}/sys/dev/${KMOD}
SRCS= tw_osl_freebsd.c tw_osl_cam.c \
tw_cl_init.c tw_cl_io.c tw_cl_intr.c tw_cl_misc.c \
bus_if.h device_if.h pci_if.h opt_scsi.h opt_cam.h opt_twa.h
# Uncomment the following line to turn on Enclosure Services support.
#CFLAGS+= -DTWA_ENCLOSURE_SUPPORT
#CFLAGS+= -DTWA_DEBUG=0
CFLAGS+= -I${SRCTOP}/sys/dev/${KMOD}
.include <bsd.kmod.mk>

View file

@ -1,21 +0,0 @@
# Doxyfile 1.5.2
# $FreeBSD$
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = "FreeBSD kernel TWA device code"
OUTPUT_DIRECTORY = $(DOXYGEN_DEST_PATH)/dev_twa/
EXTRACT_ALL = YES # for undocumented src, no warnings enabled
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = $(DOXYGEN_SRC_PATH)/dev/twa/ \
$(NOTREVIEWED)
GENERATE_TAGFILE = dev_twa/dev_twa.tag
@INCLUDE_PATH = $(DOXYGEN_INCLUDE_PATH)
@INCLUDE = common-Doxyfile