Revert "nvme: Separate total failures from I/O failures"

All kinds of crazy stuff was mixed into this commit. Revert
it and do it again.

This reverts commit d5507f9e43.

Sponsored by:		Netflix
This commit is contained in:
Warner Losh 2024-08-15 21:29:53 -06:00
parent a233cb6914
commit ce7fac64ba
24 changed files with 28 additions and 16219 deletions

View file

@ -1,2 +0,0 @@
include "GENERIC"
options CAM_IOSCHED_DYNAMIC

View file

@ -1,10 +0,0 @@
include GENERIC
device mpi3mr
# All the debugging options
options DEADLKRES # Enable the deadlock resolver
options INVARIANTS # Enable calls of extra sanity checking
options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
options QUEUE_MACRO_DEBUG_TRASH # Trash queue(2) internal pointers on invalidation
options WITNESS # Enable checks to detect deadlocks and cycles
options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed

View file

@ -1,4 +0,0 @@
include "GENERIC"
ident GENERIC_16K

View file

@ -1,117 +0,0 @@
/*-
* Copyright (c) 2010 Isilon Systems, Inc.
* Copyright (c) 2010 iX Systems, Inc.
* Copyright (c) 2010 Panasas, Inc.
* Copyright (c) 2013-2016 Mellanox Technologies, Ltd.
* Copyright (c) 2015 François Tigeot
* 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 unmodified, 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$
*/
#ifndef _LINUX_COMPILER_H_
#define _LINUX_COMPILER_H_
#include <sys/cdefs.h>
#define __user
#define __kernel
#define __safe
#define __force
#define __nocast
#define __iomem
#define __chk_user_ptr(x) ((void)0)
#define __chk_io_ptr(x) ((void)0)
#define __builtin_warning(x, y...) (1)
#define __acquires(x)
#define __releases(x)
#define __acquire(x) do { } while (0)
#define __release(x) do { } while (0)
#define __cond_lock(x,c) (c)
#define __bitwise
#define __devinitdata
#define __deprecated
#define __init
#define __initconst
#define __devinit
#define __devexit
#define __exit
#define __rcu
#define __percpu
#define __weak __weak_symbol
#define __malloc
#define ___stringify(...) #__VA_ARGS__
#define __stringify(...) ___stringify(__VA_ARGS__)
#define __attribute_const__ __attribute__((__const__))
#undef __always_inline
#define __always_inline inline
#define noinline __noinline
#define ____cacheline_aligned __aligned(CACHE_LINE_SIZE)
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define typeof(x) __typeof(x)
#define uninitialized_var(x) x = x
#define __maybe_unused __unused
#define __always_unused __unused
#define __must_check __result_use_check
#define __printf(a,b) __printflike(a,b)
#define barrier() __asm__ __volatile__("": : :"memory")
#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 50000
/* Moved from drm_os_freebsd.h */
#define lower_32_bits(n) ((u32)(n))
#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
#endif
#define ___PASTE(a,b) a##b
#define __PASTE(a,b) ___PASTE(a,b)
#define ACCESS_ONCE(x) (*(volatile __typeof(x) *)&(x))
#define WRITE_ONCE(x,v) do { \
barrier(); \
ACCESS_ONCE(x) = (v); \
barrier(); \
} while (0)
#define READ_ONCE(x) ({ \
__typeof(x) __var = ({ \
barrier(); \
ACCESS_ONCE(x); \
}); \
barrier(); \
__var; \
})
#define lockless_dereference(p) READ_ONCE(p)
#define _AT(T,X) ((T)(X))
#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
#define __must_be_array(a) __same_type(a, &(a)[0])
#endif /* _LINUX_COMPILER_H_ */

View file

@ -1,35 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2019-2020 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
#ifndef __iwl_fw_api_soc_h__
#define __iwl_fw_api_soc_h__
#define SOC_CONFIG_CMD_FLAGS_DISCRETE BIT(0)
#define SOC_CONFIG_CMD_FLAGS_LOW_LATENCY BIT(1)
#define SOC_FLAGS_LTR_APPLY_DELAY_MASK 0xc
#define SOC_FLAGS_LTR_APPLY_DELAY_NONE 0
#define SOC_FLAGS_LTR_APPLY_DELAY_200 1
#define SOC_FLAGS_LTR_APPLY_DELAY_2500 2
#define SOC_FLAGS_LTR_APPLY_DELAY_1820 3
/**
* struct iwl_soc_configuration_cmd - Set device stabilization latency
*
* @flags: soc settings flags. In VER_1, we can only set the DISCRETE
* flag, because the FW treats the whole value as an integer. In
* VER_2, we can set the bits independently.
* @latency: time for SOC to ensure stable power & XTAL
*/
struct iwl_soc_configuration_cmd {
__le32 flags;
__le32 latency;
} __packed; /*
* SOC_CONFIGURATION_CMD_S_VER_1 (see description above)
* SOC_CONFIGURATION_CMD_S_VER_2
*/
#endif /* __iwl_fw_api_soc_h__ */

View file

@ -1,51 +0,0 @@
This is a patched version of zlib, modified to use
Pentium-Pro-optimized assembly code in the deflation algorithm. The
files changed/added by this patch are:
README.686
match.S
The speedup that this patch provides varies, depending on whether the
compiler used to build the original version of zlib falls afoul of the
PPro's speed traps. My own tests show a speedup of around 10-20% at
the default compression level, and 20-30% using -9, against a version
compiled using gcc 2.7.2.3. Your mileage may vary.
Note that this code has been tailored for the PPro/PII in particular,
and will not perform particuarly well on a Pentium.
If you are using an assembler other than GNU as, you will have to
translate match.S to use your assembler's syntax. (Have fun.)
Brian Raiter
breadbox@muppetlabs.com
April, 1998
Added for zlib 1.1.3:
The patches come from
http://www.muppetlabs.com/~breadbox/software/assembly.html
To compile zlib with this asm file, copy match.S to the zlib directory
then do:
CFLAGS="-O3 -DASMV" ./configure
make OBJA=match.o
Update:
I've been ignoring these assembly routines for years, believing that
gcc's generated code had caught up with it sometime around gcc 2.95
and the major rearchitecting of the Pentium 4. However, I recently
learned that, despite what I believed, this code still has some life
in it. On the Pentium 4 and AMD64 chips, it continues to run about 8%
faster than the code produced by gcc 4.1.
In acknowledgement of its continuing usefulness, I've altered the
license to match that of the rest of zlib. Share and Enjoy!
Brian Raiter
breadbox@muppetlabs.com
April, 2007

View file

@ -1,357 +0,0 @@
/* match.S -- x86 assembly version of the zlib longest_match() function.
* Optimized for the Intel 686 chips (PPro and later).
*
* Copyright (C) 1998, 2007 Brian Raiter <breadbox@muppetlabs.com>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the author be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef NO_UNDERLINE
#define match_init _match_init
#define longest_match _longest_match
#endif
#define MAX_MATCH (258)
#define MIN_MATCH (3)
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
/* stack frame offsets */
#define chainlenwmask 0 /* high word: current chain len */
/* low word: s->wmask */
#define window 4 /* local copy of s->window */
#define windowbestlen 8 /* s->window + bestlen */
#define scanstart 16 /* first two bytes of string */
#define scanend 12 /* last two bytes of string */
#define scanalign 20 /* dword-misalignment of string */
#define nicematch 24 /* a good enough match size */
#define bestlen 28 /* size of best match so far */
#define scan 32 /* ptr to string wanting match */
#define LocalVarsSize (36)
/* saved ebx 36 */
/* saved edi 40 */
/* saved esi 44 */
/* saved ebp 48 */
/* return address 52 */
#define deflatestate 56 /* the function arguments */
#define curmatch 60
/* All the +zlib1222add offsets are due to the addition of fields
* in zlib in the deflate_state structure since the asm code was first written
* (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
* (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
* if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
*/
#define zlib1222add (8)
#define dsWSize (36+zlib1222add)
#define dsWMask (44+zlib1222add)
#define dsWindow (48+zlib1222add)
#define dsPrev (56+zlib1222add)
#define dsMatchLen (88+zlib1222add)
#define dsPrevMatch (92+zlib1222add)
#define dsStrStart (100+zlib1222add)
#define dsMatchStart (104+zlib1222add)
#define dsLookahead (108+zlib1222add)
#define dsPrevLen (112+zlib1222add)
#define dsMaxChainLen (116+zlib1222add)
#define dsGoodMatch (132+zlib1222add)
#define dsNiceMatch (136+zlib1222add)
.file "match.S"
.globl match_init, longest_match
.text
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
.cfi_sections .debug_frame
longest_match:
.cfi_startproc
/* Save registers that the compiler may be using, and adjust %esp to */
/* make room for our stack frame. */
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset ebp, -8
pushl %edi
.cfi_def_cfa_offset 12
pushl %esi
.cfi_def_cfa_offset 16
pushl %ebx
.cfi_def_cfa_offset 20
subl $LocalVarsSize, %esp
.cfi_def_cfa_offset LocalVarsSize+20
/* Retrieve the function arguments. %ecx will hold cur_match */
/* throughout the entire function. %edx will hold the pointer to the */
/* deflate_state structure during the function's setup (before */
/* entering the main loop). */
movl deflatestate(%esp), %edx
movl curmatch(%esp), %ecx
/* uInt wmask = s->w_mask; */
/* unsigned chain_length = s->max_chain_length; */
/* if (s->prev_length >= s->good_match) { */
/* chain_length >>= 2; */
/* } */
movl dsPrevLen(%edx), %eax
movl dsGoodMatch(%edx), %ebx
cmpl %ebx, %eax
movl dsWMask(%edx), %eax
movl dsMaxChainLen(%edx), %ebx
jl LastMatchGood
shrl $2, %ebx
LastMatchGood:
/* chainlen is decremented once beforehand so that the function can */
/* use the sign flag instead of the zero flag for the exit test. */
/* It is then shifted into the high word, to make room for the wmask */
/* value, which it will always accompany. */
decl %ebx
shll $16, %ebx
orl %eax, %ebx
movl %ebx, chainlenwmask(%esp)
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
movl dsNiceMatch(%edx), %eax
movl dsLookahead(%edx), %ebx
cmpl %eax, %ebx
jl LookaheadLess
movl %eax, %ebx
LookaheadLess: movl %ebx, nicematch(%esp)
/* register Bytef *scan = s->window + s->strstart; */
movl dsWindow(%edx), %esi
movl %esi, window(%esp)
movl dsStrStart(%edx), %ebp
lea (%esi,%ebp), %edi
movl %edi, scan(%esp)
/* Determine how many bytes the scan ptr is off from being */
/* dword-aligned. */
movl %edi, %eax
negl %eax
andl $3, %eax
movl %eax, scanalign(%esp)
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
movl dsWSize(%edx), %eax
subl $MIN_LOOKAHEAD, %eax
subl %eax, %ebp
jg LimitPositive
xorl %ebp, %ebp
LimitPositive:
/* int best_len = s->prev_length; */
movl dsPrevLen(%edx), %eax
movl %eax, bestlen(%esp)
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
addl %eax, %esi
movl %esi, windowbestlen(%esp)
/* register ush scan_start = *(ushf*)scan; */
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
/* Posf *prev = s->prev; */
movzwl (%edi), %ebx
movl %ebx, scanstart(%esp)
movzwl -1(%edi,%eax), %ebx
movl %ebx, scanend(%esp)
movl dsPrev(%edx), %edi
/* Jump into the main loop. */
movl chainlenwmask(%esp), %edx
jmp LoopEntry
.balign 16
/* do {
* match = s->window + cur_match;
* if (*(ushf*)(match+best_len-1) != scan_end ||
* *(ushf*)match != scan_start) continue;
* [...]
* } while ((cur_match = prev[cur_match & wmask]) > limit
* && --chain_length != 0);
*
* Here is the inner loop of the function. The function will spend the
* majority of its time in this loop, and majority of that time will
* be spent in the first ten instructions.
*
* Within this loop:
* %ebx = scanend
* %ecx = curmatch
* %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
* %esi = windowbestlen - i.e., (window + bestlen)
* %edi = prev
* %ebp = limit
*/
LookupLoop:
andl %edx, %ecx
movzwl (%edi,%ecx,2), %ecx
cmpl %ebp, %ecx
jbe LeaveNow
subl $0x00010000, %edx
js LeaveNow
LoopEntry: movzwl -1(%esi,%ecx), %eax
cmpl %ebx, %eax
jnz LookupLoop
movl window(%esp), %eax
movzwl (%eax,%ecx), %eax
cmpl scanstart(%esp), %eax
jnz LookupLoop
/* Store the current value of chainlen. */
movl %edx, chainlenwmask(%esp)
/* Point %edi to the string under scrutiny, and %esi to the string we */
/* are hoping to match it up with. In actuality, %esi and %edi are */
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
/* initialized to -(MAX_MATCH_8 - scanalign). */
movl window(%esp), %esi
movl scan(%esp), %edi
addl %ecx, %esi
movl scanalign(%esp), %eax
movl $(-MAX_MATCH_8), %edx
lea MAX_MATCH_8(%edi,%eax), %edi
lea MAX_MATCH_8(%esi,%eax), %esi
/* Test the strings for equality, 8 bytes at a time. At the end,
* adjust %edx so that it is offset to the exact byte that mismatched.
*
* We already know at this point that the first three bytes of the
* strings match each other, and they can be safely passed over before
* starting the compare loop. So what this code does is skip over 0-3
* bytes, as much as necessary in order to dword-align the %edi
* pointer. (%esi will still be misaligned three times out of four.)
*
* It should be confessed that this loop usually does not represent
* much of the total running time. Replacing it with a more
* straightforward "rep cmpsb" would not drastically degrade
* performance.
*/
LoopCmps:
movl (%esi,%edx), %eax
xorl (%edi,%edx), %eax
jnz LeaveLoopCmps
movl 4(%esi,%edx), %eax
xorl 4(%edi,%edx), %eax
jnz LeaveLoopCmps4
addl $8, %edx
jnz LoopCmps
jmp LenMaximum
LeaveLoopCmps4: addl $4, %edx
LeaveLoopCmps: testl $0x0000FFFF, %eax
jnz LenLower
addl $2, %edx
shrl $16, %eax
LenLower: subb $1, %al
adcl $0, %edx
/* Calculate the length of the match. If it is longer than MAX_MATCH, */
/* then automatically accept it as the best possible match and leave. */
lea (%edi,%edx), %eax
movl scan(%esp), %edi
subl %edi, %eax
cmpl $MAX_MATCH, %eax
jge LenMaximum
/* If the length of the match is not longer than the best match we */
/* have so far, then forget it and return to the lookup loop. */
movl deflatestate(%esp), %edx
movl bestlen(%esp), %ebx
cmpl %ebx, %eax
jg LongerMatch
movl windowbestlen(%esp), %esi
movl dsPrev(%edx), %edi
movl scanend(%esp), %ebx
movl chainlenwmask(%esp), %edx
jmp LookupLoop
/* s->match_start = cur_match; */
/* best_len = len; */
/* if (len >= nice_match) break; */
/* scan_end = *(ushf*)(scan+best_len-1); */
LongerMatch: movl nicematch(%esp), %ebx
movl %eax, bestlen(%esp)
movl %ecx, dsMatchStart(%edx)
cmpl %ebx, %eax
jge LeaveNow
movl window(%esp), %esi
addl %eax, %esi
movl %esi, windowbestlen(%esp)
movzwl -1(%edi,%eax), %ebx
movl dsPrev(%edx), %edi
movl %ebx, scanend(%esp)
movl chainlenwmask(%esp), %edx
jmp LookupLoop
/* Accept the current string, with the maximum possible length. */
LenMaximum: movl deflatestate(%esp), %edx
movl $MAX_MATCH, bestlen(%esp)
movl %ecx, dsMatchStart(%edx)
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
/* return s->lookahead; */
LeaveNow:
movl deflatestate(%esp), %edx
movl bestlen(%esp), %ebx
movl dsLookahead(%edx), %eax
cmpl %eax, %ebx
jg LookaheadRet
movl %ebx, %eax
LookaheadRet:
/* Restore the stack and return from whence we came. */
addl $LocalVarsSize, %esp
.cfi_def_cfa_offset 20
popl %ebx
.cfi_def_cfa_offset 16
popl %esi
.cfi_def_cfa_offset 12
popl %edi
.cfi_def_cfa_offset 8
popl %ebp
.cfi_def_cfa_offset 4
.cfi_endproc
match_init: ret

