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:
parent
0d5935af8f
commit
8722e05ae1
@ -552,7 +552,6 @@ MAN= aac.4 \
|
||||
${_tpm.4} \
|
||||
tty.4 \
|
||||
tun.4 \
|
||||
twa.4 \
|
||||
twe.4 \
|
||||
tws.4 \
|
||||
udp.4 \
|
||||
|
@ -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 .
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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);
|
||||
}
|
@ -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
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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);
|
||||
}
|
@ -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
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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 */
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user