View file

@ -1,595 +0,0 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/* Copyright (c) 2021, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "ice_common.h"
#include "ice_sriov.h"
/**
* ice_aq_send_msg_to_vf
* @hw: pointer to the hardware structure
* @vfid: VF ID to send msg
* @v_opcode: opcodes for VF-PF communication
* @v_retval: return error code
* @msg: pointer to the msg buffer
* @msglen: msg length
* @cd: pointer to command details
*
* Send message to VF driver (0x0802) using mailbox
* queue and asynchronously sending message via
* ice_sq_send_cmd() function
*/
enum ice_status
ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval,
u8 *msg, u16 msglen, struct ice_sq_cd *cd)
{
struct ice_aqc_pf_vf_msg *cmd;
struct ice_aq_desc desc;
ice_fill_dflt_direct_cmd_desc(&desc, ice_mbx_opc_send_msg_to_vf);
cmd = &desc.params.virt;
cmd->id = CPU_TO_LE32(vfid);
desc.cookie_high = CPU_TO_LE32(v_opcode);
desc.cookie_low = CPU_TO_LE32(v_retval);
if (msglen)
desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
return ice_sq_send_cmd(hw, &hw->mailboxq, &desc, msg, msglen, cd);
}
/**
* ice_aq_send_msg_to_pf
* @hw: pointer to the hardware structure
* @v_opcode: opcodes for VF-PF communication
* @v_retval: return error code
* @msg: pointer to the msg buffer
* @msglen: msg length
* @cd: pointer to command details
*
* Send message to PF driver using mailbox queue. By default, this
* message is sent asynchronously, i.e. ice_sq_send_cmd()
* does not wait for completion before returning.
*/
enum ice_status
ice_aq_send_msg_to_pf(struct ice_hw *hw, enum virtchnl_ops v_opcode,
enum ice_status v_retval, u8 *msg, u16 msglen,
struct ice_sq_cd *cd)
{
struct ice_aq_desc desc;
ice_fill_dflt_direct_cmd_desc(&desc, ice_mbx_opc_send_msg_to_pf);
desc.cookie_high = CPU_TO_LE32(v_opcode);
desc.cookie_low = CPU_TO_LE32(v_retval);
if (msglen)
desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
return ice_sq_send_cmd(hw, &hw->mailboxq, &desc, msg, msglen, cd);
}
/**
* ice_conv_link_speed_to_virtchnl
* @adv_link_support: determines the format of the returned link speed
* @link_speed: variable containing the link_speed to be converted
*
* Convert link speed supported by HW to link speed supported by virtchnl.
* If adv_link_support is true, then return link speed in Mbps. Else return
* link speed as a VIRTCHNL_LINK_SPEED_* casted to a u32. Note that the caller
* needs to cast back to an enum virtchnl_link_speed in the case where
* adv_link_support is false, but when adv_link_support is true the caller can
* expect the speed in Mbps.
*/
u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed)
{
u32 speed;
if (adv_link_support)
switch (link_speed) {
case ICE_AQ_LINK_SPEED_10MB:
speed = ICE_LINK_SPEED_10MBPS;
break;
case ICE_AQ_LINK_SPEED_100MB:
speed = ICE_LINK_SPEED_100MBPS;
break;
case ICE_AQ_LINK_SPEED_1000MB:
speed = ICE_LINK_SPEED_1000MBPS;
break;
case ICE_AQ_LINK_SPEED_2500MB:
speed = ICE_LINK_SPEED_2500MBPS;
break;
case ICE_AQ_LINK_SPEED_5GB:
speed = ICE_LINK_SPEED_5000MBPS;
break;
case ICE_AQ_LINK_SPEED_10GB:
speed = ICE_LINK_SPEED_10000MBPS;
break;
case ICE_AQ_LINK_SPEED_20GB:
speed = ICE_LINK_SPEED_20000MBPS;
break;
case ICE_AQ_LINK_SPEED_25GB:
speed = ICE_LINK_SPEED_25000MBPS;
break;
case ICE_AQ_LINK_SPEED_40GB:
speed = ICE_LINK_SPEED_40000MBPS;
break;
case ICE_AQ_LINK_SPEED_50GB:
speed = ICE_LINK_SPEED_50000MBPS;
break;
case ICE_AQ_LINK_SPEED_100GB:
speed = ICE_LINK_SPEED_100000MBPS;
break;
default:
speed = ICE_LINK_SPEED_UNKNOWN;
break;
}
else
/* Virtchnl speeds are not defined for every speed supported in
* the hardware. To maintain compatibility with older AVF
* drivers, while reporting the speed the new speed values are
* resolved to the closest known virtchnl speeds
*/
switch (link_speed) {
case ICE_AQ_LINK_SPEED_10MB:
case ICE_AQ_LINK_SPEED_100MB:
speed = (u32)VIRTCHNL_LINK_SPEED_100MB;
break;
case ICE_AQ_LINK_SPEED_1000MB:
case ICE_AQ_LINK_SPEED_2500MB:
case ICE_AQ_LINK_SPEED_5GB:
speed = (u32)VIRTCHNL_LINK_SPEED_1GB;
break;
case ICE_AQ_LINK_SPEED_10GB:
speed = (u32)VIRTCHNL_LINK_SPEED_10GB;
break;
case ICE_AQ_LINK_SPEED_20GB:
speed = (u32)VIRTCHNL_LINK_SPEED_20GB;
break;
case ICE_AQ_LINK_SPEED_25GB:
speed = (u32)VIRTCHNL_LINK_SPEED_25GB;
break;
case ICE_AQ_LINK_SPEED_40GB:
case ICE_AQ_LINK_SPEED_50GB:
case ICE_AQ_LINK_SPEED_100GB:
speed = (u32)VIRTCHNL_LINK_SPEED_40GB;
break;
default:
speed = (u32)VIRTCHNL_LINK_SPEED_UNKNOWN;
break;
}
return speed;
}
/* The mailbox overflow detection algorithm helps to check if there
* is a possibility of a malicious VF transmitting too many MBX messages to the
* PF.
* 1. The mailbox snapshot structure, ice_mbx_snapshot, is initialized during
* driver initialization in ice_init_hw() using ice_mbx_init_snapshot().
* The struct ice_mbx_snapshot helps to track and traverse a static window of
* messages within the mailbox queue while looking for a malicious VF.
*
* 2. When the caller starts processing its mailbox queue in response to an
* interrupt, the structure ice_mbx_snapshot is expected to be cleared before
* the algorithm can be run for the first time for that interrupt. This can be
* done via ice_mbx_reset_snapshot().
*
* 3. For every message read by the caller from the MBX Queue, the caller must
* call the detection algorithm's entry function ice_mbx_vf_state_handler().
* Before every call to ice_mbx_vf_state_handler() the struct ice_mbx_data is
* filled as it is required to be passed to the algorithm.
*
* 4. Every time a message is read from the MBX queue, a VFId is received which
* is passed to the state handler. The boolean output is_malvf of the state
* handler ice_mbx_vf_state_handler() serves as an indicator to the caller
* whether this VF is malicious or not.
*
* 5. When a VF is identified to be malicious, the caller can send a message
* to the system administrator. The caller can invoke ice_mbx_report_malvf()
* to help determine if a malicious VF is to be reported or not. This function
* requires the caller to maintain a global bitmap to track all malicious VFs
* and pass that to ice_mbx_report_malvf() along with the VFID which was identified
* to be malicious by ice_mbx_vf_state_handler().
*
* 6. The global bitmap maintained by PF can be cleared completely if PF is in
* reset or the bit corresponding to a VF can be cleared if that VF is in reset.
* When a VF is shut down and brought back up, we assume that the new VF
* brought up is not malicious and hence report it if found malicious.
*
* 7. The function ice_mbx_reset_snapshot() is called to reset the information
* in ice_mbx_snapshot for every new mailbox interrupt handled.
*
* 8. The memory allocated for variables in ice_mbx_snapshot is de-allocated
* when driver is unloaded.
*/
#define ICE_RQ_DATA_MASK(rq_data) ((rq_data) & PF_MBX_ARQH_ARQH_M)
/* Using the highest value for an unsigned 16-bit value 0xFFFF to indicate that
* the max messages check must be ignored in the algorithm
*/
#define ICE_IGNORE_MAX_MSG_CNT 0xFFFF
/**
* ice_mbx_traverse - Pass through mailbox snapshot
* @hw: pointer to the HW struct
* @new_state: new algorithm state
*
* Traversing the mailbox static snapshot without checking
* for malicious VFs.
*/
static void
ice_mbx_traverse(struct ice_hw *hw,
enum ice_mbx_snapshot_state *new_state)
{
struct ice_mbx_snap_buffer_data *snap_buf;
u32 num_iterations;
snap_buf = &hw->mbx_snapshot.mbx_buf;
/* As mailbox buffer is circular, applying a mask
* on the incremented iteration count.
*/
num_iterations = ICE_RQ_DATA_MASK(++snap_buf->num_iterations);
/* Checking either of the below conditions to exit snapshot traversal:
* Condition-1: If the number of iterations in the mailbox is equal to
* the mailbox head which would indicate that we have reached the end
* of the static snapshot.
* Condition-2: If the maximum messages serviced in the mailbox for a
* given interrupt is the highest possible value then there is no need
* to check if the number of messages processed is equal to it. If not
* check if the number of messages processed is greater than or equal
* to the maximum number of mailbox entries serviced in current work item.
*/
if (num_iterations == snap_buf->head ||
(snap_buf->max_num_msgs_mbx < ICE_IGNORE_MAX_MSG_CNT &&
++snap_buf->num_msg_proc >= snap_buf->max_num_msgs_mbx))
*new_state = ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT;
}
/**
* ice_mbx_detect_malvf - Detect malicious VF in snapshot
* @hw: pointer to the HW struct
* @vf_id: relative virtual function ID
* @new_state: new algorithm state
* @is_malvf: boolean output to indicate if VF is malicious
*
* This function tracks the number of asynchronous messages
* sent per VF and marks the VF as malicious if it exceeds
* the permissible number of messages to send.
*/
static enum ice_status
ice_mbx_detect_malvf(struct ice_hw *hw, u16 vf_id,
enum ice_mbx_snapshot_state *new_state,
bool *is_malvf)
{
struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
if (vf_id >= snap->mbx_vf.vfcntr_len)
return ICE_ERR_OUT_OF_RANGE;
/* increment the message count in the VF array */
snap->mbx_vf.vf_cntr[vf_id]++;
if (snap->mbx_vf.vf_cntr[vf_id] >= ICE_ASYNC_VF_MSG_THRESHOLD)
*is_malvf = true;
/* continue to iterate through the mailbox snapshot */
ice_mbx_traverse(hw, new_state);
return ICE_SUCCESS;
}
/**
* ice_mbx_reset_snapshot - Reset mailbox snapshot structure
* @snap: pointer to mailbox snapshot structure in the ice_hw struct
*
* Reset the mailbox snapshot structure and clear VF counter array.
*/
static void ice_mbx_reset_snapshot(struct ice_mbx_snapshot *snap)
{
u32 vfcntr_len;
if (!snap || !snap->mbx_vf.vf_cntr)
return;
/* Clear VF counters. */
vfcntr_len = snap->mbx_vf.vfcntr_len;
if (vfcntr_len)
ice_memset(snap->mbx_vf.vf_cntr, 0,
(vfcntr_len * sizeof(*snap->mbx_vf.vf_cntr)),
ICE_NONDMA_MEM);
/* Reset mailbox snapshot for a new capture. */
ice_memset(&snap->mbx_buf, 0, sizeof(snap->mbx_buf),
ICE_NONDMA_MEM);
snap->mbx_buf.state = ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT;
}
/**
* ice_mbx_vf_state_handler - Handle states of the overflow algorithm
* @hw: pointer to the HW struct
* @mbx_data: pointer to structure containing mailbox data
* @vf_id: relative virtual function (VF) ID
* @is_malvf: boolean output to indicate if VF is malicious
*
* The function serves as an entry point for the malicious VF
* detection algorithm by handling the different states and state
* transitions of the algorithm:
* New snapshot: This state is entered when creating a new static
* snapshot. The data from any previous mailbox snapshot is
* cleared and a new capture of the mailbox head and tail is
* logged. This will be the new static snapshot to detect
* asynchronous messages sent by VFs. On capturing the snapshot
* and depending on whether the number of pending messages in that
* snapshot exceed the watermark value, the state machine enters
* traverse or detect states.
* Traverse: If pending message count is below watermark then iterate
* through the snapshot without any action on VF.
* Detect: If pending message count exceeds watermark traverse
* the static snapshot and look for a malicious VF.
*/
enum ice_status
ice_mbx_vf_state_handler(struct ice_hw *hw,
struct ice_mbx_data *mbx_data, u16 vf_id,
bool *is_malvf)
{
struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
struct ice_mbx_snap_buffer_data *snap_buf;
struct ice_ctl_q_info *cq = &hw->mailboxq;
enum ice_mbx_snapshot_state new_state;
enum ice_status status = ICE_SUCCESS;
if (!is_malvf || !mbx_data)
return ICE_ERR_BAD_PTR;
/* When entering the mailbox state machine assume that the VF
* is not malicious until detected.
*/
*is_malvf = false;
/* Checking if max messages allowed to be processed while servicing current
* interrupt is not less than the defined AVF message threshold.
*/
if (mbx_data->max_num_msgs_mbx <= ICE_ASYNC_VF_MSG_THRESHOLD)
return ICE_ERR_INVAL_SIZE;
/* The watermark value should not be lesser than the threshold limit
* set for the number of asynchronous messages a VF can send to mailbox
* nor should it be greater than the maximum number of messages in the
* mailbox serviced in current interrupt.
*/
if (mbx_data->async_watermark_val < ICE_ASYNC_VF_MSG_THRESHOLD ||
mbx_data->async_watermark_val > mbx_data->max_num_msgs_mbx)
return ICE_ERR_PARAM;
new_state = ICE_MAL_VF_DETECT_STATE_INVALID;
snap_buf = &snap->mbx_buf;
switch (snap_buf->state) {
case ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT:
/* Clear any previously held data in mailbox snapshot structure. */
ice_mbx_reset_snapshot(snap);
/* Collect the pending ARQ count, number of messages processed and
* the maximum number of messages allowed to be processed from the
* Mailbox for current interrupt.
*/
snap_buf->num_pending_arq = mbx_data->num_pending_arq;
snap_buf->num_msg_proc = mbx_data->num_msg_proc;
snap_buf->max_num_msgs_mbx = mbx_data->max_num_msgs_mbx;
/* Capture a new static snapshot of the mailbox by logging the
* head and tail of snapshot and set num_iterations to the tail
* value to mark the start of the iteration through the snapshot.
*/
snap_buf->head = ICE_RQ_DATA_MASK(cq->rq.next_to_clean +
mbx_data->num_pending_arq);
snap_buf->tail = ICE_RQ_DATA_MASK(cq->rq.next_to_clean - 1);
snap_buf->num_iterations = snap_buf->tail;
/* Pending ARQ messages returned by ice_clean_rq_elem
* is the difference between the head and tail of the
* mailbox queue. Comparing this value against the watermark
* helps to check if we potentially have malicious VFs.
*/
if (snap_buf->num_pending_arq >=
mbx_data->async_watermark_val) {
new_state = ICE_MAL_VF_DETECT_STATE_DETECT;
status = ice_mbx_detect_malvf(hw, vf_id, &new_state, is_malvf);
} else {
new_state = ICE_MAL_VF_DETECT_STATE_TRAVERSE;
ice_mbx_traverse(hw, &new_state);
}
break;
case ICE_MAL_VF_DETECT_STATE_TRAVERSE:
new_state = ICE_MAL_VF_DETECT_STATE_TRAVERSE;
ice_mbx_traverse(hw, &new_state);
break;
case ICE_MAL_VF_DETECT_STATE_DETECT:
new_state = ICE_MAL_VF_DETECT_STATE_DETECT;
status = ice_mbx_detect_malvf(hw, vf_id, &new_state, is_malvf);
break;
default:
new_state = ICE_MAL_VF_DETECT_STATE_INVALID;
status = ICE_ERR_CFG;
}
snap_buf->state = new_state;
return status;
}
/**
* ice_mbx_report_malvf - Track and note malicious VF
* @hw: pointer to the HW struct
* @all_malvfs: all malicious VFs tracked by PF
* @bitmap_len: length of bitmap in bits
* @vf_id: relative virtual function ID of the malicious VF
* @report_malvf: boolean to indicate if malicious VF must be reported
*
* This function will update a bitmap that keeps track of the malicious
* VFs attached to the PF. A malicious VF must be reported only once if
* discovered between VF resets or loading so the function checks
* the input vf_id against the bitmap to verify if the VF has been
* detected in any previous mailbox iterations.
*/
enum ice_status
ice_mbx_report_malvf(struct ice_hw *hw, ice_bitmap_t *all_malvfs,
u16 bitmap_len, u16 vf_id, bool *report_malvf)
{
if (!all_malvfs || !report_malvf)
return ICE_ERR_PARAM;
*report_malvf = false;
if (bitmap_len < hw->mbx_snapshot.mbx_vf.vfcntr_len)
return ICE_ERR_INVAL_SIZE;
if (vf_id >= bitmap_len)
return ICE_ERR_OUT_OF_RANGE;
/* If the vf_id is found in the bitmap set bit and boolean to true */
if (!ice_is_bit_set(all_malvfs, vf_id)) {
ice_set_bit(vf_id, all_malvfs);
ice_debug(hw, ICE_DBG_TRACE, "Malicious VF=%d found\n", vf_id);
*report_malvf = true;
}
return ICE_SUCCESS;
}
/**
* ice_mbx_clear_malvf - Clear VF bitmap and counter for VF ID
* @snap: pointer to the mailbox snapshot structure
* @all_malvfs: all malicious VFs tracked by PF
* @bitmap_len: length of bitmap in bits
* @vf_id: relative virtual function ID of the malicious VF
*
* In case of a VF reset, this function can be called to clear
* the bit corresponding to the VF ID in the bitmap tracking all
* malicious VFs attached to the PF. The function also clears the
* VF counter array at the index of the VF ID. This is to ensure
* that the new VF loaded is not considered malicious before going
* through the overflow detection algorithm.
*/
enum ice_status
ice_mbx_clear_malvf(struct ice_mbx_snapshot *snap, ice_bitmap_t *all_malvfs,
u16 bitmap_len, u16 vf_id)
{
if (!snap || !all_malvfs)
return ICE_ERR_PARAM;
if (bitmap_len < snap->mbx_vf.vfcntr_len)
return ICE_ERR_INVAL_SIZE;
/* Ensure VF ID value is not larger than bitmap or VF counter length */
if (vf_id >= bitmap_len || vf_id >= snap->mbx_vf.vfcntr_len)
return ICE_ERR_OUT_OF_RANGE;
/* Clear VF ID bit in the bitmap tracking malicious VFs attached to PF */
ice_clear_bit(vf_id, all_malvfs);
/* Clear the VF counter in the mailbox snapshot structure for that VF ID.
* This is to ensure that if a VF is unloaded and a new one brought back
* up with the same VF ID for a snapshot currently in traversal or detect
* state the counter for that VF ID does not increment on top of existing
* values in the mailbox overflow detection algorithm.
*/
snap->mbx_vf.vf_cntr[vf_id] = 0;
return ICE_SUCCESS;
}
/**
* ice_mbx_init_snapshot - Initialize mailbox snapshot structure
* @hw: pointer to the hardware structure
* @vf_count: number of VFs allocated on a PF
*
* Clear the mailbox snapshot structure and allocate memory
* for the VF counter array based on the number of VFs allocated
* on that PF.
*
* Assumption: This function will assume ice_get_caps() has already been
* called to ensure that the vf_count can be compared against the number
* of VFs supported as defined in the functional capabilities of the device.
*/
enum ice_status ice_mbx_init_snapshot(struct ice_hw *hw, u16 vf_count)
{
struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
/* Ensure that the number of VFs allocated is non-zero and
* is not greater than the number of supported VFs defined in
* the functional capabilities of the PF.
*/
if (!vf_count || vf_count > hw->func_caps.num_allocd_vfs)
return ICE_ERR_INVAL_SIZE;
snap->mbx_vf.vf_cntr =
(u32 *)ice_calloc(hw, vf_count,
sizeof(*snap->mbx_vf.vf_cntr));
if (!snap->mbx_vf.vf_cntr)
return ICE_ERR_NO_MEMORY;
/* Setting the VF counter length to the number of allocated
* VFs for given PF's functional capabilities.
*/
snap->mbx_vf.vfcntr_len = vf_count;
/* Clear mbx_buf in the mailbox snaphot structure and setting the
* mailbox snapshot state to a new capture.
*/
ice_memset(&snap->mbx_buf, 0, sizeof(snap->mbx_buf), ICE_NONDMA_MEM);
snap->mbx_buf.state = ICE_MAL_VF_DETECT_STATE_NEW_SNAPSHOT;
return ICE_SUCCESS;
}
/**
* ice_mbx_deinit_snapshot - Free mailbox snapshot structure
* @hw: pointer to the hardware structure
*
* Clear the mailbox snapshot structure and free the VF counter array.
*/
void ice_mbx_deinit_snapshot(struct ice_hw *hw)
{
struct ice_mbx_snapshot *snap = &hw->mbx_snapshot;
/* Free VF counter array and reset vf counter length */
ice_free(hw, snap->mbx_vf.vf_cntr);
snap->mbx_vf.vfcntr_len = 0;
/* Clear mbx_buf in the mailbox snaphot structure */
ice_memset(&snap->mbx_buf, 0, sizeof(snap->mbx_buf), ICE_NONDMA_MEM);
}

View file

@ -1,64 +0,0 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/* Copyright (c) 2021, Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
#ifndef _ICE_SRIOV_H_
#define _ICE_SRIOV_H_
#include "ice_type.h"
#include "ice_controlq.h"
/* Defining the mailbox message threshold as 63 asynchronous
* pending messages. Normal VF functionality does not require
* sending more than 63 asynchronous pending message.
*/
#define ICE_ASYNC_VF_MSG_THRESHOLD 63
enum ice_status
ice_aq_send_msg_to_pf(struct ice_hw *hw, enum virtchnl_ops v_opcode,
enum ice_status v_retval, u8 *msg, u16 msglen,
struct ice_sq_cd *cd);
enum ice_status
ice_aq_send_msg_to_vf(struct ice_hw *hw, u16 vfid, u32 v_opcode, u32 v_retval,
u8 *msg, u16 msglen, struct ice_sq_cd *cd);
u32 ice_conv_link_speed_to_virtchnl(bool adv_link_support, u16 link_speed);
enum ice_status
ice_mbx_vf_state_handler(struct ice_hw *hw, struct ice_mbx_data *mbx_data,
u16 vf_id, bool *is_mal_vf);
enum ice_status
ice_mbx_clear_malvf(struct ice_mbx_snapshot *snap, ice_bitmap_t *all_malvfs,
u16 bitmap_len, u16 vf_id);
enum ice_status ice_mbx_init_snapshot(struct ice_hw *hw, u16 vf_count);
void ice_mbx_deinit_snapshot(struct ice_hw *hw);
enum ice_status
ice_mbx_report_malvf(struct ice_hw *hw, ice_bitmap_t *all_malvfs,
u16 bitmap_len, u16 vf_id, bool *report_malvf);
#endif /* _ICE_SRIOV_H_ */

View file

@ -1,141 +0,0 @@
/*-
* Copyright 2000-2020 Broadcom Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* 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.
*
* Broadcom Inc. (LSI) MPT-Fusion Host Adapter FreeBSD
*
*/
/*
* Copyright 2000-2020 Broadcom Inc. All rights reserved.
*
*
* Name: mpi2_pci.h
* Title: MPI PCIe Attached Devices structures and definitions.
* Creation Date: October 9, 2012
*
* mpi2_pci.h Version: 02.00.03
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
* with MPI v2.0 products. Unless otherwise noted, names beginning with
* MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products.
*
* Version History
* ---------------
*
* Date Version Description
* -------- -------- ------------------------------------------------------
* 03-16-15 02.00.00 Initial version.
* 02-17-16 02.00.01 Removed AHCI support.
* Removed SOP support.
* 07-01-16 02.00.02 Added MPI26_NVME_FLAGS_FORCE_ADMIN_ERR_RESP to
* NVME Encapsulated Request.
* 07-22-18 02.00.03 Updted flags field for NVME Encapsulated req
* --------------------------------------------------------------------------
*/
#ifndef MPI2_PCI_H
#define MPI2_PCI_H
/*
* Values for the PCIe DeviceInfo field used in PCIe Device Status Change Event
* data and PCIe Configuration pages.
*/
#define MPI26_PCIE_DEVINFO_DIRECT_ATTACH (0x00000010)
#define MPI26_PCIE_DEVINFO_MASK_DEVICE_TYPE (0x0000000F)
#define MPI26_PCIE_DEVINFO_NO_DEVICE (0x00000000)
#define MPI26_PCIE_DEVINFO_PCI_SWITCH (0x00000001)
#define MPI26_PCIE_DEVINFO_NVME (0x00000003)
/****************************************************************************
* NVMe Encapsulated message
****************************************************************************/
/* NVME Encapsulated Request Message */
typedef struct _MPI26_NVME_ENCAPSULATED_REQUEST
{
U16 DevHandle; /* 0x00 */
U8 ChainOffset; /* 0x02 */
U8 Function; /* 0x03 */
U16 EncapsulatedCommandLength; /* 0x04 */
U8 Reserved1; /* 0x06 */
U8 MsgFlags; /* 0x07 */
U8 VP_ID; /* 0x08 */
U8 VF_ID; /* 0x09 */
U16 Reserved2; /* 0x0A */
U32 Reserved3; /* 0x0C */
U64 ErrorResponseBaseAddress; /* 0x10 */
U16 ErrorResponseAllocationLength; /* 0x18 */
U16 Flags; /* 0x1A */
U32 DataLength; /* 0x1C */
U8 NVMe_Command[4]; /* 0x20 */ /* variable length */
} MPI26_NVME_ENCAPSULATED_REQUEST, MPI2_POINTER PTR_MPI26_NVME_ENCAPSULATED_REQUEST,
Mpi26NVMeEncapsulatedRequest_t, MPI2_POINTER pMpi26NVMeEncapsulatedRequest_t;
/* defines for the Flags field */
#define MPI26_NVME_FLAGS_FORCE_ADMIN_ERR_RESP (0x0020)
/* Submission Queue Type*/
#define MPI26_NVME_FLAGS_SUBMISSIONQ_MASK (0x0010)
#define MPI26_NVME_FLAGS_SUBMISSIONQ_IO (0x0000)
#define MPI26_NVME_FLAGS_SUBMISSIONQ_ADMIN (0x0010)
/* Error Response Address Space */
#define MPI26_NVME_FLAGS_MASK_ERROR_RSP_ADDR (0x000C)
#define MPI26_NVME_FLAGS_MASK_ERROR_RSP_ADDR_MASK (0x000C)
#define MPI26_NVME_FLAGS_SYSTEM_RSP_ADDR (0x0000)
#define MPI26_NVME_FLAGS_IOCCTL_RSP_ADDR (0x0008)
/* Data Direction*/
#define MPI26_NVME_FLAGS_DATADIRECTION_MASK (0x0003)
#define MPI26_NVME_FLAGS_NODATATRANSFER (0x0000)
#define MPI26_NVME_FLAGS_WRITE (0x0001)
#define MPI26_NVME_FLAGS_READ (0x0002)
#define MPI26_NVME_FLAGS_BIDIRECTIONAL (0x0003)
/* NVMe Encapuslated Reply Message */
typedef struct _MPI26_NVME_ENCAPSULATED_ERROR_REPLY
{
U16 DevHandle; /* 0x00 */
U8 MsgLength; /* 0x02 */
U8 Function; /* 0x03 */
U16 EncapsulatedCommandLength; /* 0x04 */
U8 Reserved1; /* 0x06 */
U8 MsgFlags; /* 0x07 */
U8 VP_ID; /* 0x08 */
U8 VF_ID; /* 0x09 */
U16 Reserved2; /* 0x0A */
U16 Reserved3; /* 0x0C */
U16 IOCStatus; /* 0x0E */
U32 IOCLogInfo; /* 0x10 */
U16 ErrorResponseCount; /* 0x14 */
U16 Reserved4; /* 0x16 */
} MPI26_NVME_ENCAPSULATED_ERROR_REPLY,
MPI2_POINTER PTR_MPI26_NVME_ENCAPSULATED_ERROR_REPLY,
Mpi26NVMeEncapsulatedErrorReply_t,
MPI2_POINTER pMpi26NVMeEncapsulatedErrorReply_t;
#endif

View file

@ -232,7 +232,7 @@ nvme_ctrlr_construct_io_qpairs(struct nvme_controller *ctrlr)
}
static void
nvme_ctrlr_fail(struct nvme_controller *ctrlr, bool admin_also)
nvme_ctrlr_fail(struct nvme_controller *ctrlr)
{
int i;
@ -242,10 +242,7 @@ nvme_ctrlr_fail(struct nvme_controller *ctrlr, bool admin_also)
* a different error, though when we fail, that hardly matters).
*/
ctrlr->is_failed = true;
if (admin_also) {
ctrlr->is_failed_admin = true;
nvme_qpair_fail(&ctrlr->adminq);
}
nvme_qpair_fail(&ctrlr->adminq);
if (ctrlr->ioq != NULL) {
for (i = 0; i < ctrlr->num_io_queues; i++) {
nvme_qpair_fail(&ctrlr->ioq[i]);
@ -418,7 +415,6 @@ nvme_ctrlr_hw_reset(struct nvme_controller *ctrlr)
TSENTER();
ctrlr->is_failed_admin = true;
nvme_ctrlr_disable_qpairs(ctrlr);
err = nvme_ctrlr_disable(ctrlr);
@ -427,8 +423,6 @@ nvme_ctrlr_hw_reset(struct nvme_controller *ctrlr)
err = nvme_ctrlr_enable(ctrlr);
out:
if (err == 0)
ctrlr->is_failed_admin = false;
TSEXIT();
return (err);
@ -441,10 +435,11 @@ nvme_ctrlr_reset(struct nvme_controller *ctrlr)
cmpset = atomic_cmpset_32(&ctrlr->is_resetting, 0, 1);
if (cmpset == 0)
if (cmpset == 0 || ctrlr->is_failed)
/*
* Controller is already resetting. Return immediately since
* there is no need to kick off another reset.
* Controller is already resetting or has failed. Return
* immediately since there is no need to kick off another
* reset in these cases.
*/
return;
@ -1095,7 +1090,7 @@ nvme_ctrlr_start(void *ctrlr_arg, bool resetting)
return;
if (resetting && nvme_ctrlr_identify(ctrlr) != 0) {
nvme_ctrlr_fail(ctrlr, false);
nvme_ctrlr_fail(ctrlr);
return;
}
@ -1110,7 +1105,7 @@ nvme_ctrlr_start(void *ctrlr_arg, bool resetting)
if (resetting) {
old_num_io_queues = ctrlr->num_io_queues;
if (nvme_ctrlr_set_num_qpairs(ctrlr) != 0) {
nvme_ctrlr_fail(ctrlr, false);
nvme_ctrlr_fail(ctrlr);
return;
}
@ -1128,12 +1123,12 @@ nvme_ctrlr_start(void *ctrlr_arg, bool resetting)
nvme_ctrlr_hmb_enable(ctrlr, true, true);
if (nvme_ctrlr_create_qpairs(ctrlr) != 0) {
nvme_ctrlr_fail(ctrlr, false);
nvme_ctrlr_fail(ctrlr);
return;
}
if (nvme_ctrlr_construct_namespaces(ctrlr) != 0) {
nvme_ctrlr_fail(ctrlr, false);
nvme_ctrlr_fail(ctrlr);
return;
}
@ -1153,7 +1148,8 @@ nvme_ctrlr_start_config_hook(void *arg)
TSENTER();
if (nvme_ctrlr_hw_reset(ctrlr) != 0) {
nvme_ctrlr_fail(ctrlr, true);
fail:
nvme_ctrlr_fail(ctrlr);
config_intrhook_disestablish(&ctrlr->config_hook);
return;
}
@ -1166,15 +1162,13 @@ nvme_ctrlr_start_config_hook(void *arg)
nvme_ctrlr_construct_io_qpairs(ctrlr) == 0)
nvme_ctrlr_start(ctrlr, false);
else
nvme_ctrlr_fail(ctrlr, false);
goto fail;
nvme_sysctl_initialize_ctrlr(ctrlr);
config_intrhook_disestablish(&ctrlr->config_hook);
if (!ctrlr->is_failed) {
ctrlr->is_initialized = true;
nvme_notify_new_controller(ctrlr);
}
ctrlr->is_initialized = true;
nvme_notify_new_controller(ctrlr);
TSEXIT();
}
@ -1191,7 +1185,7 @@ nvme_ctrlr_reset_task(void *arg, int pending)
nvme_ctrlr_start(ctrlr, true);
} else {
nvme_ctrlr_devctl_log(ctrlr, "RESET", "event=\"timed_out\"");
nvme_ctrlr_fail(ctrlr, true);
nvme_ctrlr_fail(ctrlr);
}
atomic_cmpset_32(&ctrlr->is_resetting, 1, 0);
@ -1618,7 +1612,7 @@ nvme_ctrlr_destruct(struct nvme_controller *ctrlr, device_t dev)
*/
gone = (nvme_mmio_read_4(ctrlr, csts) == NVME_GONE);
if (gone)
nvme_ctrlr_fail(ctrlr, true);
nvme_ctrlr_fail(ctrlr);
else
nvme_notify_fail_consumers(ctrlr);
@ -1748,9 +1742,7 @@ nvme_ctrlr_suspend(struct nvme_controller *ctrlr)
int to = hz;
/*
* Can't touch failed controllers, so it's already suspended. User will
* need to do an explicit reset to bring it back, if that's even
* possible.
* Can't touch failed controllers, so it's already suspended.
*/
if (ctrlr->is_failed)
return (0);
@ -1817,7 +1809,7 @@ fail:
* itself, due to questionable APIs.
*/
nvme_printf(ctrlr, "Failed to reset on resume, failing.\n");
nvme_ctrlr_fail(ctrlr, true);
nvme_ctrlr_fail(ctrlr);
(void)atomic_cmpset_32(&ctrlr->is_resetting, 1, 0);
return (0);
}

View file

@ -301,7 +301,6 @@ struct nvme_controller {
uint32_t notification_sent;
bool is_failed;
bool is_failed_admin;
bool is_dying;
bool isr_warned;
bool is_initialized;

View file

@ -1046,7 +1046,6 @@ nvme_qpair_timeout(void *arg)
struct nvme_tracker *tr;
sbintime_t now;
bool idle = true;
bool is_admin = qpair == &ctrlr->adminq;
bool fast;
uint32_t csts;
uint8_t cfs;
@ -1058,10 +1057,9 @@ nvme_qpair_timeout(void *arg)
* failure processing that races with the qpair timeout will fail
* safely.
*/
if (is_admin ? qpair->ctrlr->is_failed_admin : qpair->ctrlr->is_failed) {
if (qpair->ctrlr->is_failed) {
nvme_printf(qpair->ctrlr,
"%sFailed controller, stopping watchdog timeout.\n",
is_admin ? "Complete " : "");
"Failed controller, stopping watchdog timeout.\n");
qpair->timer_armed = false;
return;
}
@ -1331,7 +1329,6 @@ _nvme_qpair_submit_request(struct nvme_qpair *qpair, struct nvme_request *req)
{
struct nvme_tracker *tr;
int err = 0;
bool is_admin = qpair == &qpair->ctrlr->adminq;
mtx_assert(&qpair->lock, MA_OWNED);
@ -1341,14 +1338,12 @@ _nvme_qpair_submit_request(struct nvme_qpair *qpair, struct nvme_request *req)
/*
* The controller has failed, so fail the request. Note, that this races
* the recovery / timeout code. Since we hold the qpair lock, we know
* it's safe to fail directly. is_failed is set when we fail the
* controller. It is only ever reset in the ioctl reset controller
* path, which is safe to race (for failed controllers, we make no
* guarantees about bringing it out of failed state relative to other
* commands). We try hard to allow admin commands when the entire
* controller hasn't failed, only something related to I/O queues.
* it's safe to fail directly. is_failed is set when we fail the controller.
* It is only ever reset in the ioctl reset controller path, which is safe
* to race (for failed controllers, we make no guarantees about bringing
* it out of failed state relative to other commands).
*/
if (is_admin ? qpair->ctrlr->is_failed_admin : qpair->ctrlr->is_failed) {
if (qpair->ctrlr->is_failed) {
nvme_qpair_manual_complete_request(qpair, req,
NVME_SCT_GENERIC, NVME_SC_ABORTED_BY_REQUEST, 1,
ERROR_PRINT_NONE);
@ -1415,13 +1410,11 @@ nvme_qpair_submit_request(struct nvme_qpair *qpair, struct nvme_request *req)
static void
nvme_qpair_enable(struct nvme_qpair *qpair)
{
bool is_admin __unused = qpair == &qpair->ctrlr->adminq;
if (mtx_initialized(&qpair->recovery))
mtx_assert(&qpair->recovery, MA_OWNED);
if (mtx_initialized(&qpair->lock))
mtx_assert(&qpair->lock, MA_OWNED);
KASSERT(!(is_admin ? qpair->ctrlr->is_failed_admin : qpair->ctrlr->is_failed),
KASSERT(!qpair->ctrlr->is_failed,
("Enabling a failed qpair\n"));
qpair->recovery_state = RECOVERY_NONE;

View file

@ -268,6 +268,7 @@ nvme_sim_action(struct cam_sim *sim, union ccb *ccb)
ccb->ccb_h.status = CAM_REQ_CMP;
break;
case XPT_NVME_IO: /* Execute the requested I/O operation */
case XPT_NVME_ADMIN: /* or Admin operation */
if (ctrlr->is_failed) {
/*
* I/O came in while we were failing the drive, so drop
@ -278,18 +279,6 @@ nvme_sim_action(struct cam_sim *sim, union ccb *ccb)
}
nvme_sim_nvmeio(sim, ccb);
return; /* no done */
case XPT_NVME_ADMIN: /* or Admin operation */
if (ctrlr->is_failed_admin) {
/*
* Admin request came in when we can't send admin
* commands, so drop it. Once falure is complete, we'll
* be destroyed.
*/
ccb->ccb_h.status = CAM_DEV_NOT_THERE;
break;
}
nvme_sim_nvmeio(sim, ccb);
return; /* no done */
default:
ccb->ccb_h.status = CAM_REQ_INVALID;
break;

View file

@ -1,686 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
* 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.
*/
#ifdef HAVE_KERNEL_OPTION_HEADERS
#include "opt_snd.h"
#endif
#include <dev/sound/pcm/sound.h>
#include <dev/sound/pcm/ac97.h>
#include <dev/sound/pci/aureal.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
SND_DECLARE_FILE("");
/* PCI IDs of supported chips */
#define AU8820_PCI_ID 0x000112eb
/* channel interface */
static u_int32_t au_playfmt[] = {
SND_FORMAT(AFMT_U8, 1, 0),
SND_FORMAT(AFMT_U8, 2, 0),
SND_FORMAT(AFMT_S16_LE, 1, 0),
SND_FORMAT(AFMT_S16_LE, 2, 0),
0
};
static struct pcmchan_caps au_playcaps = {4000, 48000, au_playfmt, 0};
static u_int32_t au_recfmt[] = {
SND_FORMAT(AFMT_U8, 1, 0),
SND_FORMAT(AFMT_U8, 2, 0),
SND_FORMAT(AFMT_S16_LE, 1, 0),
SND_FORMAT(AFMT_S16_LE, 2, 0),
0
};
static struct pcmchan_caps au_reccaps = {4000, 48000, au_recfmt, 0};
/* -------------------------------------------------------------------- */
struct au_info;
struct au_chinfo {
struct au_info *parent;
struct pcm_channel *channel;
struct snd_dbuf *buffer;
int dir;
};
struct au_info {
int unit;
bus_space_tag_t st[3];
bus_space_handle_t sh[3];
bus_dma_tag_t parent_dmat;
struct mtx *lock;
u_int32_t x[32], y[128];
char z[128];
u_int32_t routes[4], interrupts;
struct au_chinfo pch;
};
static int au_init(device_t dev, struct au_info *au);
static void au_intr(void *);
/* -------------------------------------------------------------------- */
static u_int32_t
au_rd(struct au_info *au, int mapno, int regno, int size)
{
switch(size) {
case 1:
return bus_space_read_1(au->st[mapno], au->sh[mapno], regno);
case 2:
return bus_space_read_2(au->st[mapno], au->sh[mapno], regno);
case 4:
return bus_space_read_4(au->st[mapno], au->sh[mapno], regno);
default:
return 0xffffffff;
}
}
static void
au_wr(struct au_info *au, int mapno, int regno, u_int32_t data, int size)
{
switch(size) {
case 1:
bus_space_write_1(au->st[mapno], au->sh[mapno], regno, data);
break;
case 2:
bus_space_write_2(au->st[mapno], au->sh[mapno], regno, data);
break;
case 4:
bus_space_write_4(au->st[mapno], au->sh[mapno], regno, data);
break;
}
}
/* -------------------------------------------------------------------- */
static int
au_rdcd(kobj_t obj, void *arg, int regno)
{
struct au_info *au = (struct au_info *)arg;
int i=0, j=0;
regno<<=16;
au_wr(au, 0, AU_REG_CODECIO, regno, 4);
while (j<50) {
i=au_rd(au, 0, AU_REG_CODECIO, 4);
if ((i & 0x00ff0000) == (regno | 0x00800000)) break;
DELAY(j * 200 + 2000);
j++;
}
if (j==50) printf("pcm%d: codec timeout reading register %x (%x)\n",
au->unit, (regno & AU_CDC_REGMASK)>>16, i);
return i & AU_CDC_DATAMASK;
}
static int
au_wrcd(kobj_t obj, void *arg, int regno, u_int32_t data)
{
struct au_info *au = (struct au_info *)arg;
int i, j, tries;
i=j=tries=0;
do {
while (j<50 && (i & AU_CDC_WROK) == 0) {
i=au_rd(au, 0, AU_REG_CODECST, 4);
DELAY(2000);
j++;
}
if (j==50) printf("codec timeout during write of register %x, data %x\n",
regno, data);
au_wr(au, 0, AU_REG_CODECIO, (regno<<16) | AU_CDC_REGSET | data, 4);
/* DELAY(20000);
i=au_rdcd(au, regno);
*/ tries++;
} while (0); /* (i != data && tries < 3); */
/*
if (tries == 3) printf("giving up writing 0x%4x to codec reg %2x\n", data, regno);
*/
return 0;
}
static kobj_method_t au_ac97_methods[] = {
KOBJMETHOD(ac97_read, au_rdcd),
KOBJMETHOD(ac97_write, au_wrcd),
KOBJMETHOD_END
};
AC97_DECLARE(au_ac97);
/* -------------------------------------------------------------------- */
static void
au_setbit(u_int32_t *p, char bit, u_int32_t value)
{
p += bit >> 5;
bit &= 0x1f;
*p &= ~ (1 << bit);
*p |= (value << bit);
}
static void
au_addroute(struct au_info *au, int a, int b, int route)
{
int j = 0x1099c+(a<<2);
if (au->x[a] != a+0x67) j = AU_REG_RTBASE+(au->x[a]<<2);
au_wr(au, 0, AU_REG_RTBASE+(route<<2), 0xffffffff, 4);
au_wr(au, 0, j, route | (b<<7), 4);
au->y[route]=au->x[a];
au->x[a]=route;
au->z[route]=a & 0x000000ff;
au_setbit(au->routes, route, 1);
}
static void
au_delroute(struct au_info *au, int route)
{
int i;
int j=au->z[route];
au_setbit(au->routes, route, 0);
au->z[route]=0x1f;
i=au_rd(au, 0, AU_REG_RTBASE+(route<<2), 4);
au_wr(au, 0, AU_REG_RTBASE+(au->y[route]<<2), i, 4);
au->y[i & 0x7f]=au->y[route];
au_wr(au, 0, AU_REG_RTBASE+(route<<2), 0xfffffffe, 4);
if (au->x[j] == route) au->x[j]=au->y[route];
au->y[route]=0x7f;
}
static void
au_encodec(struct au_info *au, char channel)
{
au_wr(au, 0, AU_REG_CODECEN,
au_rd(au, 0, AU_REG_CODECEN, 4) | (1 << (channel + 8)), 4);
}
static void
au_clrfifo(struct au_info *au, u_int32_t c)
{
u_int32_t i;
for (i=0; i<32; i++) au_wr(au, 0, AU_REG_FIFOBASE+(c<<7)+(i<<2), 0, 4);
}
static void
au_setadb(struct au_info *au, u_int32_t c, u_int32_t enable)
{
int x;
x = au_rd(au, 0, AU_REG_ADB, 4);
x &= ~(1 << c);
x |= (enable << c);
au_wr(au, 0, AU_REG_ADB, x, 4);
}
static void
au_prepareoutput(struct au_chinfo *ch, u_int32_t format)
{
struct au_info *au = ch->parent;
int i, stereo = (AFMT_CHANNEL(format) > 1)? 1 : 0;
u_int32_t baseaddr = sndbuf_getbufaddr(ch->buffer);
au_wr(au, 0, 0x1061c, 0, 4);
au_wr(au, 0, 0x10620, 0, 4);
au_wr(au, 0, 0x10624, 0, 4);
switch(AFMT_ENCODING(format)) {
case 1:
i=0xb000;
break;
case 2:
i=0xf000;
break;
case 8:
i=0x7000;
break;
case 16:
i=0x23000;
break;
default:
i=0x3000;
}
au_wr(au, 0, 0x10200, baseaddr, 4);
au_wr(au, 0, 0x10204, baseaddr+0x1000, 4);
au_wr(au, 0, 0x10208, baseaddr+0x2000, 4);
au_wr(au, 0, 0x1020c, baseaddr+0x3000, 4);
au_wr(au, 0, 0x10400, 0xdeffffff, 4);
au_wr(au, 0, 0x10404, 0xfcffffff, 4);
au_wr(au, 0, 0x10580, i, 4);
au_wr(au, 0, 0x10210, baseaddr, 4);
au_wr(au, 0, 0x10214, baseaddr+0x1000, 4);
au_wr(au, 0, 0x10218, baseaddr+0x2000, 4);
au_wr(au, 0, 0x1021c, baseaddr+0x3000, 4);
au_wr(au, 0, 0x10408, 0x00fff000 | 0x56000000 | 0x00000fff, 4);
au_wr(au, 0, 0x1040c, 0x00fff000 | 0x74000000 | 0x00000fff, 4);
au_wr(au, 0, 0x10584, i, 4);
au_wr(au, 0, 0x0f800, stereo? 0x00030032 : 0x00030030, 4);
au_wr(au, 0, 0x0f804, stereo? 0x00030032 : 0x00030030, 4);
au_addroute(au, 0x11, 0, 0x58);
au_addroute(au, 0x11, stereo? 0 : 1, 0x59);
}
/* -------------------------------------------------------------------- */
/* channel interface */
static void *
auchan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b, struct pcm_channel *c, int dir)
{
struct au_info *au = devinfo;
struct au_chinfo *ch = (dir == PCMDIR_PLAY)? &au->pch : NULL;
ch->parent = au;
ch->channel = c;
ch->buffer = b;
ch->dir = dir;
if (sndbuf_alloc(ch->buffer, au->parent_dmat, 0, AU_BUFFSIZE) != 0)
return NULL;
return ch;
}
static int
auchan_setformat(kobj_t obj, void *data, u_int32_t format)
{
struct au_chinfo *ch = data;
if (ch->dir == PCMDIR_PLAY) au_prepareoutput(ch, format);
return 0;
}
static int
auchan_setspeed(kobj_t obj, void *data, u_int32_t speed)
{
struct au_chinfo *ch = data;
if (ch->dir == PCMDIR_PLAY) {
} else {
}
return speed;
}
static int
auchan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
{
return blocksize;
}
static int
auchan_trigger(kobj_t obj, void *data, int go)
{
struct au_chinfo *ch = data;
struct au_info *au = ch->parent;
if (!PCMTRIG_COMMON(go))
return 0;
if (ch->dir == PCMDIR_PLAY) {
au_setadb(au, 0x11, (go)? 1 : 0);
if (go != PCMTRIG_START) {
au_wr(au, 0, 0xf800, 0, 4);
au_wr(au, 0, 0xf804, 0, 4);
au_delroute(au, 0x58);
au_delroute(au, 0x59);
}
} else {
}
return 0;
}
static int
auchan_getptr(kobj_t obj, void *data)
{
struct au_chinfo *ch = data;
struct au_info *au = ch->parent;
if (ch->dir == PCMDIR_PLAY) {
return au_rd(au, 0, AU_REG_UNK2, 4) & (AU_BUFFSIZE-1);
} else {
return 0;
}
}
static struct pcmchan_caps *
auchan_getcaps(kobj_t obj, void *data)
{
struct au_chinfo *ch = data;
return (ch->dir == PCMDIR_PLAY)? &au_playcaps : &au_reccaps;
}
static kobj_method_t auchan_methods[] = {
KOBJMETHOD(channel_init, auchan_init),
KOBJMETHOD(channel_setformat, auchan_setformat),
KOBJMETHOD(channel_setspeed, auchan_setspeed),
KOBJMETHOD(channel_setblocksize, auchan_setblocksize),
KOBJMETHOD(channel_trigger, auchan_trigger),
KOBJMETHOD(channel_getptr, auchan_getptr),
KOBJMETHOD(channel_getcaps, auchan_getcaps),
KOBJMETHOD_END
};
CHANNEL_DECLARE(auchan);
/* -------------------------------------------------------------------- */
/* The interrupt handler */
static void
au_intr (void *p)
{
struct au_info *au = p;
u_int32_t intsrc, i;
au->interrupts++;
intsrc=au_rd(au, 0, AU_REG_IRQSRC, 4);
printf("pcm%d: interrupt with src %x\n", au->unit, intsrc);
if (intsrc & AU_IRQ_FATAL) printf("pcm%d: fatal error irq\n", au->unit);
if (intsrc & AU_IRQ_PARITY) printf("pcm%d: parity error irq\n", au->unit);
if (intsrc & AU_IRQ_UNKNOWN) {
(void)au_rd(au, 0, AU_REG_UNK1, 4);
au_wr(au, 0, AU_REG_UNK1, 0, 4);
au_wr(au, 0, AU_REG_UNK1, 0x10000, 4);
}
if (intsrc & AU_IRQ_PCMOUT) {
i=au_rd(au, 0, AU_REG_UNK2, 4) & (AU_BUFFSIZE-1);
chn_intr(au->pch.channel);
(void)au_rd(au, 0, AU_REG_UNK3, 4);
(void)au_rd(au, 0, AU_REG_UNK4, 4);
(void)au_rd(au, 0, AU_REG_UNK5, 4);
}
/* don't support midi
if (intsrc & AU_IRQ_MIDI) {
i=au_rd(au, 0, 0x11004, 4);
j=10;
while (i & 0xff) {
if (j-- <= 0) break;
i=au_rd(au, 0, 0x11000, 4);
if ((au->midi_stat & 1) && (au->midi_out))
au->midi_out(au->midi_devno, i);
i=au_rd(au, 0, 0x11004);
}
}
*/
au_wr(au, 0, AU_REG_IRQSRC, intsrc & 0x7ff, 4);
au_rd(au, 0, AU_REG_IRQSRC, 4);
}
/* -------------------------------------------------------------------- */
/* Probe and attach the card */
static int
au_init(device_t dev, struct au_info *au)
{
u_int32_t i, j;
au_wr(au, 0, AU_REG_IRQGLOB, 0xffffffff, 4);
DELAY(100000);
/* init codec */
/* cold reset */
for (i=0; i<32; i++) {
au_wr(au, 0, AU_REG_CODECCHN+(i<<2), 0, 4);
DELAY(10000);
}
if (1) {
au_wr(au, 0, AU_REG_CODECST, 0x8068, 4);
DELAY(10000);
au_wr(au, 0, AU_REG_CODECST, 0x00e8, 4);
DELAY(10000);
} else {
au_wr(au, 0, AU_REG_CODECST, 0x00a8, 4);
DELAY(100000);
au_wr(au, 0, AU_REG_CODECST, 0x80a8, 4);
DELAY(100000);
au_wr(au, 0, AU_REG_CODECST, 0x80e8, 4);
DELAY(100000);
au_wr(au, 0, AU_REG_CODECST, 0x80a8, 4);
DELAY(100000);
au_wr(au, 0, AU_REG_CODECST, 0x00a8, 4);
DELAY(100000);
au_wr(au, 0, AU_REG_CODECST, 0x00e8, 4);
DELAY(100000);
}
/* init */
for (i=0; i<32; i++) {
au_wr(au, 0, AU_REG_CODECCHN+(i<<2), 0, 4);
DELAY(10000);
}
au_wr(au, 0, AU_REG_CODECST, 0xe8, 4);
DELAY(10000);
au_wr(au, 0, AU_REG_CODECEN, 0, 4);
/* setup codec */
i=j=0;
while (j<100 && (i & AU_CDC_READY)==0) {
i=au_rd(au, 0, AU_REG_CODECST, 4);
DELAY(1000);
j++;
}
if (j==100) device_printf(dev, "codec not ready, status 0x%x\n", i);
/* init adb */
/*au->x5c=0;*/
for (i=0; i<32; i++) au->x[i]=i+0x67;
for (i=0; i<128; i++) au->y[i]=0x7f;
for (i=0; i<128; i++) au->z[i]=0x1f;
au_wr(au, 0, AU_REG_ADB, 0, 4);
for (i=0; i<124; i++) au_wr(au, 0, AU_REG_RTBASE+(i<<2), 0xffffffff, 4);
/* test */
i=au_rd(au, 0, 0x107c0, 4);
if (i!=0xdeadbeef) device_printf(dev, "dma check failed: 0x%x\n", i);
/* install mixer */
au_wr(au, 0, AU_REG_IRQGLOB,
au_rd(au, 0, AU_REG_IRQGLOB, 4) | AU_IRQ_ENABLE, 4);
/* braindead but it's what the oss/linux driver does
* for (i=0; i<0x80000000; i++) au_wr(au, 0, i<<2, 0, 4);
*/
au->routes[0]=au->routes[1]=au->routes[2]=au->routes[3]=0;
/*au->x1e4=0;*/
/* attach channel */
au_addroute(au, 0x11, 0x48, 0x02);
au_addroute(au, 0x11, 0x49, 0x03);
au_encodec(au, 0);
au_encodec(au, 1);
for (i=0; i<48; i++) au_wr(au, 0, 0xf800+(i<<2), 0x20, 4);
for (i=2; i<6; i++) au_wr(au, 0, 0xf800+(i<<2), 0, 4);
au_wr(au, 0, 0xf8c0, 0x0843, 4);
for (i=0; i<4; i++) au_clrfifo(au, i);
return (0);
}
static int
au_testirq(struct au_info *au)
{
au_wr(au, 0, AU_REG_UNK1, 0x80001000, 4);
au_wr(au, 0, AU_REG_IRQEN, 0x00001030, 4);
au_wr(au, 0, AU_REG_IRQSRC, 0x000007ff, 4);
DELAY(1000000);
if (au->interrupts==0) printf("pcm%d: irq test failed\n", au->unit);
/* this apparently generates an irq */
return 0;
}
static int
au_pci_probe(device_t dev)
{
if (pci_get_devid(dev) == AU8820_PCI_ID) {
device_set_desc(dev, "Aureal Vortex 8820");
return BUS_PROBE_DEFAULT;
}
return ENXIO;
}
static int
au_pci_attach(device_t dev)
{
struct au_info *au;
int type[10];
int regid[10];
struct resource *reg[10];
int i, j, mapped = 0;
int irqid;
struct resource *irq;
void *ih;
struct ac97_info *codec;
char status[SND_STATUSLEN];
au = malloc(sizeof(*au), M_DEVBUF, M_WAITOK | M_ZERO);
au->unit = device_get_unit(dev);
pci_enable_busmaster(dev);
irq = NULL;
ih = NULL;
j=0;
/* XXX dfr: is this strictly necessary? */
for (i=0; i<PCI_MAXMAPS_0; i++) {
#if 0
/* Slapped wrist: config_id and map are private structures */
if (bootverbose) {
printf("pcm%d: map %d - allocating ", unit, i+1);
printf("0x%x bytes of ", 1<<config_id->map[i].ln2size);
printf("%s space ", (config_id->map[i].type & PCI_MAPPORT)?
"io" : "memory");
printf("at 0x%x...", config_id->map[i].base);
}
#endif
regid[j] = PCIR_BAR(i);
type[j] = SYS_RES_MEMORY;
reg[j] = bus_alloc_resource_any(dev, type[j], &regid[j],
RF_ACTIVE);
if (!reg[j]) {
type[j] = SYS_RES_IOPORT;
reg[j] = bus_alloc_resource_any(dev, type[j],
&regid[j], RF_ACTIVE);
}
if (reg[j]) {
au->st[i] = rman_get_bustag(reg[j]);
au->sh[i] = rman_get_bushandle(reg[j]);
mapped++;
}
#if 0
if (bootverbose) printf("%s\n", mapped? "ok" : "failed");
#endif
if (mapped) j++;
if (j == 10) {
/* XXX */
device_printf(dev, "too many resources");
goto bad;
}
}
#if 0
if (j < config_id->nummaps) {
printf("pcm%d: unable to map a required resource\n", unit);
free(au, M_DEVBUF);
return;
}
#endif
au_wr(au, 0, AU_REG_IRQEN, 0, 4);
irqid = 0;
irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irqid,
RF_ACTIVE | RF_SHAREABLE);
if (!irq || snd_setup_intr(dev, irq, 0, au_intr, au, &ih)) {
device_printf(dev, "unable to map interrupt\n");
goto bad;
}
if (au_testirq(au)) device_printf(dev, "irq test failed\n");
if (au_init(dev, au) == -1) {
device_printf(dev, "unable to initialize the card\n");
goto bad;
}
codec = AC97_CREATE(dev, au, au_ac97);
if (codec == NULL) goto bad;
if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad;
if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
/*boundary*/0,
/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
/*highaddr*/BUS_SPACE_MAXADDR,
/*filter*/NULL, /*filterarg*/NULL,
/*maxsize*/AU_BUFFSIZE, /*nsegments*/1, /*maxsegz*/0x3ffff,
/*flags*/0, /*lockfunc*/NULL, /*lockarg*/NULL,
&au->parent_dmat) != 0) {
device_printf(dev, "unable to create dma tag\n");
goto bad;
}
snprintf(status, SND_STATUSLEN, "at %s 0x%jx irq %jd %s",
(type[0] == SYS_RES_IOPORT)? "io" : "memory",
rman_get_start(reg[0]), rman_get_start(irq),PCM_KLDSTRING(snd_aureal));
if (pcm_register(dev, au, 1, 1)) goto bad;
/* pcm_addchan(dev, PCMDIR_REC, &au_chantemplate, au); */
pcm_addchan(dev, PCMDIR_PLAY, &auchan_class, au);
pcm_setstatus(dev, status);
return 0;
bad:
if (au) free(au, M_DEVBUF);
for (i = 0; i < j; i++)
bus_release_resource(dev, type[i], regid[i], reg[i]);
if (ih) bus_teardown_intr(dev, irq, ih);
if (irq) bus_release_resource(dev, SYS_RES_IRQ, irqid, irq);
return ENXIO;
}
static device_method_t au_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, au_pci_probe),
DEVMETHOD(device_attach, au_pci_attach),
{ 0, 0 }
};
static driver_t au_driver = {
"pcm",
au_methods,
PCM_SOFTC_SIZE,
};
DRIVER_MODULE(snd_aureal, pci, au_driver, pcm_devclass, 0, 0);
MODULE_DEPEND(snd_aureal, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
MODULE_VERSION(snd_aureal, 1);

View file

@ -1,99 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1999 Cameron Grant <cg@freebsd.org>
* 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.
*
*/
#ifndef _AU8820_REG_H
#define _AU8820_REG_H
#define AU_BUFFSIZE 0x4000
#define AU_REG_FIFOBASE 0x0e000
#define AU_REG_UNK2 0x105c0
#define AU_REG_UNK3 0x10600
#define AU_REG_UNK4 0x10604
#define AU_REG_UNK5 0x10608
#define AU_REG_RTBASE 0x10800
#define AU_REG_ADB 0x10a00
#define AU_REG_CODECCHN 0x11880
#define AU_REG_CODECST 0x11984
#define AU_CDC_RUN 0x00000040
#define AU_CDC_WROK 0x00000100
#define AU_CDC_RESET 0x00008000
#define AU_REG_CODECIO 0x11988
#define AU_CDC_DATAMASK 0x0000ffff
#define AU_CDC_REGMASK 0x007f0000
#define AU_CDC_REGSET 0x00800000
#define AU_CDC_READY 0x04000000
#define AU_REG_CODECEN 0x11990
#define AU_CDC_CHAN1EN 0x00000100
#define AU_CDC_CHAN2EN 0x00000200
#define AU_REG_UNK1 0x1199c
#define AU_REG_IRQSRC 0x12800
#define AU_IRQ_FATAL 0x0001
#define AU_IRQ_PARITY 0x0002
#define AU_IRQ_PCMOUT 0x0020
#define AU_IRQ_UNKNOWN 0x1000
#define AU_IRQ_MIDI 0x2000
#define AU_REG_IRQEN 0x12804
#define AU_REG_IRQGLOB 0x1280c
#define AU_IRQ_ENABLE 0x4000
#define AC97_MUTE 0x8000
#define AC97_REG_RESET 0x00
#define AC97_MIX_MASTER 0x02
#define AC97_MIX_PHONES 0x04
#define AC97_MIX_MONO 0x06
#define AC97_MIX_TONE 0x08
#define AC97_MIX_BEEP 0x0a
#define AC97_MIX_PHONE 0x0c
#define AC97_MIX_MIC 0x0e
#define AC97_MIX_LINE 0x10
#define AC97_MIX_CD 0x12
#define AC97_MIX_VIDEO 0x14
#define AC97_MIX_AUX 0x16
#define AC97_MIX_PCM 0x18
#define AC97_REG_RECSEL 0x1a
#define AC97_MIX_RGAIN 0x1c
#define AC97_MIX_MGAIN 0x1e
#define AC97_REG_GEN 0x20
#define AC97_REG_3D 0x22
#define AC97_REG_POWER 0x26
#define AC97_REG_ID1 0x7c
#define AC97_REG_ID2 0x7e
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,146 +0,0 @@
/*
* =======================================================================
* title : define
* company : YAMAHA
* author : Taichi Sugiyama
* create Data : 28/Sep/99
* =======================================================================
*/
/* ----- YAMAHA DS-XG Devices -------------------------------------------- */
#define YAMAHA 0x1073
#define YMF724 0x0004
#define YMF724F 0x000d
#define YMF734 0x0005
#define YMF737 0x0008
#define YMF738 0x0020
#define YMF740 0x000a
#define YMF740C 0x000c
#define YMF744 0x0010
#define YMF754 0x0012
#define YMF738_TEG 0x0006
#define DEVICE4CH(x) ((x == YMF738) || (x == YMF744) || (x == YMF754))
#define PCIR_DSXGCTRL 0x48
/* ----- interrupt flag -------------------------------------------------- */
#define YDSXG_DEFINT 0x01
#define YDSXG_TIMERINT 0x02
/* ----- AC97 ------------------------------------------------------------ */
#define YDSXG_AC97TIMEOUT 1000
#define YDSXG_AC97READCMD 0x8000
#define YDSXG_AC97WRITECMD 0x0000
#define YDSXG_AC97READFALSE 0xFFFF
/* ----- AC97 register map _---------------------------------------------- */
#define AC97R_GPIOSTATUS 0x54
/* ----- work buffer ----------------------------------------------------- */
#define DEF_WORKBUFFLENGTH 0x0400
/* ----- register size --------------------------------------------------- */
#define YDSXG_MAPLENGTH 0x8000
#define YDSXG_DSPLENGTH 0x0080
#define YDSXG_CTRLLENGTH 0x3000
/* ----- register map ---------------------------------------------------- */
#define YDSXGR_INTFLAG 0x0004
#define YDSXGR_ACTIVITY 0x0006
#define YDSXGR_GLOBALCTRL 0x0008
#define YDSXGR_ZVCTRL 0x000A
#define YDSXGR_TIMERCTRL 0x0010
#define YDSXGR_TIMERCOUNT 0x0012
#define YDSXGR_SPDIFOUTCTRL 0x0018
#define YDSXGR_SPDIFOUTSTATUS 0x001C
#define YDSXGR_EEPROMCTRL 0x0020
#define YDSXGR_SPDIFINCTRL 0x0034
#define YDSXGR_SPDIFINSTATUS 0x0038
#define YDSXGR_DSPPROGRAMDL 0x0048
#define YDSXGR_DLCNTRL 0x004C
#define YDSXGR_GPIOININTFLAG 0x0050
#define YDSXGR_GPIOININTENABLE 0x0052
#define YDSXGR_GPIOINSTATUS 0x0054
#define YDSXGR_GPIOOUTCTRL 0x0056
#define YDSXGR_GPIOFUNCENABLE 0x0058
#define YDSXGR_GPIOTYPECONFIG 0x005A
#define YDSXGR_AC97CMDDATA 0x0060
#define YDSXGR_AC97CMDADR 0x0062
#define YDSXGR_PRISTATUSDATA 0x0064
#define YDSXGR_PRISTATUSADR 0x0066
#define YDSXGR_SECSTATUSDATA 0x0068
#define YDSXGR_SECSTATUSADR 0x006A
#define YDSXGR_SECCONFIG 0x0070
#define YDSXGR_LEGACYOUTVOL 0x0080
#define YDSXGR_LEGACYOUTVOLL 0x0080
#define YDSXGR_LEGACYOUTVOLR 0x0082
#define YDSXGR_NATIVEDACOUTVOL 0x0084
#define YDSXGR_NATIVEDACOUTVOLL 0x0084
#define YDSXGR_NATIVEDACOUTVOLR 0x0086
#define YDSXGR_SPDIFOUTVOL 0x0088
#define YDSXGR_SPDIFOUTVOLL 0x0088
#define YDSXGR_SPDIFOUTVOLR 0x008A
#define YDSXGR_AC3OUTVOL 0x008C
#define YDSXGR_AC3OUTVOLL 0x008C
#define YDSXGR_AC3OUTVOLR 0x008E
#define YDSXGR_PRIADCOUTVOL 0x0090
#define YDSXGR_PRIADCOUTVOLL 0x0090
#define YDSXGR_PRIADCOUTVOLR 0x0092
#define YDSXGR_LEGACYLOOPVOL 0x0094
#define YDSXGR_LEGACYLOOPVOLL 0x0094
#define YDSXGR_LEGACYLOOPVOLR 0x0096
#define YDSXGR_NATIVEDACLOOPVOL 0x0098
#define YDSXGR_NATIVEDACLOOPVOLL 0x0098
#define YDSXGR_NATIVEDACLOOPVOLR 0x009A
#define YDSXGR_SPDIFLOOPVOL 0x009C
#define YDSXGR_SPDIFLOOPVOLL 0x009E
#define YDSXGR_SPDIFLOOPVOLR 0x009E
#define YDSXGR_AC3LOOPVOL 0x00A0
#define YDSXGR_AC3LOOPVOLL 0x00A0
#define YDSXGR_AC3LOOPVOLR 0x00A2
#define YDSXGR_PRIADCLOOPVOL 0x00A4
#define YDSXGR_PRIADCLOOPVOLL 0x00A4
#define YDSXGR_PRIADCLOOPVOLR 0x00A6
#define YDSXGR_NATIVEADCINVOL 0x00A8
#define YDSXGR_NATIVEADCINVOLL 0x00A8
#define YDSXGR_NATIVEADCINVOLR 0x00AA
#define YDSXGR_NATIVEDACINVOL 0x00AC
#define YDSXGR_NATIVEDACINVOLL 0x00AC
#define YDSXGR_NATIVEDACINVOLR 0x00AE
#define YDSXGR_BUF441OUTVOL 0x00B0
#define YDSXGR_BUF441OUTVOLL 0x00B0
#define YDSXGR_BUF441OUTVOLR 0x00B2
#define YDSXGR_BUF441LOOPVOL 0x00B4
#define YDSXGR_BUF441LOOPVOLL 0x00B4
#define YDSXGR_BUF441LOOPVOLR 0x00B6
#define YDSXGR_SPDIFOUTVOL2 0x00B8
#define YDSXGR_SPDIFOUTVOL2L 0x00B8
#define YDSXGR_SPDIFOUTVOL2R 0x00BA
#define YDSXGR_SPDIFLOOPVOL2 0x00BC
#define YDSXGR_SPDIFLOOPVOL2L 0x00BC
#define YDSXGR_SPDIFLOOPVOL2R 0x00BE
#define YDSXGR_ADCSLOTSR 0x00C0
#define YDSXGR_RECSLOTSR 0x00C4
#define YDSXGR_ADCFORMAT 0x00C8
#define YDSXGR_RECFORMAT 0x00CC
#define YDSXGR_P44SLOTSR 0x00D0
#define YDSXGR_STATUS 0x0100
#define YDSXGR_CTRLSELECT 0x0104
#define YDSXGR_MODE 0x0108
#define YDSXGR_SAMPLECOUNT 0x010C
#define YDSXGR_NUMOFSAMPLES 0x0110
#define YDSXGR_CONFIG 0x0114
#define YDSXGR_PLAYCTRLSIZE 0x0140
#define YDSXGR_RECCTRLSIZE 0x0144
#define YDSXGR_EFFCTRLSIZE 0x0148
#define YDSXGR_WORKSIZE 0x014C
#define YDSXGR_MAPOFREC 0x0150
#define YDSXGR_MAPOFEFFECT 0x0154
#define YDSXGR_PLAYCTRLBASE 0x0158
#define YDSXGR_RECCTRLBASE 0x015C
#define YDSXGR_EFFCTRLBASE 0x0160
#define YDSXGR_WORKBASE 0x0164
#define YDSXGR_DSPINSTRAM 0x1000
#define YDSXGR_CTRLINSTRAM 0x4000
/* ----- time out -------------------------------------------------------- */
#define YDSXG_WORKBITTIMEOUT 250000

File diff suppressed because it is too large Load diff

View file

@ -1,381 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
* Copyright (c) 1999-2000 Taku YAMAMOTO <taku@cent.saitama-u.ac.jp>
* 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.
*
* maestro_reg.h,v 1.13 2001/11/11 18:29:46 taku Exp
*/
#ifndef MAESTRO_REG_H_INCLUDED
#define MAESTRO_REG_H_INCLUDED
/* -----------------------------
* PCI config registers
*/
/* Legacy emulation */
#define CONF_LEGACY 0x40
#define LEGACY_DISABLED 0x8000
/* Chip configurations */
#define CONF_MAESTRO 0x50
#define MAESTRO_PMC 0x08000000
#define MAESTRO_SPDIF 0x01000000
#define MAESTRO_HWVOL 0x00800000
#define MAESTRO_CHIBUS 0x00100000
#define MAESTRO_POSTEDWRITE 0x00000080
#define MAESTRO_DMA_PCITIMING 0x00000040
#define MAESTRO_SWAP_LR 0x00000020
/* ACPI configurations */
#define CONF_ACPI_STOPCLOCK 0x54
#define ACPI_PART_2ndC_CLOCK 15
#define ACPI_PART_CODEC_CLOCK 14
#define ACPI_PART_978 13 /* Docking station or something */
#define ACPI_PART_SPDIF 12
#define ACPI_PART_GLUE 11 /* What? */
#define ACPI_PART_DAA 10
#define ACPI_PART_PCI_IF 9
#define ACPI_PART_HW_VOL 8
#define ACPI_PART_GPIO 7
#define ACPI_PART_ASSP 6
#define ACPI_PART_SB 5
#define ACPI_PART_FM 4
#define ACPI_PART_RINGBUS 3
#define ACPI_PART_MIDI 2
#define ACPI_PART_GAME_PORT 1
#define ACPI_PART_WP 0
/* Power management */
#define CONF_PM_PTR 0x34 /* BYTE R */
#define PM_CID 0 /* BYTE R */
#define PPMI_CID 1
#define PM_CTRL 4 /* BYTE RW */
#define PPMI_D0 0 /* Full power */
#define PPMI_D1 1 /* Medium power */
#define PPMI_D2 2 /* Low power */
#define PPMI_D3 3 /* Turned off */
/* -----------------------------
* I/O ports
*/
/* Direct Sound Processor (aka WP) */
#define PORT_DSP_DATA 0x00 /* WORD RW */
#define PORT_DSP_INDEX 0x02 /* WORD RW */
#define PORT_INT_STAT 0x04 /* WORD RW */
#define PORT_SAMPLE_CNT 0x06 /* WORD RO */
/* WaveCache */
#define PORT_WAVCACHE_INDEX 0x10 /* WORD RW */
#define PORT_WAVCACHE_DATA 0x12 /* WORD RW */
#define WAVCACHE_PCMBAR 0x1fc
#define WAVCACHE_WTBAR 0x1f0
#define WAVCACHE_BASEADDR_SHIFT 12
#define WAVCACHE_CHCTL_ADDRTAG_MASK 0xfff8
#define WAVCACHE_CHCTL_U8 0x0004
#define WAVCACHE_CHCTL_STEREO 0x0002
#define WAVCACHE_CHCTL_DECREMENTAL 0x0001
#define PORT_WAVCACHE_CTRL 0x14 /* WORD RW */
#define WAVCACHE_EXTRA_CH_ENABLED 0x0200
#define WAVCACHE_ENABLED 0x0100
#define WAVCACHE_CH_60_ENABLED 0x0080
#define WAVCACHE_WTSIZE_MASK 0x0060
#define WAVCACHE_WTSIZE_1MB 0x0000
#define WAVCACHE_WTSIZE_2MB 0x0020
#define WAVCACHE_WTSIZE_4MB 0x0040
#define WAVCACHE_WTSIZE_8MB 0x0060
#define WAVCACHE_SGC_MASK 0x000c
#define WAVCACHE_SGC_DISABLED 0x0000
#define WAVCACHE_SGC_40_47 0x0004
#define WAVCACHE_SGC_32_47 0x0008
#define WAVCACHE_TESTMODE 0x0001
/* Host Interruption */
#define PORT_HOSTINT_CTRL 0x18 /* WORD RW */
#define HOSTINT_CTRL_SOFT_RESET 0x8000
#define HOSTINT_CTRL_DSOUND_RESET 0x4000
#define HOSTINT_CTRL_HW_VOL_TO_PME 0x0400
#define HOSTINT_CTRL_CLKRUN_ENABLED 0x0100
#define HOSTINT_CTRL_HWVOL_ENABLED 0x0040
#define HOSTINT_CTRL_ASSP_INT_ENABLED 0x0010
#define HOSTINT_CTRL_ISDN_INT_ENABLED 0x0008
#define HOSTINT_CTRL_DSOUND_INT_ENABLED 0x0004
#define HOSTINT_CTRL_MPU401_INT_ENABLED 0x0002
#define HOSTINT_CTRL_SB_INT_ENABLED 0x0001
#define PORT_HOSTINT_STAT 0x1a /* BYTE RW */
#define HOSTINT_STAT_HWVOL 0x40
#define HOSTINT_STAT_ASSP 0x10
#define HOSTINT_STAT_ISDN 0x08
#define HOSTINT_STAT_DSOUND 0x04
#define HOSTINT_STAT_MPU401 0x02
#define HOSTINT_STAT_SB 0x01
/* Hardware volume */
#define PORT_HWVOL_CTRL 0x1b /* BYTE RW */
#define HWVOL_CTRL_SPLIT_SHADOW 0x01
#define PORT_HWVOL_VOICE_SHADOW 0x1c /* BYTE RW */
#define PORT_HWVOL_VOICE 0x1d /* BYTE RW */
#define PORT_HWVOL_MASTER_SHADOW 0x1e /* BYTE RW */
#define PORT_HWVOL_MASTER 0x1f /* BYTE RW */
#define HWVOL_NOP 0x88
#define HWVOL_MUTE 0x11
#define HWVOL_UP 0xaa
#define HWVOL_DOWN 0x66
/* CODEC */
#define PORT_CODEC_CMD 0x30 /* BYTE W */
#define CODEC_CMD_READ 0x80
#define CODEC_CMD_WRITE 0x00
#define CODEC_CMD_ADDR_MASK 0x7f
#define PORT_CODEC_STAT 0x30 /* BYTE R */
#define CODEC_STAT_MASK 0x01
#define CODEC_STAT_RW_DONE 0x00
#define CODEC_STAT_PROGLESS 0x01
#define PORT_CODEC_REG 0x32 /* WORD RW */
/* Ring bus control */
#define PORT_RINGBUS_CTRL 0x34 /* DWORD RW */
#define RINGBUS_CTRL_I2S_ENABLED 0x80000000
#define RINGBUS_CTRL_RINGBUS_ENABLED 0x20000000
#define RINGBUS_CTRL_ACLINK_ENABLED 0x10000000
#define RINGBUS_CTRL_AC97_SWRESET 0x08000000
#define RINGBUS_SRC_MIC 20
#define RINGBUS_SRC_I2S 16
#define RINGBUS_SRC_ADC 12
#define RINGBUS_SRC_MODEM 8
#define RINGBUS_SRC_DSOUND 4
#define RINGBUS_SRC_ASSP 0
#define RINGBUS_DEST_MONORAL 000
#define RINGBUS_DEST_STEREO 010
#define RINGBUS_DEST_NONE 0
#define RINGBUS_DEST_DAC 1
#define RINGBUS_DEST_MODEM_IN 2
#define RINGBUS_DEST_RESERVED3 3
#define RINGBUS_DEST_DSOUND_IN 4
#define RINGBUS_DEST_ASSP_IN 5
/* Ring bus control B */
#define PORT_RINGBUS_CTRL_B 0x38 /* BYTE RW */
#define RINGBUS_CTRL_SSPE 0x40
#define RINGBUS_CTRL_2ndCODEC 0x20
#define RINGBUS_CTRL_SPDIF 0x10
#define RINGBUS_CTRL_ITB_DISABLE 0x08
#define RINGBUS_CTRL_CODEC_ID_MASK 0x03
#define RINGBUS_CTRL_CODEC_ID_AC98 2
/* General Purpose I/O */
#define PORT_GPIO_DATA 0x60 /* WORD RW */
#define PORT_GPIO_MASK 0x64 /* WORD RW */
#define PORT_GPIO_DIR 0x68 /* WORD RW */
/* Application Specific Signal Processor */
#define PORT_ASSP_MEM_INDEX 0x80 /* DWORD RW */
#define PORT_ASSP_MEM_DATA 0x84 /* WORD RW */
#define PORT_ASSP_CTRL_A 0xa2 /* BYTE RW */
#define PORT_ASSP_CTRL_B 0xa4 /* BYTE RW */
#define PORT_ASSP_CTRL_C 0xa6 /* BYTE RW */
#define PORT_ASSP_HOST_WR_INDEX 0xa8 /* BYTE W */
#define PORT_ASSP_HOST_WR_DATA 0xaa /* BYTE RW */
#define PORT_ASSP_INT_STAT 0xac /* BYTE RW */
/* -----------------------------
* Wave Processor Indexed Data Registers.
*/
#define WPREG_DATA_PORT 0
#define WPREG_CRAM_PTR 1
#define WPREG_CRAM_DATA 2
#define WPREG_WAVE_DATA 3
#define WPREG_WAVE_PTR_LOW 4
#define WPREG_WAVE_PTR_HIGH 5
#define WPREG_TIMER_FREQ 6
#define WP_TIMER_FREQ_PRESCALE_MASK 0x00e0 /* actual - 9 */
#define WP_TIMER_FREQ_PRESCALE_SHIFT 5
#define WP_TIMER_FREQ_DIVIDE_MASK 0x001f
#define WP_TIMER_FREQ_DIVIDE_SHIFT 0
#define WPREG_WAVE_ROMRAM 7
#define WP_WAVE_VIRTUAL_ENABLED 0x0400
#define WP_WAVE_8BITRAM_ENABLED 0x0200
#define WP_WAVE_DRAM_ENABLED 0x0100
#define WP_WAVE_RAMSPLIT_MASK 0x00ff
#define WP_WAVE_RAMSPLIT_SHIFT 0
#define WPREG_BASE 12
#define WP_PARAOUT_BASE_MASK 0xf000
#define WP_PARAOUT_BASE_SHIFT 12
#define WP_PARAIN_BASE_MASK 0x0f00
#define WP_PARAIN_BASE_SHIFT 8
#define WP_SERIAL0_BASE_MASK 0x00f0
#define WP_SERIAL0_BASE_SHIFT 4
#define WP_SERIAL1_BASE_MASK 0x000f
#define WP_SERIAL1_BASE_SHIFT 0
#define WPREG_TIMER_ENABLE 17
#define WPREG_TIMER_START 23
/* -----------------------------
* Audio Processing Unit.
*/
#define APUREG_APUTYPE 0
#define APU_DMA_ENABLED 0x4000
#define APU_INT_ON_LOOP 0x2000
#define APU_ENDCURVE 0x1000
#define APU_APUTYPE_MASK 0x00f0
#define APU_FILTERTYPE_MASK 0x000c
#define APU_FILTERQ_MASK 0x0003
/* APU types */
#define APU_APUTYPE_SHIFT 4
#define APUTYPE_INACTIVE 0
#define APUTYPE_16BITLINEAR 1
#define APUTYPE_16BITSTEREO 2
#define APUTYPE_8BITLINEAR 3
#define APUTYPE_8BITSTEREO 4
#define APUTYPE_8BITDIFF 5
#define APUTYPE_DIGITALDELAY 6
#define APUTYPE_DUALTAP_READER 7
#define APUTYPE_CORRELATOR 8
#define APUTYPE_INPUTMIXER 9
#define APUTYPE_WAVETABLE 10
#define APUTYPE_RATECONV 11
#define APUTYPE_16BITPINGPONG 12
/* APU type 13 through 15 are reserved. */
/* Filter types */
#define APU_FILTERTYPE_SHIFT 2
#define FILTERTYPE_2POLE_LOPASS 0
#define FILTERTYPE_2POLE_BANDPASS 1
#define FILTERTYPE_2POLE_HIPASS 2
#define FILTERTYPE_1POLE_LOPASS 3
#define FILTERTYPE_1POLE_HIPASS 4
#define FILTERTYPE_PASSTHROUGH 5
/* Filter Q */
#define APU_FILTERQ_SHIFT 0
#define FILTERQ_LESSQ 0
#define FILTERQ_MOREQ 3
/* APU register 2 */
#define APUREG_FREQ_LOBYTE 2
#define APU_FREQ_LOBYTE_MASK 0xff00
#define APU_plus6dB 0x0010
/* APU register 3 */
#define APUREG_FREQ_HIWORD 3
#define APU_FREQ_HIWORD_MASK 0x0fff
/* Frequency */
#define APU_FREQ_LOBYTE_SHIFT 8
#define APU_FREQ_HIWORD_SHIFT 0
#define FREQ_Hz2DIV(freq) (((u_int64_t)(freq) << 16) / 48000)
/* APU register 4 */
#define APUREG_WAVESPACE 4
#define APU_64KPAGE_MASK 0xff00
/* 64KW (==128KB) Page */
#define APU_64KPAGE_SHIFT 8
/* Wave Processor Wavespace Address */
#define WPWA_MAX ((1 << 22) - 1)
#define WPWA_STEREO (1 << 23)
#define WPWA_USE_SYSMEM (1 << 22)
#define WPWA_WTBAR_SHIFT(wtsz) WPWA_WTBAR_SHIFT_##wtsz
#define WPWA_WTBAR_SHIFT_1 15
#define WPWA_WTBAR_SHIFT_2 16
#define WPWA_WTBAR_SHIFT_4 17
#define WPWA_WTBAR_SHIFT_8 18
#define WPWA_PCMBAR_SHIFT 20
/* APU register 5 - 7 */
#define APUREG_CURPTR 5
#define APUREG_ENDPTR 6
#define APUREG_LOOPLEN 7
/* APU register 8 */
#define APUREG_EFFECT_GAIN 8
/* Effect gain? */
#define APUREG_EFFECT_GAIN_MASK 0x00ff
/* APU register 9 */
#define APUREG_AMPLITUDE 9
#define APU_AMPLITUDE_NOW_MASK 0xff00
#define APU_AMPLITUDE_DEST_MASK 0x00ff
/* Amplitude now? */
#define APU_AMPLITUDE_NOW_SHIFT 8
/* APU register 10 */
#define APUREG_POSITION 10
#define APU_RADIUS_MASK 0x00c0
#define APU_PAN_MASK 0x003f
/* Radius control. */
#define APU_RADIUS_SHIFT 6
#define RADIUS_CENTERCIRCLE 0
#define RADIUS_MIDDLE 1
#define RADIUS_OUTSIDE 2
/* Polar pan. */
#define APU_PAN_SHIFT 0
#define PAN_RIGHT 0x00
#define PAN_FRONT 0x08
#define PAN_LEFT 0x10
/* Source routing. */
#define APUREG_ROUTING 11
#define APU_INVERT_POLARITY_B 0x8000
#define APU_DATASRC_B_MASK 0x7f00
#define APU_INVERT_POLARITY_A 0x0080
#define APU_DATASRC_A_MASK 0x007f
#define APU_DATASRC_A_SHIFT 0
#define APU_DATASRC_B_SHIFT 8
/* -----------------------------
* Limits.
*/
#define WPWA_MAXADDR ((1 << 23) - 1)
#define MAESTRO_MAXADDR ((1 << 28) - 1)
#endif /* MAESTRO_REG_H_INCLUDED */

File diff suppressed because it is too large Load diff

View file

@ -1,8 +0,0 @@
.PATH: ${SRCTOP}/sys/dev/sound/pci
KMOD= snd_ds1
SRCS= device_if.h bus_if.h pci_if.h
SRCS+= ds1.c
.include <bsd.kmod.mk>

View file

@ -1,8 +0,0 @@
.PATH: ${SRCTOP}/sys/dev/sound/pci
KMOD= snd_maestro
SRCS= device_if.h bus_if.h pci_if.h
SRCS+= maestro.c
.include <bsd.kmod.mk>