Add QLogic 10 Gigabit Ethernet & CNA Adapter Driver version 1.30

for 3200 and 8200 series cards.

Submitted by:	David C Somayajulu (david.somayajulu@qlogic.com),
		Qlogic Corporation
MFC After:	3 days
This commit is contained in:
Bjoern A. Zeeb 2011-11-03 21:20:22 +00:00
parent 1fef78c3f0
commit 0bc7cf6fde
21 changed files with 6918 additions and 0 deletions

View File

@ -347,6 +347,7 @@ MAN= aac.4 \
pts.4 \
pty.4 \
puc.4 \
${_qlxgb.4} \
ral.4 \
random.4 \
rc.4 \
@ -713,6 +714,10 @@ _xen.4= xen.4
MLINKS+=lindev.4 full.4
.endif
.if ${MACHINE_CPUARCH} == "amd64"
_qlxgb.4= qlxgb.4
.endif
.if ${MACHINE_CPUARCH} == "powerpc"
_atp.4= atp.4
.endif

93
share/man/man4/qlxgb.4 Normal file
View File

@ -0,0 +1,93 @@
.\"-
.\" Copyright (c) 2011 "Bjoern A. Zeeb" <bz@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.
.\"
.\" $FreeBSD$
.\"
.Dd November 3, 2011
.Dt QLXGB 4
.Os
.Sh NAME
.Nm qlxgb
.Nd "QLogic 10 Gigabit Ethernet & CNA Adapter Driver"
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device qlxgb"
.Ed
.Pp
To load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
if_qlxgb_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
driver supports IPv4 checksum offload,
TCP and UDP checksum offload for both IPv4 and IPv6,
Large Segment Offload for both IPv4 and IPv6,
Jumbo frames, VLAN Tag, and
Receive Side scaling.
For further hardware information, see
.Pa http://www.qlogic.com/ .
.Sh HARDWARE
The
.Nm
driver supports 10 Gigabit Ethernet & CNA Adapter based on the following
chipsets:
.Pp
.Bl -bullet -compact
.It
QLogic 3200 series
.It
QLogic 8200 series
.El
.Sh SUPPORT
For support questions please contact your QLogic approved reseller or
QLogic Technical Support at
.Pa http://support.qlogic.com ,
or by E-mail at
.Aq support@qlogic.com .
.Sh SEE ALSO
.Xr altq 4 ,
.Xr arp 4 ,
.Xr netintro 4 ,
.Xr ng_ether 4 ,
.Xr ifconfig 8
.Sh HISTORY
The
.Nm
device driver first appeared in
.Fx 10.0 .
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written by
.An David C Somayajulu
at Qlogic Corporation.

View File

@ -208,6 +208,12 @@ dev/lindev/lindev.c optional lindev
dev/nfe/if_nfe.c optional nfe pci
dev/nve/if_nve.c optional nve pci
dev/nvram/nvram.c optional nvram isa
dev/qlxgb/qla_dbg.c optional qlxgb pci
dev/qlxgb/qla_hw.c optional qlxgb pci
dev/qlxgb/qla_ioctl.c optional qlxgb pci
dev/qlxgb/qla_isr.c optional qlxgb pci
dev/qlxgb/qla_misc.c optional qlxgb pci
dev/qlxgb/qla_os.c optional qlxgb pci
dev/sio/sio.c optional sio
dev/sio/sio_isa.c optional sio isa
dev/sio/sio_pccard.c optional sio pccard

99
sys/dev/qlxgb/README.txt Normal file
View File

@ -0,0 +1,99 @@
# $FreeBSD$
README File
QLogic 3200 and 8200 series Single/Dual Port
10 Gigabit Ethernet & CNA Adapter Driver for FreeBSD 7.x/8.x/9.x
QLogic Corporation.
All rights reserved.
Table of Contents
1. Package Contents
2. OS Support
3. Supported Features
4. Using the Driver
4.1 Installing the driver
4.2 Removing the driver
5. Driver Parameters
6. Additional Notes
7. Contacting Support
1. Package Contents
* Documentation
- README (this document) version:1.0
- Release Notes Version:1.0
* Driver (if_qlxgb.ko)
- FreeBSD 7.x/8.x/9.x
* Firmware: pre-flashed on QLogic adapter;
2. OS Support
The Qlogic 10Gigabit Ethernet/CNA driver is compatible with the
following OS platforms:
* FreeBSD 7.x/8.x/9.x (64-bit) [Intel EM64T, AMD64]
3. Supported Features
10Gigabit Ethernet NIC/CNA driver supports following features
* Large Segment Offload over TCP IPV4
* Large Segment Offload over TCP IPV6
* Receive Side scaling
* TCP over IPv4 checksum offload
* UDP over IPv4 checksum offload
* IPV4 checksum offload
* TCP over IPv6 checksum offload
* UDP over IPv6 checksum offload
* Jumbo frames
* VLAN Tag
4. Using the driver
4.1 Installing the driver
- copy the driver file (if_qlxgb.ko) into some directory (say qla_driver)
- cd <to qla_driver>
- kldload -v ./if_qlxgb.ko
4.2 Removing the driver
- kldunload if_qlxgb
5. Parameters to set prior to installing the driver
- Add the following lines to /etc/sysctl.conf and reboot the machine prior
to installing the driver
kern.ipc.nmbjumbo9=262144
net.inet.tcp.recvbuf_max=262144
net.inet.tcp.recvbuf_inc=16384
kern.ipc.nmbclusters=1000000
kern.ipc.maxsockbuf=2097152
net.inet.tcp.recvspace=131072
net.inet.tcp.sendbuf_max=262144
net.inet.tcp.sendspace=65536
- If you do not want to reboot the system please run the following commands
login or su to root
sysctl kern.ipc.nmbjumbo9=262144
sysctl net.inet.tcp.recvbuf_max=262144
sysctl net.inet.tcp.recvbuf_inc=16384
sysctl kern.ipc.nmbclusters=1000000
sysctl kern.ipc.maxsockbuf=2097152
sysctl net.inet.tcp.recvspace=131072
sysctl net.inet.tcp.sendbuf_max=262144
sysctl net.inet.tcp.sendspace=65536
6. Contacting Support
Please feel free to contact your QLogic approved reseller or QLogic
Technical Support at any phase of integration for assistance. QLogic
Technical Support can be reached by the following methods:
Web: http://support.qlogic.com
E-mail: support@qlogic.com
(c) Copyright 2011. All rights reserved worldwide. QLogic, the QLogic
logo, and the Powered by QLogic logo are registered trademarks of
QLogic Corporation. All other brand and product names are trademarks
or registered trademarks of their respective owners.

263
sys/dev/qlxgb/qla_dbg.c Normal file
View File

@ -0,0 +1,263 @@
/*
* Copyright (c) 2010-2011 Qlogic 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 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.
*/
/*
* File : qla_dbg.c
* Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "qla_os.h"
#include "qla_reg.h"
#include "qla_hw.h"
#include "qla_def.h"
#include "qla_inline.h"
#include "qla_ver.h"
#include "qla_glbl.h"
#include "qla_dbg.h"
uint32_t dbg_level = 0 ;
/*
* Name: qla_dump_buf32
* Function: dumps a buffer as 32 bit words
*/
void qla_dump_buf32(qla_host_t *ha, char *msg, void *dbuf32, uint32_t len32)
{
device_t dev;
uint32_t i = 0;
uint32_t *buf;
dev = ha->pci_dev;
buf = dbuf32;
device_printf(dev, "%s: %s dump start\n", __func__, msg);
while (len32 >= 4) {
device_printf(dev,"0x%08x: 0x%08x 0x%08x 0x%08x 0x%08x\n",
i, buf[0], buf[1], buf[2], buf[3]);
i += 4 * 4;
len32 -= 4;
buf += 4;
}
switch (len32) {
case 1:
device_printf(dev,"0x%08x: 0x%08x\n", i, buf[0]);
break;
case 2:
device_printf(dev,"0x%08x: 0x%08x 0x%08x\n", i, buf[0], buf[1]);
break;
case 3:
device_printf(dev,"0x%08x: 0x%08x 0x%08x 0x%08x\n",
i, buf[0], buf[1], buf[2]);
break;
default:
break;
}
device_printf(dev, "%s: %s dump end\n", __func__, msg);
}
/*
* Name: qla_dump_buf16
* Function: dumps a buffer as 16 bit words
*/
void qla_dump_buf16(qla_host_t *ha, char *msg, void *dbuf16, uint32_t len16)
{
device_t dev;
uint32_t i = 0;
uint16_t *buf;
dev = ha->pci_dev;
buf = dbuf16;
device_printf(dev, "%s: %s dump start\n", __func__, msg);
while (len16 >= 8) {
device_printf(dev,"0x%08x: 0x%04x 0x%04x 0x%04x 0x%04x"
" 0x%04x 0x%04x 0x%04x 0x%04x\n", i, buf[0],
buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
i += 16;
len16 -= 8;
buf += 8;
}
switch (len16) {
case 1:
device_printf(dev,"0x%08x: 0x%04x\n", i, buf[0]);
break;
case 2:
device_printf(dev,"0x%08x: 0x%04x 0x%04x\n", i, buf[0], buf[1]);
break;
case 3:
device_printf(dev,"0x%08x: 0x%04x 0x%04x 0x%04x\n",
i, buf[0], buf[1], buf[2]);
break;
case 4:
device_printf(dev,"0x%08x: 0x%04x 0x%04x 0x%04x 0x%04x\n", i,
buf[0], buf[1], buf[2], buf[3]);
break;
case 5:
device_printf(dev,"0x%08x:"
" 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4]);
break;
case 6:
device_printf(dev,"0x%08x:"
" 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
break;
case 7:
device_printf(dev,"0x%04x: 0x%04x 0x%04x 0x%04x 0x%04x"
" 0x%04x 0x%04x 0x%04x\n", i, buf[0], buf[1],
buf[2], buf[3], buf[4], buf[5], buf[6]);
break;
default:
break;
}
device_printf(dev, "%s: %s dump end\n", __func__, msg);
}
/*
* Name: qla_dump_buf8
* Function: dumps a buffer as bytes
*/
void qla_dump_buf8(qla_host_t *ha, char *msg, void *dbuf, uint32_t len)
{
device_t dev;
uint32_t i = 0;
uint8_t *buf;
dev = ha->pci_dev;
buf = dbuf;
device_printf(dev, "%s: %s 0x%x dump start\n", __func__, msg, len);
while (len >= 16) {
device_printf(dev,"0x%08x:"
" %02x %02x %02x %02x %02x %02x %02x %02x"
" %02x %02x %02x %02x %02x %02x %02x %02x\n", i,
buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7],
buf[8], buf[9], buf[10], buf[11],
buf[12], buf[13], buf[14], buf[15]);
i += 16;
len -= 16;
buf += 16;
}
switch (len) {
case 1:
device_printf(dev,"0x%08x: %02x\n", i, buf[0]);
break;
case 2:
device_printf(dev,"0x%08x: %02x %02x\n", i, buf[0], buf[1]);
break;
case 3:
device_printf(dev,"0x%08x: %02x %02x %02x\n",
i, buf[0], buf[1], buf[2]);
break;
case 4:
device_printf(dev,"0x%08x: %02x %02x %02x %02x\n", i,
buf[0], buf[1], buf[2], buf[3]);
break;
case 5:
device_printf(dev,"0x%08x:"
" %02x %02x %02x %02x %02x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4]);
break;
case 6:
device_printf(dev,"0x%08x:"
" %02x %02x %02x %02x %02x %02x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
break;
case 7:
device_printf(dev,"0x%08x:"
" %02x %02x %02x %02x %02x %02x %02x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
break;
case 8:
device_printf(dev,"0x%08x:"
" %02x %02x %02x %02x %02x %02x %02x %02x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
buf[7]);
break;
case 9:
device_printf(dev,"0x%08x:"
" %02x %02x %02x %02x %02x %02x %02x %02x"
" %02x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
buf[7], buf[8]);
break;
case 10:
device_printf(dev,"0x%08x:"
" %02x %02x %02x %02x %02x %02x %02x %02x"
" %02x %02x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
buf[7], buf[8], buf[9]);
break;
case 11:
device_printf(dev,"0x%08x:"
" %02x %02x %02x %02x %02x %02x %02x %02x"
" %02x %02x %02x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
buf[7], buf[8], buf[9], buf[10]);
break;
case 12:
device_printf(dev,"0x%08x:"
" %02x %02x %02x %02x %02x %02x %02x %02x"
" %02x %02x %02x %02x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
buf[7], buf[8], buf[9], buf[10], buf[11]);
break;
case 13:
device_printf(dev,"0x%08x:"
" %02x %02x %02x %02x %02x %02x %02x %02x"
" %02x %02x %02x %02x %02x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
buf[7], buf[8], buf[9], buf[10], buf[11], buf[12]);
break;
case 14:
device_printf(dev,"0x%08x:"
" %02x %02x %02x %02x %02x %02x %02x %02x"
" %02x %02x %02x %02x %02x %02x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
buf[7], buf[8], buf[9], buf[10], buf[11], buf[12],
buf[13]);
break;
case 15:
device_printf(dev,"0x%08x:"
" %02x %02x %02x %02x %02x %02x %02x %02x"
" %02x %02x %02x %02x %02x %02x %02x\n", i,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6],
buf[7], buf[8], buf[9], buf[10], buf[11], buf[12],
buf[13], buf[14]);
break;
default:
break;
}
device_printf(dev, "%s: %s dump end\n", __func__, msg);
}

85
sys/dev/qlxgb/qla_dbg.h Normal file
View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2010-2011 Qlogic 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 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.
*
* $FreeBSD$
*/
/*
* File : qla_dbg.h
* Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
*/
#ifndef _QL_DBG_H_
#define _QL_DBG_H_
extern uint32_t dbg_level;
extern void qla_dump_buf8(qla_host_t *ha, char *str, void *dbuf,
uint32_t len);
extern void qla_dump_buf16(qla_host_t *ha, char *str, void *dbuf,
uint32_t len16);
extern void qla_dump_buf32(qla_host_t *ha, char *str, void *dbuf,
uint32_t len32);
#define DBG 1
#if DBG
#define QL_DPRINT1(x) if (dbg_level & 0x0001) device_printf x
#define QL_DPRINT2(x) if (dbg_level & 0x0002) device_printf x
#define QL_DPRINT4(x) if (dbg_level & 0x0004) device_printf x
#define QL_DPRINT8(x) if (dbg_level & 0x0008) device_printf x
#define QL_DPRINT10(x) if (dbg_level & 0x0010) device_printf x
#define QL_DPRINT20(x) if (dbg_level & 0x0020) device_printf x
#define QL_DPRINT40(x) if (dbg_level & 0x0040) device_printf x
#define QL_DPRINT80(x) if (dbg_level & 0x0080) device_printf x
#define QL_DUMP_BUFFER8(h, s, b, n) if (dbg_level & 0x08000000)\
qla_dump_buf8(h, s, b, n)
#define QL_DUMP_BUFFER16(h, s, b, n) if (dbg_level & 0x08000000)\
qla_dump_buf16(h, s, b, n)
#define QL_DUMP_BUFFER32(h, s, b, n) if (dbg_level & 0x08000000)\
qla_dump_buf32(h, s, b, n)
#else
#define QL_DPRINT1(x)
#define QL_DPRINT2(x)
#define QL_DPRINT4(x)
#define QL_DPRINT8(x)
#define QL_DPRINT10(x)
#define QL_DPRINT20(x)
#define QL_DPRINT40(x)
#define QL_DPRINT80(x)
#define QL_DUMP_BUFFER8(h, s, b, n)
#define QL_DUMP_BUFFER16(h, s, b, n)
#define QL_DUMP_BUFFER32(h, s, b, n)
#endif
#endif /* #ifndef _QL_DBG_H_ */

208
sys/dev/qlxgb/qla_def.h Normal file
View File

@ -0,0 +1,208 @@
/*
* Copyright (c) 2010-2011 Qlogic 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 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.
*
* $FreeBSD$
*/
/*
* File: qla_def.h
* Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
*/
#ifndef _QLA_DEF_H_
#define _QLA_DEF_H_
#define BIT_0 (0x1 << 0)
#define BIT_1 (0x1 << 1)
#define BIT_2 (0x1 << 2)
#define BIT_3 (0x1 << 3)
#define BIT_4 (0x1 << 4)
#define BIT_5 (0x1 << 5)
#define BIT_6 (0x1 << 6)
#define BIT_7 (0x1 << 7)
#define BIT_8 (0x1 << 8)
#define BIT_9 (0x1 << 9)
#define BIT_10 (0x1 << 10)
#define BIT_11 (0x1 << 11)
#define BIT_12 (0x1 << 12)
#define BIT_13 (0x1 << 13)
#define BIT_14 (0x1 << 14)
#define BIT_15 (0x1 << 15)
#define BIT_16 (0x1 << 16)
#define BIT_17 (0x1 << 17)
#define BIT_18 (0x1 << 18)
#define BIT_19 (0x1 << 19)
#define BIT_20 (0x1 << 20)
#define BIT_21 (0x1 << 21)
#define BIT_22 (0x1 << 22)
#define BIT_23 (0x1 << 23)
#define BIT_24 (0x1 << 24)
#define BIT_25 (0x1 << 25)
#define BIT_26 (0x1 << 26)
#define BIT_27 (0x1 << 27)
#define BIT_28 (0x1 << 28)
#define BIT_29 (0x1 << 29)
#define BIT_30 (0x1 << 30)
#define BIT_31 (0x1 << 31)
struct qla_rx_buf {
struct mbuf *m_head;
bus_dmamap_t map;
bus_addr_t paddr;
uint32_t handle;
void *next;
};
typedef struct qla_rx_buf qla_rx_buf_t;
struct qla_tx_buf {
struct mbuf *m_head;
bus_dmamap_t map;
};
typedef struct qla_tx_buf qla_tx_buf_t;
#define QLA_MAX_SEGMENTS 63 /* maximum # of segs in a sg list */
#define QLA_MAX_FRAME_SIZE MJUM9BYTES
#define QLA_STD_FRAME_SIZE 1514
#define QLA_MAX_TSO_FRAME_SIZE (64 * 1024 - 1)
/* Number of MSIX/MSI Vectors required */
#define Q8_MSI_COUNT 4
struct qla_ivec {
struct resource *irq;
void *handle;
int irq_rid;
void *ha;
struct task rcv_task;
struct taskqueue *rcv_tq;
};
typedef struct qla_ivec qla_ivec_t;
#define QLA_WATCHDOG_CALLOUT_TICKS 1
/*
* Adapter structure contains the hardware independant information of the
* pci function.
*/
struct qla_host {
volatile struct {
volatile uint32_t
qla_watchdog_active :1,
qla_watchdog_exit :1,
qla_watchdog_pause :1,
lro_init :1,
stop_rcv :1,
link_up :1,
parent_tag :1,
lock_init :1;
} flags;
device_t pci_dev;
uint8_t pci_func;
uint16_t watchdog_ticks;
uint8_t resvd;
/* ioctl related */
struct cdev *ioctl_dev;
/* register mapping */
struct resource *pci_reg;
int reg_rid;
/* interrupts */
struct resource *irq;
int msix_count;
void *intr_handle;
qla_ivec_t irq_vec[Q8_MSI_COUNT];
/* parent dma tag */
bus_dma_tag_t parent_tag;
/* interface to o.s */
struct ifnet *ifp;
struct ifmedia media;
uint16_t max_frame_size;
uint16_t rsrvd0;
int if_flags;
/* hardware access lock */
struct mtx hw_lock;
volatile uint32_t hw_lock_held;
/* transmit and receive buffers */
qla_tx_buf_t tx_buf[NUM_TX_DESCRIPTORS];
bus_dma_tag_t tx_tag;
struct mtx tx_lock;
struct task tx_task;
struct taskqueue *tx_tq;
struct callout tx_callout;
qla_rx_buf_t rx_buf[NUM_RX_DESCRIPTORS];
qla_rx_buf_t rx_jbuf[NUM_RX_JUMBO_DESCRIPTORS];
bus_dma_tag_t rx_tag;
struct mtx rx_lock;
struct mtx rxj_lock;
/* stats */
uint32_t err_m_getcl;
uint32_t err_m_getjcl;
uint32_t err_tx_dmamap_create;
uint32_t err_tx_dmamap_load;
uint32_t err_tx_defrag;
uint64_t rx_frames;
uint64_t rx_bytes;
uint64_t tx_frames;
uint64_t tx_bytes;
uint32_t fw_ver_major;
uint32_t fw_ver_minor;
uint32_t fw_ver_sub;
uint32_t fw_ver_build;
/* hardware specific */
qla_hw_t hw;
/* debug stuff */
volatile const char *qla_lock;
volatile const char *qla_unlock;
};
typedef struct qla_host qla_host_t;
/* note that align has to be a power of 2 */
#define QL_ALIGN(size, align) (size + (align - 1)) & ~(align - 1);
#define QL_MIN(x, y) ((x < y) ? x : y)
#define QL_RUNNING(ifp) \
((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) == \
IFF_DRV_RUNNING)
#endif /* #ifndef _QLA_DEF_H_ */

109
sys/dev/qlxgb/qla_glbl.h Normal file
View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2010-2011 Qlogic 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 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.
*
* $FreeBSD$
*/
/*
* File: qla_glbl.h
* Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
* Content: Contains prototypes of the exported functions from each file.
*/
#ifndef _QLA_GLBL_H_
#define _QLA_GLBL_H_
/*
* from qla_isr.c
*/
extern void qla_isr(void *arg);
extern void qla_rcv(void *context, int pending);
/*
* from qla_os.c
*/
extern uint32_t std_replenish;
extern uint32_t jumbo_replenish;
extern uint32_t rcv_pkt_thres;
extern uint32_t rcv_pkt_thres_d;
extern uint32_t snd_pkt_thres;
extern uint32_t free_pkt_thres;
extern int qla_alloc_dmabuf(qla_host_t *ha, qla_dma_t *dma_buf);
extern void qla_free_dmabuf(qla_host_t *ha, qla_dma_t *dma_buf);
extern void qla_start(struct ifnet *ifp);
extern int qla_get_mbuf(qla_host_t *ha, qla_rx_buf_t *rxb, struct mbuf *nmp,
uint32_t jumbo);
/*
* from qla_flash.c
*/
extern int qla_flash_rd32_words(qla_host_t *ha, uint32_t addr,
uint32_t *val, uint32_t num);
extern int qla_flash_rd32(qla_host_t *ha, uint32_t addr, uint32_t *val);
/*
* from qla_hw.c
*/
extern int qla_get_msix_count(qla_host_t *ha);
extern int qla_alloc_dma(qla_host_t *ha);
extern void qla_free_dma(qla_host_t *ha);
extern void qla_hw_add_sysctls(qla_host_t *ha);
extern int qla_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
uint32_t *tx_idx, struct mbuf *mp);
extern int qla_init_hw_if(qla_host_t *ha);
extern void qla_get_hw_caps(qla_host_t *ha);
extern void qla_hw_set_multi(qla_host_t *ha, uint8_t *mta, uint32_t mcnt,
uint32_t add_multi);
extern void qla_del_hw_if(qla_host_t *ha);
extern void qla_set_promisc(qla_host_t *ha);
extern void qla_set_allmulti(qla_host_t *ha);
extern void qla_reset_promisc_allmulti(qla_host_t *ha);
extern void qla_config_ipv4_addr(qla_host_t *ha, uint32_t ipv4_addr);
extern int qla_hw_tx_compl(qla_host_t *ha);
extern void qla_update_link_state(qla_host_t *ha);
extern void qla_hw_tx_done(qla_host_t *ha);
extern int qla_config_lro(qla_host_t *ha);
extern void qla_free_lro(qla_host_t *ha);
extern int qla_set_max_mtu(qla_host_t *ha, uint32_t mtu, uint16_t cntxt_id);
extern void qla_hw_stop_rcv(qla_host_t *ha);
/*
* from qla_misc.c
*/
extern int qla_init_hw(qla_host_t *ha);
extern int qla_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val,
uint32_t rd);
extern int qla_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data);
/*
* from qla_ioctl.c
*/
extern int qla_make_cdev(qla_host_t *ha);
extern void qla_del_cdev(qla_host_t *ha);
extern int qla_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
struct thread *td);
#endif /* #ifndef_QLA_GLBL_H_ */

1776
sys/dev/qlxgb/qla_hw.c Normal file

File diff suppressed because it is too large Load Diff

831
sys/dev/qlxgb/qla_hw.h Normal file
View File

@ -0,0 +1,831 @@
/*
* Copyright (c) 2010-2011 Qlogic 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 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.
*
* $FreeBSD$
*/
/*
* File: qla_hw.h
* Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
*/
#ifndef _QLA_HW_H_
#define _QLA_HW_H_
#define Q8_MAX_NUM_MULTICAST_ADDRS 128
#define Q8_MAC_ADDR_LEN 6
/*
* Firmware Interface
*/
/*
* Command Response Interface - Commands
*/
typedef struct qla_cdrp {
uint32_t cmd;
uint32_t cmd_arg1;
uint32_t cmd_arg2;
uint32_t cmd_arg3;
uint32_t rsp;
uint32_t rsp_arg1;
uint32_t rsp_arg2;
uint32_t rsp_arg3;
} qla_cdrp_t;
#define Q8_CMD_RD_MAX_RDS_PER_CNTXT 0x80000002
#define Q8_CMD_RD_MAX_SDS_PER_CNTXT 0x80000003
#define Q8_CMD_RD_MAX_RULES_PER_CNTXT 0x80000004
#define Q8_CMD_RD_MAX_RX_CNTXT 0x80000005
#define Q8_CMD_RD_MAX_TX_CNTXT 0x80000006
#define Q8_CMD_CREATE_RX_CNTXT 0x80000007
#define Q8_CMD_DESTROY_RX_CNTXT 0x80000008
#define Q8_CMD_CREATE_TX_CNTXT 0x80000009
#define Q8_CMD_DESTROY_TX_CNTXT 0x8000000A
#define Q8_CMD_SETUP_STATS 0x8000000E
#define Q8_CMD_GET_STATS 0x8000000F
#define Q8_CMD_DELETE_STATS 0x80000010
#define Q8_CMD_GEN_INT 0x80000011
#define Q8_CMD_SET_MTU 0x80000012
#define Q8_CMD_GET_FLOW_CNTRL 0x80000016
#define Q8_CMD_SET_FLOW_CNTRL 0x80000017
#define Q8_CMD_RD_MAX_MTU 0x80000018
#define Q8_CMD_RD_MAX_LRO 0x80000019
/*
* Command Response Interface - Response
*/
#define Q8_RSP_SUCCESS 0x00000000
#define Q8_RSP_NO_HOST_MEM 0x00000001
#define Q8_RSP_NO_HOST_RSRC 0x00000002
#define Q8_RSP_NO_CARD_CRB 0x00000003
#define Q8_RSP_NO_CARD_MEM 0x00000004
#define Q8_RSP_NO_CARD_RSRC 0x00000005
#define Q8_RSP_INVALID_ARGS 0x00000006
#define Q8_RSP_INVALID_ACTION 0x00000007
#define Q8_RSP_INVALID_STATE 0x00000008
#define Q8_RSP_NOT_SUPPORTED 0x00000009
#define Q8_RSP_NOT_PERMITTED 0x0000000A
#define Q8_RSP_NOT_READY 0x0000000B
#define Q8_RSP_DOES_NOT_EXIST 0x0000000C
#define Q8_RSP_ALREADY_EXISTS 0x0000000D
#define Q8_RSP_BAD_SIGNATURE 0x0000000E
#define Q8_RSP_CMD_NOT_IMPLEMENTED 0x0000000F
#define Q8_RSP_CMD_INVALID 0x00000010
#define Q8_RSP_TIMEOUT 0x00000011
/*
* Transmit Related Definitions
*/
/*
* Transmit Context - Q8_CMD_CREATE_TX_CNTXT Command Configuration Data
*/
typedef struct _q80_tx_cntxt_req {
uint64_t rsp_dma_addr; /* rsp from firmware is DMA'ed here */
uint64_t cmd_cons_dma_addr;
uint64_t rsrvd0;
uint32_t caps[4]; /* capabilities - bit vector*/
#define CNTXT_CAP0_BASEFW 0x0001
#define CNTXT_CAP0_LEGACY_MN 0x0004
#define CNTXT_CAP0_LSO 0x0040
uint32_t intr_mode; /* Interrupt Mode */
#define CNTXT_INTR_MODE_UNIQUE 0x0000
#define CNTXT_INTR_MODE_SHARED 0x0001
uint64_t rsrvd1;
uint16_t msi_index;
uint16_t rsrvd2;
uint64_t phys_addr; /* physical address of transmit ring
* in system memory */
uint32_t num_entries; /* number of entries in transmit ring */
uint8_t rsrvd3[128];
} __packed q80_tx_cntxt_req_t; /* 188 bytes total */
/*
* Transmit Context - Response from Firmware to Q8_CMD_CREATE_TX_CNTXT
*/
typedef struct _q80_tx_cntxt_rsp {
uint32_t cntxt_state; /* starting state */
#define CNTXT_STATE_ALLOCATED_NOT_ACTIVE 0x0001
#define CNTXT_STATE_ACTIVE 0x0002
#define CNTXT_STATE_QUIESCED 0x0004
uint16_t cntxt_id; /* handle for context */
uint8_t phys_port_id; /* physical id of port */
uint8_t virt_port_id; /* virtual or logical id of port */
uint32_t producer_reg; /* producer register for transmit ring */
uint32_t intr_mask_reg; /* interrupt mask register */
uint8_t rsrvd[128];
} __packed q80_tx_cntxt_rsp_t; /* 144 bytes */
/*
* Transmit Command Descriptor
* These commands are issued on the Transmit Ring associated with a Transmit
* context
*/
typedef struct _q80_tx_cmd {
uint8_t tcp_hdr_off; /* TCP Header Offset */
uint8_t ip_hdr_off; /* IP Header Offset */
uint16_t flags_opcode; /* Bits 0-6: flags; 7-12: opcode */
/* flags field */
#define Q8_TX_CMD_FLAGS_MULTICAST 0x01
#define Q8_TX_CMD_FLAGS_LSO_TSO 0x02
#define Q8_TX_CMD_FLAGS_VLAN_TAGGED 0x10
#define Q8_TX_CMD_FLAGS_HW_VLAN_ID 0x40
/* opcode field */
#define Q8_TX_CMD_OP_XMT_UDP_CHKSUM_IPV6 (0xC << 7)
#define Q8_TX_CMD_OP_XMT_TCP_CHKSUM_IPV6 (0xB << 7)
#define Q8_TX_CMD_OP_XMT_TCP_LSO_IPV6 (0x6 << 7)
#define Q8_TX_CMD_OP_XMT_TCP_LSO (0x5 << 7)
#define Q8_TX_CMD_OP_XMT_UDP_CHKSUM (0x3 << 7)
#define Q8_TX_CMD_OP_XMT_TCP_CHKSUM (0x2 << 7)
#define Q8_TX_CMD_OP_XMT_ETHER (0x1 << 7)
uint8_t n_bufs; /* # of data segs in data buffer */
uint8_t data_len_lo; /* data length lower 8 bits */
uint16_t data_len_hi; /* data length upper 16 bits */
uint64_t buf2_addr; /* buffer 2 address */
uint16_t rsrvd0;
uint16_t mss; /* MSS for this packet */
uint8_t port_cntxtid; /* Bits 7-4: ContextId; 3-0: reserved */
#define Q8_TX_CMD_PORT_CNXTID(c_id) ((c_id & 0xF) << 4)
uint8_t total_hdr_len; /* MAC+IP+TCP Header Length for LSO */
uint16_t rsrvd1;
uint64_t buf3_addr; /* buffer 3 address */
uint64_t buf1_addr; /* buffer 1 address */
uint16_t buf1_len; /* length of buffer 1 */
uint16_t buf2_len; /* length of buffer 2 */
uint16_t buf3_len; /* length of buffer 3 */
uint16_t buf4_len; /* length of buffer 4 */
uint64_t buf4_addr; /* buffer 4 address */
uint32_t rsrvd2;
uint16_t rsrvd3;
uint16_t vlan_tci; /* VLAN TCI when hw tagging is enabled*/
} __packed q80_tx_cmd_t; /* 64 bytes */
#define Q8_TX_CMD_MAX_SEGMENTS 4
#define Q8_TX_CMD_TSO_ALIGN 2
#define Q8_TX_MAX_SEGMENTS 14
/*
* Receive Related Definitions
*/
/*
* Receive Context - Q8_CMD_CREATE_RX_CNTXT Command Configuration Data
*/
typedef struct _q80_rq_sds_ring {
uint64_t phys_addr; /* physical addr of status ring in system memory */
uint32_t size; /* number of entries in status ring */
uint16_t msi_index;
uint16_t rsrvd;
} __packed q80_rq_sds_ring_t; /* 16 bytes */
typedef struct _q80_rq_rds_ring {
uint64_t phys_addr; /* physical addr of rcv ring in system memory */
uint64_t buf_size; /* packet buffer size */
uint32_t size; /* number of entries in ring */
uint32_t rsrvd;
} __packed q80_rq_rds_ring_t; /* 24 bytes */
typedef struct _q80_rq_rcv_cntxt {
uint64_t rsp_dma_addr; /* rsp from firmware is DMA'ed here */
uint32_t caps[4]; /* bit vector */
#define CNTXT_CAP0_JUMBO 0x0080 /* Contiguous Jumbo buffers*/
#define CNTXT_CAP0_LRO 0x0100
#define CNTXT_CAP0_HW_LRO 0x0800 /* HW LRO */
uint32_t intr_mode; /* same as q80_tx_cntxt_req_t */
uint32_t rds_intr_mode; /* same as q80_tx_cntxt_req_t */
uint32_t rds_ring_offset; /* rds configuration relative to data[0] */
uint32_t sds_ring_offset; /* sds configuration relative to data[0] */
uint16_t num_rds_rings;
uint16_t num_sds_rings;
uint8_t rsrvd1[132];
} __packed q80_rq_rcv_cntxt_t; /* 176 bytes header + rds + sds ring rqsts */
/*
* Receive Context - Response from Firmware to Q8_CMD_CREATE_RX_CNTXT
*/
typedef struct _q80_rsp_rds_ring {
uint32_t producer_reg;
uint32_t rsrvd;
} __packed q80_rsp_rds_ring_t; /* 8 bytes */
typedef struct _q80_rsp_sds_ring {
uint32_t consumer_reg;
uint32_t intr_mask_reg;
} __packed q80_rsp_sds_ring_t; /* 8 bytes */
typedef struct _q80_rsp_rcv_cntxt {
uint32_t rds_ring_offset; /* rds configuration relative to data[0] */
uint32_t sds_ring_offset; /* sds configuration relative to data[0] */
uint32_t cntxt_state; /* starting state */
uint32_t funcs_per_port; /* number of PCI functions sharing each port */
uint16_t num_rds_rings;
uint16_t num_sds_rings;
uint16_t cntxt_id; /* handle for context */
uint8_t phys_port; /* physical id of port */
uint8_t virt_port; /* virtual or logical id of port */
uint8_t rsrvd[128];
uint8_t data[0];
} __packed q80_rsp_rcv_cntxt_t; /* 152 bytes header + rds + sds ring rspncs */
/*
* Note:
* Transmit Context
* 188 (rq) + 144 (rsp) = 332 bytes are required
*
* Receive Context
* 1 RDS and 1 SDS rings: (16+24+176)+(8+8+152) = 384 bytes
*
* 3 RDS and 4 SDS rings: (((16+24)*3)+176) + (((8+8)*4)+152) =
* = 296 + 216 = 512 bytes
* Clearly this within the minimum PAGE size of most O.S platforms
* (typically 4Kbytes). Hence it is simpler to simply allocate one PAGE
* and then carve out space for each context. It is also a good idea to
* to throw in the shadown register for the consumer index of the transmit
* ring in this PAGE.
*/
/*
* Receive Descriptor corresponding to each entry in the receive ring
*/
typedef struct _q80_rcv_desc {
uint16_t handle;
uint16_t rsrvd;
uint32_t buf_size; /* buffer size in bytes */
uint64_t buf_addr; /* physical address of buffer */
} __packed q80_recv_desc_t;
/*
* Status Descriptor corresponding to each entry in the Status ring
*/
typedef struct _q80_stat_desc {
uint64_t data[2];
} __packed q80_stat_desc_t;
/*
* definitions for data[0] field of Status Descriptor
*/
#define Q8_STAT_DESC_OWNER(data) ((data >> 56) & 0x3)
#define Q8_STAT_DESC_OWNER_HOST 0x1
#define Q8_STAT_DESC_OWNER_FW 0x2
#define Q8_STAT_DESC_OWNER_MASK (((uint64_t)0x3) << 56)
#define Q8_STAT_DESC_SET_OWNER(owner) (uint64_t)(((uint64_t)owner) << 56)
#define Q8_STAT_DESC_OPCODE(data) ((data >> 58) & 0x003F)
#define Q8_STAT_DESC_OPCODE_SYN_OFFLOAD 0x03
#define Q8_STAT_DESC_OPCODE_RCV_PKT 0x04
#define Q8_STAT_DESC_OPCODE_CTRL_MSG 0x05
#define Q8_STAT_DESC_OPCODE_LRO_PKT 0x12
/*
* definitions for data[0] field of Status Descriptor for standard frames
* status descriptor opcode equals 0x04
*/
#define Q8_STAT_DESC_PORT(data) ((data) & 0x000F)
#define Q8_STAT_DESC_STATUS(data) ((data >> 4) & 0x000F)
#define Q8_STAT_DESC_STATUS_NO_CHKSUM 0x01
#define Q8_STAT_DESC_STATUS_CHKSUM_OK 0x02
#define Q8_STAT_DESC_STATUS_CHKSUM_ERR 0x03
#define Q8_STAT_DESC_TYPE(data) ((data >> 8) & 0x000F)
#define Q8_STAT_DESC_TOTAL_LENGTH(data) ((data >> 12) & 0xFFFF)
#define Q8_STAT_DESC_HANDLE(data) ((data >> 28) & 0xFFFF)
#define Q8_STAT_DESC_PROTOCOL(data) ((data >> 44) & 0x000F)
#define Q8_STAT_DESC_L2_OFFSET(data) ((data >> 48) & 0x001F)
#define Q8_STAT_DESC_COUNT(data) ((data >> 53) & 0x0007)
/*
* definitions for data[0-1] fields of Status Descriptor for LRO
* status descriptor opcode equals 0x05
*/
/* definitions for data[0] field */
#define Q8_LRO_STAT_DESC_HANDLE(data) ((data) & 0xFFFF)
#define Q8_LRO_STAT_DESC_PAYLOAD_LENGTH(data) ((data >> 16) & 0xFFFF)
#define Q8_LRO_STAT_DESC_L2_OFFSET(data) ((data >> 32) & 0xFF)
#define Q8_LRO_STAT_DESC_L4_OFFSET(data) ((data >> 40) & 0xFF)
#define Q8_LRO_STAT_DESC_TS_PRESENT(data) ((data >> 48) & 0x1)
#define Q8_LRO_STAT_DESC_TYPE(data) ((data >> 49) & 0x7)
#define Q8_LRO_STAT_DESC_PUSH_BIT(data) ((data >> 52) & 0x1)
/* definitions for data[1] field */
#define Q8_LRO_STAT_DESC_SEQ_NUM(data) (uint32_t)(data)
/** Driver Related Definitions Begin **/
#define MAX_RDS_RINGS 2 /* Max# of Receive Descriptor Rings */
#define MAX_SDS_RINGS 4 /* Max# of Status Descriptor Rings */
#define TX_SMALL_PKT_SIZE 128 /* size in bytes of small packets */
/* The number of descriptors should be a power of 2 */
#define NUM_TX_DESCRIPTORS 2048
#define NUM_RX_DESCRIPTORS 8192
//#define NUM_RX_JUMBO_DESCRIPTORS 1024
#define NUM_RX_JUMBO_DESCRIPTORS 2048
//#define NUM_STATUS_DESCRIPTORS 8192
#define NUM_STATUS_DESCRIPTORS 2048
typedef struct _q80_rcv_cntxt_req {
q80_rq_rcv_cntxt_t rx_req;
q80_rq_rds_ring_t rds_req[MAX_RDS_RINGS];
q80_rq_sds_ring_t sds_req[MAX_SDS_RINGS];
} __packed q80_rcv_cntxt_req_t;
typedef struct _q80_rcv_cntxt_rsp {
q80_rsp_rcv_cntxt_t rx_rsp;
q80_rsp_rds_ring_t rds_rsp[MAX_RDS_RINGS];
q80_rsp_sds_ring_t sds_rsp[MAX_SDS_RINGS];
} __packed q80_rcv_cntxt_rsp_t;
/*
* structure describing various dma buffers
*/
#define RDS_RING_INDEX_NORMAL 0
#define RDS_RING_INDEX_JUMBO 1
typedef struct qla_dmabuf {
volatile struct {
uint32_t tx_ring :1,
rds_ring :1,
sds_ring :1,
context :1;
} flags;
qla_dma_t tx_ring;
qla_dma_t rds_ring[MAX_RDS_RINGS];
qla_dma_t sds_ring[MAX_SDS_RINGS];
qla_dma_t context;
} qla_dmabuf_t;
/** Driver Related Definitions End **/
/*
* Firmware Control Descriptor
*/
typedef struct _qla_fw_cds_hdr {
uint64_t cmd;
#define Q8_FWCD_CNTRL_REQ (0x13 << 23)
uint8_t opcode;
uint8_t cookie;
uint16_t cntxt_id;
uint8_t response;
#define Q8_FW_CDS_HDR_COMPLETION 0x1
uint16_t rsrvd;
uint8_t sub_opcode;
} __packed qla_fw_cds_hdr_t;
/*
* definitions for opcode in qla_fw_cds_hdr_t
*/
#define Q8_FWCD_OPCODE_CONFIG_RSS 0x01
#define Q8_FWCD_OPCODE_CONFIG_RSS_TABLE 0x02
#define Q8_FWCD_OPCODE_CONFIG_INTR_COALESCING 0x03
#define Q8_FWCD_OPCODE_CONFIG_LED 0x04
#define Q8_FWCD_OPCODE_CONFIG_MAC_ADDR 0x06
#define Q8_FWCD_OPCODE_LRO_FLOW 0x07
#define Q8_FWCD_OPCODE_GET_SNMP_STATS 0x08
#define Q8_FWCD_OPCODE_CONFIG_MAC_RCV_MODE 0x0C
#define Q8_FWCD_OPCODE_STATISTICS 0x10
#define Q8_FWCD_OPCODE_CONFIG_IPADDR 0x12
#define Q8_FWCD_OPCODE_CONFIG_LOOPBACK 0x13
#define Q8_FWCD_OPCODE_LINK_EVENT_REQ 0x15
#define Q8_FWCD_OPCODE_CONFIG_BRIDGING 0x17
#define Q8_FWCD_OPCODE_CONFIG_LRO 0x18
/*
* Configure RSS
*/
typedef struct _qla_fw_cds_config_rss {
qla_fw_cds_hdr_t hdr;
uint8_t hash_type;
#define Q8_FWCD_RSS_HASH_TYPE_IPV4_TCP (0x2 << 4)
#define Q8_FWCD_RSS_HASH_TYPE_IPV4_IP (0x1 << 4)
#define Q8_FWCD_RSS_HASH_TYPE_IPV4_TCP_IP (0x3 << 4)
#define Q8_FWCD_RSS_HASH_TYPE_IPV6_TCP (0x2 << 6)
#define Q8_FWCD_RSS_HASH_TYPE_IPV6_IP (0x1 << 6)
#define Q8_FWCD_RSS_HASH_TYPE_IPV6_TCP_IP (0x3 << 6)
uint8_t flags;
#define Q8_FWCD_RSS_FLAGS_ENABLE_RSS 0x1
#define Q8_FWCD_RSS_FLAGS_USE_IND_TABLE 0x2
uint8_t rsrvd[4];
uint16_t ind_tbl_mask;
uint64_t rss_key[5];
} __packed qla_fw_cds_config_rss_t;
/*
* Configure RSS Table
*/
typedef struct _qla_fw_cds_config_rss_table {
qla_fw_cds_hdr_t hdr;
uint64_t index;
uint8_t table[40];
} __packed qla_fw_cds_config_rss_table_t;
/*
* Configure Interrupt Coalescing
*/
typedef struct _qla_fw_cds_config_intr_coalesc {
qla_fw_cds_hdr_t hdr;
uint16_t rsrvd0;
uint16_t rsrvd1;
uint16_t flags;
uint16_t rsrvd2;
uint64_t rsrvd3;
uint16_t max_rcv_pkts;
uint16_t max_rcv_usecs;
uint16_t max_snd_pkts;
uint16_t max_snd_usecs;
uint64_t rsrvd4;
uint64_t rsrvd5;
uint32_t usecs_to;
uint8_t timer_type;
#define Q8_FWCMD_INTR_COALESC_TIMER_NONE 0x00
#define Q8_FWCMD_INTR_COALESC_TIMER_ONCE 0x01
#define Q8_FWCMD_INTR_COALESC_TIMER_PERIODIC 0x02
uint8_t sds_ring_bitmask;
#define Q8_FWCMD_INTR_COALESC_SDS_RING_0 0x01
#define Q8_FWCMD_INTR_COALESC_SDS_RING_1 0x02
#define Q8_FWCMD_INTR_COALESC_SDS_RING_2 0x04
#define Q8_FWCMD_INTR_COALESC_SDS_RING_3 0x08
uint16_t rsrvd6;
} __packed qla_fw_cds_config_intr_coalesc_t;
/*
* Configure LED Parameters
*/
typedef struct _qla_fw_cds_config_led {
qla_fw_cds_hdr_t hdr;
uint32_t cntxt_id;
uint32_t blink_rate;
uint32_t blink_state;
uint32_t rsrvd;
} __packed qla_fw_cds_config_led_t;
/*
* Configure MAC Address
*/
typedef struct _qla_fw_cds_config_mac_addr {
qla_fw_cds_hdr_t hdr;
uint8_t cmd;
#define Q8_FWCD_ADD_MAC_ADDR 0x1
#define Q8_FWCD_DEL_MAC_ADDR 0x2
uint8_t rsrvd;
uint8_t mac_addr[6];
} __packed qla_fw_cds_config_mac_addr_t;
/*
* Configure Add/Delete LRO
*/
typedef struct _qla_fw_cds_config_lro {
qla_fw_cds_hdr_t hdr;
uint32_t dst_ip_addr;
uint32_t src_ip_addr;
uint16_t dst_tcp_port;
uint16_t src_tcp_port;
uint8_t ipv6;
uint8_t time_stamp;
uint16_t rsrvd;
uint32_t rss_hash;
uint32_t host_handle;
} __packed qla_fw_cds_config_lro_t;
/*
* Get SNMP Statistics
*/
typedef struct _qla_fw_cds_get_snmp {
qla_fw_cds_hdr_t hdr;
uint64_t phys_addr;
uint16_t size;
uint16_t cntxt_id;
uint32_t rsrvd;
} __packed qla_fw_cds_get_snmp_t;
typedef struct _qla_snmp_stats {
uint64_t jabber_state;
uint64_t false_carrier;
uint64_t rsrvd;
uint64_t mac_cntrl;
uint64_t align_errors;
uint64_t chksum_errors;
uint64_t oversize_frames;
uint64_t tx_errors;
uint64_t mac_rcv_errors;
uint64_t phy_rcv_errors;
uint64_t rcv_pause;
uint64_t tx_pause;
} __packed qla_snmp_stats_t;
/*
* Enable Link Event Requests
*/
typedef struct _qla_link_event_req {
qla_fw_cds_hdr_t hdr;
uint8_t enable;
uint8_t get_clnk_params;
uint8_t pad[6];
} __packed qla_link_event_req_t;
/*
* Set MAC Receive Mode
*/
typedef struct _qla_set_mac_rcv_mode {
qla_fw_cds_hdr_t hdr;
uint32_t mode;
#define Q8_MAC_RCV_RESET_PROMISC_ALLMULTI 0x00
#define Q8_MAC_RCV_ENABLE_PROMISCUOUS 0x01
#define Q8_MAC_RCV_ENABLE_ALLMULTI 0x02
uint8_t pad[4];
} __packed qla_set_mac_rcv_mode_t;
/*
* Configure IP Address
*/
typedef struct _qla_config_ipv4 {
qla_fw_cds_hdr_t hdr;
uint64_t cmd;
#define Q8_CONFIG_CMD_IP_ENABLE 0x02
#define Q8_CONFIG_CMD_IP_DISABLE 0x03
uint64_t ipv4_addr;
} __packed qla_config_ipv4_t;
/*
* Configure LRO
*/
typedef struct _qla_config_lro {
qla_fw_cds_hdr_t hdr;
uint64_t cmd;
#define Q8_CONFIG_LRO_ENABLE 0x08
} __packed qla_config_lro_t;
/*
* Control Messages Received on SDS Ring
*/
/* Header */
typedef struct _qla_cntrl_msg_hdr {
uint16_t rsrvd0;
uint16_t err_code;
uint8_t rsp_type;
uint8_t comp_id;
uint16_t tag;
#define Q8_CTRL_MSG_TAG_DESC_COUNT_MASK (0x7 << 5)
#define Q8_CTRL_MSG_TAG_OWNER_MASK (0x3 << 8)
#define Q8_CTRL_MSG_TAG_OPCODE_MASK (0x3F << 10)
} __packed qla_cntrl_msg_hdr_t;
/*
* definitions for rsp_type in qla_cntrl_msg_hdr_t
*/
#define Q8_CTRL_CONFIG_MAC_RSP 0x85
#define Q8_CTRL_LRO_FLOW_DELETE_RSP 0x86
#define Q8_CTRL_LRO_FLOW_ADD_FAILURE_RSP 0x87
#define Q8_CTRL_GET_SNMP_STATS_RSP 0x88
#define Q8_CTRL_GET_NETWORK_STATS_RSP 0x8C
#define Q8_CTRL_LINK_EVENT_NOTIFICATION 0x8D
/*
* Configure MAC Response
*/
typedef struct _qla_config_mac_rsp {
uint32_t rval;
uint32_t rsrvd;
} __packed qla_config_mac_rsp_t;
/*
* LRO Flow Response (can be LRO Flow Delete and LRO Flow Add Failure)
*/
typedef struct _qla_lro_flow_rsp {
uint32_t handle;
uint32_t rss_hash;
uint32_t dst_ip;
uint32_t src_ip;
uint16_t dst_tcp_port;
uint16_t src_tcp_port;
uint8_t ipv6;
uint8_t rsrvd0;
uint16_t rsrvd1;
} __packed qla_lro_flow_rsp_t;
/*
* Get SNMP Statistics Response
*/
typedef struct _qla_get_snmp_stats_rsp {
uint64_t rsrvd;
} __packed qla_get_snmp_stats_rsp_t;
/*
* Get Network Statistics Response
*/
typedef struct _qla_get_net_stats_rsp {
uint64_t rsrvd;
} __packed qla_get_net_stats_rsp_t;
/*
* Link Event Notification
*/
typedef struct _qla_link_event {
uint32_t cable_oui;
uint16_t cable_length;
uint16_t link_speed;
#define Q8_LE_SPEED_MASK 0xFFF
#define Q8_LE_SPEED_10GBPS 0x710
#define Q8_LE_SPEED_1GBPS 0x3E8
#define Q8_LE_SPEED_100MBPS 0x064
#define Q8_LE_SPEED_10MBPS 0x00A
uint8_t link_up;/* 0 = down; else up */
uint8_t mod_info;
#define Q8_LE_MI_MODULE_NOT_PRESENT 0x01
#define Q8_LE_MI_UNKNOWN_OPTICAL_MODULE 0x02
#define Q8_LE_MI_SR_LR_OPTICAL_MODULE 0x03
#define Q8_LE_MI_LRM_OPTICAL_MODULE 0x04
#define Q8_LE_MI_SFP_1G_MODULE 0x05
#define Q8_LE_MI_UNSUPPORTED_TWINAX 0x06
#define Q8_LE_MI_UNSUPPORTED_TWINAX_LENGTH 0x07
#define Q8_LE_MI_SUPPORTED_TWINAX 0x08
uint8_t fduplex; /* 1 = full duplex; 0 = half duplex */
uint8_t autoneg; /* 1 = autoneg enable; 0 = disabled */
uint32_t rsrvd;
} __packed qla_link_event_t;
typedef struct _qla_sds {
q80_stat_desc_t *sds_ring_base; /* start of sds ring */
uint32_t sdsr_next; /* next entry in SDS ring to process */
struct lro_ctrl lro;
void *rxb_free;
uint32_t rx_free;
void *rxjb_free;
uint32_t rxj_free;
volatile uint32_t rcv_active;
} qla_sds_t;
/*
* struct for storing hardware specific information for a given interface
*/
typedef struct _qla_hw {
struct {
uint32_t
lro :1,
init_tx_cnxt :1,
init_rx_cnxt :1,
fduplex :1,
autoneg :1,
link_up :1;
} flags;
uint16_t link_speed;
uint16_t cable_length;
uint16_t cable_oui;
uint8_t mod_info;
uint8_t rsrvd;
uint32_t max_rds_per_cntxt;
uint32_t max_sds_per_cntxt;
uint32_t max_rules_per_cntxt;
uint32_t max_rcv_cntxts;
uint32_t max_xmt_cntxts;
uint32_t max_mtu;
uint32_t max_lro;
uint8_t mac_addr[ETHER_ADDR_LEN];
uint16_t num_rds_rings;
uint16_t num_sds_rings;
qla_dmabuf_t dma_buf;
/* Transmit Side */
q80_tx_cmd_t *tx_ring_base;
q80_tx_cntxt_req_t *tx_cntxt_req; /* TX Context Request */
bus_addr_t tx_cntxt_req_paddr;
q80_tx_cntxt_rsp_t *tx_cntxt_rsp; /* TX Context Response */
bus_addr_t tx_cntxt_rsp_paddr;
uint32_t *tx_cons; /* tx consumer shadow reg */
bus_addr_t tx_cons_paddr;
volatile uint32_t txr_free; /* # of free entries in tx ring */
volatile uint32_t txr_next; /* # next available tx ring entry */
volatile uint32_t txr_comp; /* index of last tx entry completed */
uint32_t tx_prod_reg;
/* Receive Side */
volatile uint32_t rx_next; /* next standard rcv ring to arm fw */
volatile int32_t rxj_next; /* next jumbo rcv ring to arm fw */
volatile int32_t rx_in; /* next standard rcv ring to add mbufs */
volatile int32_t rxj_in; /* next jumbo rcv ring to add mbufs */
q80_rcv_cntxt_req_t *rx_cntxt_req; /* Rcv Context Request */
bus_addr_t rx_cntxt_req_paddr;
q80_rcv_cntxt_rsp_t *rx_cntxt_rsp; /* Rcv Context Response */
bus_addr_t rx_cntxt_rsp_paddr;
qla_sds_t sds[MAX_SDS_RINGS];
} qla_hw_t;
#define QL_UPDATE_RDS_PRODUCER_INDEX(ha, i, val) \
WRITE_REG32(ha, ((ha->hw.rx_cntxt_rsp)->rds_rsp[i].producer_reg +\
0x1b2000), val)
#define QL_UPDATE_TX_PRODUCER_INDEX(ha, val) \
WRITE_REG32(ha, (ha->hw.tx_prod_reg + 0x1b2000), val)
#define QL_UPDATE_SDS_CONSUMER_INDEX(ha, i, val) \
WRITE_REG32(ha, ((ha->hw.rx_cntxt_rsp)->sds_rsp[i].consumer_reg +\
0x1b2000), val)
#define QL_CLEAR_INTERRUPTS(ha) \
if (ha->pci_func == 0) {\
WRITE_REG32(ha, Q8_INT_TARGET_STATUS_F0, 0xFFFFFFFF);\
} else {\
WRITE_REG32(ha, Q8_INT_TARGET_STATUS_F1, 0xFFFFFFFF);\
}\
#define QL_ENABLE_INTERRUPTS(ha, sds_index) \
{\
q80_rsp_sds_ring_t *rsp_sds;\
rsp_sds = &((ha->hw.rx_cntxt_rsp)->sds_rsp[sds_index]);\
WRITE_REG32(ha, (rsp_sds->intr_mask_reg + 0x1b2000), 0x1);\
}
#define QL_DISABLE_INTERRUPTS(ha, sds_index) \
{\
q80_rsp_sds_ring_t *rsp_sds;\
rsp_sds = &((ha->hw.rx_cntxt_rsp)->sds_rsp[sds_index]);\
WRITE_REG32(ha, (rsp_sds->intr_mask_reg + 0x1b2000), 0x0);\
}
#define QL_BUFFER_ALIGN 16
#endif /* #ifndef _QLA_HW_H_ */

229
sys/dev/qlxgb/qla_inline.h Normal file
View File

@ -0,0 +1,229 @@
/*
* Copyright (c) 2010-2011 Qlogic 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 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.
*
* $FreeBSD$
*/
/*
* File: qla_inline.h
* Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
*/
#ifndef _QLA_INLINE_H_
#define _QLA_INLINE_H_
/*
* Function: qla_hw_reset
*/
static __inline void qla_hw_reset(qla_host_t *ha)
{
WRITE_OFFSET32(ha, Q8_ASIC_RESET, 0xFFFFFFFF);
}
#define QL8_SEMLOCK_TIMEOUT 1000/* QLA8020 Semaphore Lock Timeout 10ms */
/*
* Inline functions for hardware semaphores
*/
/*
* Name: qla_sem_lock
* Function: Locks one of the semaphore registers (semaphore 2,3,5 & 7)
* If the id_reg is valid, then id_val is written into it.
* This is for debugging purpose
* Returns: 0 on success; otherwise its failed.
*/
static __inline int
qla_sem_lock(qla_host_t *ha, uint32_t sem_reg, uint32_t id_reg, uint32_t id_val)
{
int count = QL8_SEMLOCK_TIMEOUT;
while (count) {
if ((READ_REG32(ha, sem_reg) & SEM_LOCK_BIT))
break;
count--;
if (!count)
return(-1);
qla_mdelay(__func__, 10);
}
if (id_reg)
WRITE_OFFSET32(ha, id_reg, id_val);
return(0);
}
/*
* Name: qla_sem_unlock
* Function: Unlocks the semaphore registers (semaphore 2,3,5 & 7)
* previously locked by qla_sem_lock()
*/
static __inline void
qla_sem_unlock(qla_host_t *ha, uint32_t sem_reg)
{
READ_REG32(ha, sem_reg);
}
static __inline int
qla_get_ifq_snd_maxlen(qla_host_t *ha)
{
return((NUM_TX_DESCRIPTORS - 1));
}
static __inline uint32_t
qla_get_optics(qla_host_t *ha)
{
uint32_t link_speed;
link_speed = READ_REG32(ha, Q8_LINK_SPEED_0);
if (ha->pci_func == 0)
link_speed = link_speed & 0xFF;
else
link_speed = (link_speed >> 8) & 0xFF;
switch (link_speed) {
case 0x1:
link_speed = IFM_100_FX;
break;
case 0x10:
link_speed = IFM_1000_SX;
break;
default:
link_speed = (IFM_10G_LR | IFM_10G_SR);
break;
}
return(link_speed);
}
static __inline uint8_t *
qla_get_mac_addr(qla_host_t *ha)
{
return (ha->hw.mac_addr);
}
static __inline void
qla_read_mac_addr(qla_host_t *ha)
{
uint32_t mac_crb_addr;
uint32_t mac_lo;
uint32_t mac_hi;
uint8_t *macp;
mac_crb_addr = Q8_CRB_MAC_BLOCK_START +
(((ha->pci_func >> 1) * 3) << 2) + ((ha->pci_func & 0x01) << 2);
mac_lo = READ_REG32(ha, mac_crb_addr);
mac_hi = READ_REG32(ha, (mac_crb_addr + 0x4));
if (ha->pci_func & 0x01) {
mac_lo = mac_lo >> 16;
macp = (uint8_t *)&mac_lo;
ha->hw.mac_addr[5] = macp[0];
ha->hw.mac_addr[4] = macp[1];
macp = (uint8_t *)&mac_hi;
ha->hw.mac_addr[3] = macp[0];
ha->hw.mac_addr[2] = macp[1];
ha->hw.mac_addr[1] = macp[2];
ha->hw.mac_addr[0] = macp[3];
} else {
macp = (uint8_t *)&mac_lo;
ha->hw.mac_addr[5] = macp[0];
ha->hw.mac_addr[4] = macp[1];
ha->hw.mac_addr[3] = macp[2];
ha->hw.mac_addr[2] = macp[3];
macp = (uint8_t *)&mac_hi;
ha->hw.mac_addr[1] = macp[0];
ha->hw.mac_addr[0] = macp[1];
}
return;
}
static __inline void
qla_set_hw_rcv_desc(qla_host_t *ha, uint32_t ridx, uint32_t index,
uint32_t handle, bus_addr_t paddr, uint32_t buf_size)
{
q80_recv_desc_t *rcv_desc;
rcv_desc = (q80_recv_desc_t *)ha->hw.dma_buf.rds_ring[ridx].dma_b;
rcv_desc += index;
rcv_desc->handle = (uint16_t)handle;
rcv_desc->buf_size = buf_size;
rcv_desc->buf_addr = paddr;
return;
}
static __inline void
qla_init_hw_rcv_descriptors(qla_host_t *ha, uint32_t ridx)
{
if (ridx == RDS_RING_INDEX_NORMAL)
bzero((void *)ha->hw.dma_buf.rds_ring[ridx].dma_b,
(sizeof(q80_recv_desc_t) * NUM_RX_DESCRIPTORS));
else if (ridx == RDS_RING_INDEX_JUMBO)
bzero((void *)ha->hw.dma_buf.rds_ring[ridx].dma_b,
(sizeof(q80_recv_desc_t) * NUM_RX_JUMBO_DESCRIPTORS));
else
QL_ASSERT(0, ("%s: invalid rds index [%d]\n", __func__, ridx));
}
static __inline void
qla_lock(qla_host_t *ha, const char *str)
{
while (1) {
mtx_lock(&ha->hw_lock);
if (!ha->hw_lock_held) {
ha->hw_lock_held = 1;
ha->qla_lock = str;
mtx_unlock(&ha->hw_lock);
break;
}
mtx_unlock(&ha->hw_lock);
qla_mdelay(__func__, 1);
}
return;
}
static __inline void
qla_unlock(qla_host_t *ha, const char *str)
{
mtx_lock(&ha->hw_lock);
ha->hw_lock_held = 0;
ha->qla_unlock = str;
mtx_unlock(&ha->hw_lock);
}
#endif /* #ifndef _QLA_INLINE_H_ */

119
sys/dev/qlxgb/qla_ioctl.c Normal file
View File

@ -0,0 +1,119 @@
/*
* Copyright (c) 2010-2011 Qlogic 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 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.
*/
/*
* File: qla_ioctl.c
* Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "qla_os.h"
#include "qla_reg.h"
#include "qla_hw.h"
#include "qla_def.h"
#include "qla_reg.h"
#include "qla_inline.h"
#include "qla_glbl.h"
#include "qla_ioctl.h"
static struct cdevsw qla_cdevsw = {
.d_version = D_VERSION,
.d_ioctl = qla_eioctl,
.d_name = "qlcnic",
};
int
qla_make_cdev(qla_host_t *ha)
{
ha->ioctl_dev = make_dev(&qla_cdevsw,
ha->ifp->if_dunit,
UID_ROOT,
GID_WHEEL,
0600,
"%s",
if_name(ha->ifp));
if (ha->ioctl_dev == NULL)
return (-1);
ha->ioctl_dev->si_drv1 = ha;
return (0);
}
void
qla_del_cdev(qla_host_t *ha)
{
if (ha->ioctl_dev != NULL)
destroy_dev(ha->ioctl_dev);
return;
}
int
qla_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
struct thread *td)
{
qla_host_t *ha;
int rval = 0;
qla_reg_val_t *rv;
qla_rd_flash_t *rdf;
if ((ha = (qla_host_t *)dev->si_drv1) == NULL)
return ENXIO;
switch(cmd) {
case QLA_RDWR_REG:
rv = (qla_reg_val_t *)data;
if (rv->direct) {
if (rv->rd) {
rv->val = READ_OFFSET32(ha, rv->reg);
} else {
WRITE_OFFSET32(ha, rv->reg, rv->val);
}
} else {
if ((rval = qla_rdwr_indreg32(ha, rv->reg, &rv->val,
rv->rd)))
rval = ENXIO;
}
break;
case QLA_RD_FLASH:
rdf = (qla_rd_flash_t *)data;
if ((rval = qla_rd_flash32(ha, rdf->off, &rdf->data)))
rval = ENXIO;
break;
default:
break;
}
return rval;
}

64
sys/dev/qlxgb/qla_ioctl.h Normal file
View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2010-2011 Qlogic 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 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.
*
* $FreeBSD$
*/
/*
* File: qla_ioctl.h
* Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
*/
#ifndef _QLA_IOCTL_H_
#define _QLA_IOCTL_H_
#include <sys/ioccom.h>
struct qla_reg_val {
uint16_t rd;
uint16_t direct;
uint32_t reg;
uint32_t val;
};
typedef struct qla_reg_val qla_reg_val_t;
struct qla_rd_flash {
uint32_t off;
uint32_t data;
};
typedef struct qla_rd_flash qla_rd_flash_t;
/*
* Read/Write Register
*/
#define QLA_RDWR_REG _IOWR('q', 1, qla_reg_val_t)
/*
* Read Flash
*/
#define QLA_RD_FLASH _IOWR('q', 2, qla_rd_flash_t)
#endif /* #ifndef _QLA_IOCTL_H_ */

416
sys/dev/qlxgb/qla_isr.c Normal file
View File

@ -0,0 +1,416 @@
/*
* Copyright (c) 2010-2011 Qlogic 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 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.
*/
/*
* File: qla_isr.c
* Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "qla_os.h"
#include "qla_reg.h"
#include "qla_hw.h"
#include "qla_def.h"
#include "qla_inline.h"
#include "qla_ver.h"
#include "qla_glbl.h"
#include "qla_dbg.h"
static void qla_replenish_normal_rx(qla_host_t *ha, qla_sds_t *sdsp);
static void qla_replenish_jumbo_rx(qla_host_t *ha, qla_sds_t *sdsp);
/*
* Name: qla_rx_intr
* Function: Handles normal ethernet frames received
*/
static void
qla_rx_intr(qla_host_t *ha, uint64_t data, uint32_t sds_idx,
struct lro_ctrl *lro)
{
uint32_t idx, length, status, ring;
qla_rx_buf_t *rxb;
struct mbuf *mp;
struct ifnet *ifp = ha->ifp;
qla_sds_t *sdsp;
struct ether_vlan_header *eh;
sdsp = &ha->hw.sds[sds_idx];
ring = (uint32_t)Q8_STAT_DESC_TYPE(data);
idx = (uint32_t)Q8_STAT_DESC_HANDLE(data);
length = (uint32_t)Q8_STAT_DESC_TOTAL_LENGTH(data);
status = (uint32_t)Q8_STAT_DESC_STATUS(data);
if (ring == 0) {
if ((idx >= NUM_RX_DESCRIPTORS) || (length > MCLBYTES)) {
device_printf(ha->pci_dev, "%s: ring[%d] index[0x%08x]"
" len[0x%08x] invalid\n",
__func__, ring, idx, length);
return;
}
} else {
if ((idx >= NUM_RX_JUMBO_DESCRIPTORS)||(length > MJUM9BYTES)) {
device_printf(ha->pci_dev, "%s: ring[%d] index[0x%08x]"
" len[0x%08x] invalid\n",
__func__, ring, idx, length);
return;
}
}
if (ring == 0)
rxb = &ha->rx_buf[idx];
else
rxb = &ha->rx_jbuf[idx];
QL_ASSERT((rxb != NULL),\
("%s: [r, i, sds_idx]=[%d, 0x%x, %d] rxb != NULL\n",\
__func__, ring, idx, sds_idx));
mp = rxb->m_head;
QL_ASSERT((mp != NULL),\
("%s: [r,i,rxb, sds_idx]=[%d, 0x%x, %p, %d] mp != NULL\n",\
__func__, ring, idx, rxb, sds_idx));
bus_dmamap_sync(ha->rx_tag, rxb->map, BUS_DMASYNC_POSTREAD);
if (ring == 0) {
rxb->m_head = NULL;
rxb->next = sdsp->rxb_free;
sdsp->rxb_free = rxb;
sdsp->rx_free++;
} else {
rxb->m_head = NULL;
rxb->next = sdsp->rxjb_free;
sdsp->rxjb_free = rxb;
sdsp->rxj_free++;
}
mp->m_len = length;
mp->m_pkthdr.len = length;
mp->m_pkthdr.rcvif = ifp;
eh = mtod(mp, struct ether_vlan_header *);
if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
uint32_t *data = (uint32_t *)eh;
mp->m_pkthdr.ether_vtag = ntohs(eh->evl_tag);
mp->m_flags |= M_VLANTAG;
*(data + 3) = *(data + 2);
*(data + 2) = *(data + 1);
*(data + 1) = *data;
m_adj(mp, ETHER_VLAN_ENCAP_LEN);
}
if (status == Q8_STAT_DESC_STATUS_CHKSUM_OK) {
mp->m_pkthdr.csum_flags = (CSUM_IP_CHECKED | CSUM_IP_VALID);
} else {
mp->m_pkthdr.csum_flags = 0;
}
if (lro->lro_cnt && (tcp_lro_rx(lro, mp, 0) == 0)) {
/* LRO packet has been successfuly queued */
} else {
(*ifp->if_input)(ifp, mp);
}
if (sdsp->rx_free > std_replenish)
qla_replenish_normal_rx(ha, sdsp);
if (sdsp->rxj_free > jumbo_replenish)
qla_replenish_jumbo_rx(ha, sdsp);
return;
}
static void
qla_replenish_jumbo_rx(qla_host_t *ha, qla_sds_t *sdsp)
{
qla_rx_buf_t *rxb;
int count = jumbo_replenish;
uint32_t rxj_next;
if (!mtx_trylock(&ha->rxj_lock))
return;
rxj_next = ha->hw.rxj_next;
while (count--) {
rxb = sdsp->rxjb_free;
if (rxb == NULL)
break;
sdsp->rxjb_free = rxb->next;
sdsp->rxj_free--;
if (qla_get_mbuf(ha, rxb, NULL, RDS_RING_INDEX_JUMBO) == 0) {
qla_set_hw_rcv_desc(ha, RDS_RING_INDEX_JUMBO,
ha->hw.rxj_in, rxb->handle, rxb->paddr,
(rxb->m_head)->m_pkthdr.len);
ha->hw.rxj_in++;
if (ha->hw.rxj_in == NUM_RX_JUMBO_DESCRIPTORS)
ha->hw.rxj_in = 0;
ha->hw.rxj_next++;
if (ha->hw.rxj_next == NUM_RX_JUMBO_DESCRIPTORS)
ha->hw.rxj_next = 0;
} else {
device_printf(ha->pci_dev,
"%s: qla_get_mbuf [1,(%d),(%d)] failed\n",
__func__, ha->hw.rxj_in, rxb->handle);
rxb->m_head = NULL;
rxb->next = sdsp->rxjb_free;
sdsp->rxjb_free = rxb;
sdsp->rxj_free++;
break;
}
}
if (rxj_next != ha->hw.rxj_next) {
QL_UPDATE_RDS_PRODUCER_INDEX(ha, 1, ha->hw.rxj_next);
}
mtx_unlock(&ha->rxj_lock);
}
static void
qla_replenish_normal_rx(qla_host_t *ha, qla_sds_t *sdsp)
{
qla_rx_buf_t *rxb;
int count = std_replenish;
uint32_t rx_next;
if (!mtx_trylock(&ha->rx_lock))
return;
rx_next = ha->hw.rx_next;
while (count--) {
rxb = sdsp->rxb_free;
if (rxb == NULL)
break;
sdsp->rxb_free = rxb->next;
sdsp->rx_free--;
if (qla_get_mbuf(ha, rxb, NULL, RDS_RING_INDEX_NORMAL) == 0) {
qla_set_hw_rcv_desc(ha, RDS_RING_INDEX_NORMAL,
ha->hw.rx_in, rxb->handle, rxb->paddr,
(rxb->m_head)->m_pkthdr.len);
ha->hw.rx_in++;
if (ha->hw.rx_in == NUM_RX_DESCRIPTORS)
ha->hw.rx_in = 0;
ha->hw.rx_next++;
if (ha->hw.rx_next == NUM_RX_DESCRIPTORS)
ha->hw.rx_next = 0;
} else {
device_printf(ha->pci_dev,
"%s: qla_get_mbuf [0,(%d),(%d)] failed\n",
__func__, ha->hw.rx_in, rxb->handle);
rxb->m_head = NULL;
rxb->next = sdsp->rxb_free;
sdsp->rxb_free = rxb;
sdsp->rx_free++;
break;
}
}
if (rx_next != ha->hw.rx_next) {
QL_UPDATE_RDS_PRODUCER_INDEX(ha, 0, ha->hw.rx_next);
}
mtx_unlock(&ha->rx_lock);
}
/*
* Name: qla_isr
* Function: Main Interrupt Service Routine
*/
static uint32_t
qla_rcv_isr(qla_host_t *ha, uint32_t sds_idx, uint32_t count)
{
device_t dev;
qla_hw_t *hw;
uint32_t comp_idx, desc_count;
q80_stat_desc_t *sdesc;
struct lro_ctrl *lro;
struct lro_entry *queued;
uint32_t ret = 0;
dev = ha->pci_dev;
hw = &ha->hw;
hw->sds[sds_idx].rcv_active = 1;
if (ha->flags.stop_rcv) {
hw->sds[sds_idx].rcv_active = 0;
return 0;
}
QL_DPRINT2((dev, "%s: [%d]enter\n", __func__, sds_idx));
/*
* receive interrupts
*/
comp_idx = hw->sds[sds_idx].sdsr_next;
lro = &hw->sds[sds_idx].lro;
while (count--) {
sdesc = (q80_stat_desc_t *)
&hw->sds[sds_idx].sds_ring_base[comp_idx];
if (Q8_STAT_DESC_OWNER((sdesc->data[0])) !=
Q8_STAT_DESC_OWNER_HOST) {
QL_DPRINT2((dev, "%s: data %p sdsr_next 0x%08x\n",
__func__, (void *)sdesc->data[0], comp_idx));
break;
}
desc_count = Q8_STAT_DESC_COUNT((sdesc->data[0]));
switch (Q8_STAT_DESC_OPCODE((sdesc->data[0]))) {
case Q8_STAT_DESC_OPCODE_RCV_PKT:
case Q8_STAT_DESC_OPCODE_SYN_OFFLOAD:
qla_rx_intr(ha, (sdesc->data[0]), sds_idx, lro);
break;
default:
device_printf(dev, "%s: default 0x%llx!\n", __func__,
(long long unsigned int)sdesc->data[0]);
break;
}
while (desc_count--) {
sdesc->data[0] =
Q8_STAT_DESC_SET_OWNER(Q8_STAT_DESC_OWNER_FW);
comp_idx = (comp_idx + 1) & (NUM_STATUS_DESCRIPTORS-1);
sdesc = (q80_stat_desc_t *)
&hw->sds[sds_idx].sds_ring_base[comp_idx];
}
}
while((!SLIST_EMPTY(&lro->lro_active))) {
queued = SLIST_FIRST(&lro->lro_active);
SLIST_REMOVE_HEAD(&lro->lro_active, next);
tcp_lro_flush(lro, queued);
}
if (hw->sds[sds_idx].sdsr_next != comp_idx) {
QL_UPDATE_SDS_CONSUMER_INDEX(ha, sds_idx, comp_idx);
}
hw->sds[sds_idx].sdsr_next = comp_idx;
sdesc = (q80_stat_desc_t *)&hw->sds[sds_idx].sds_ring_base[comp_idx];
if ((sds_idx == 0) && (Q8_STAT_DESC_OWNER((sdesc->data[0])) ==
Q8_STAT_DESC_OWNER_HOST)) {
ret = -1;
}
hw->sds[sds_idx].rcv_active = 0;
return (ret);
}
void
qla_isr(void *arg)
{
qla_ivec_t *ivec = arg;
qla_host_t *ha;
uint32_t sds_idx;
uint32_t ret;
ha = ivec->ha;
sds_idx = ivec->irq_rid - 1;
if (sds_idx >= ha->hw.num_sds_rings) {
device_printf(ha->pci_dev, "%s: bogus sds_idx 0x%x\n", __func__,
sds_idx);
return;
}
if (sds_idx == 0)
taskqueue_enqueue(ha->tx_tq, &ha->tx_task);
ret = qla_rcv_isr(ha, sds_idx, rcv_pkt_thres);
if (sds_idx == 0)
taskqueue_enqueue(ha->tx_tq, &ha->tx_task);
if (ret) {
taskqueue_enqueue(ha->irq_vec[sds_idx].rcv_tq,
&ha->irq_vec[sds_idx].rcv_task);
} else {
QL_ENABLE_INTERRUPTS(ha, sds_idx);
}
}
void
qla_rcv(void *context, int pending)
{
qla_ivec_t *ivec = context;
qla_host_t *ha;
device_t dev;
qla_hw_t *hw;
uint32_t sds_idx;
uint32_t ret;
struct ifnet *ifp;
ha = ivec->ha;
dev = ha->pci_dev;
hw = &ha->hw;
sds_idx = ivec->irq_rid - 1;
ifp = ha->ifp;
do {
if (sds_idx == 0) {
if (qla_le32_to_host(*(hw->tx_cons)) != hw->txr_comp) {
taskqueue_enqueue(ha->tx_tq, &ha->tx_task);
} else if ((ifp->if_snd.ifq_head != NULL) &&
QL_RUNNING(ifp)) {
taskqueue_enqueue(ha->tx_tq, &ha->tx_task);
}
}
ret = qla_rcv_isr(ha, sds_idx, rcv_pkt_thres_d);
} while (ret);
if (sds_idx == 0)
taskqueue_enqueue(ha->tx_tq, &ha->tx_task);
QL_ENABLE_INTERRUPTS(ha, sds_idx);
}

624
sys/dev/qlxgb/qla_misc.c Normal file
View File

@ -0,0 +1,624 @@
/*
* Copyright (c) 2010-2011 Qlogic 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 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.
*/
/*
* File : qla_misc.c
* Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "qla_os.h"
#include "qla_reg.h"
#include "qla_hw.h"
#include "qla_def.h"
#include "qla_reg.h"
#include "qla_inline.h"
#include "qla_glbl.h"
#include "qla_dbg.h"
/*
* structure encapsulating the value to read/write to offchip memory
*/
typedef struct _offchip_mem_val {
uint32_t data_lo;
uint32_t data_hi;
uint32_t data_ulo;
uint32_t data_uhi;
} offchip_mem_val_t;
#define Q8_ADDR_UNDEFINED 0xFFFFFFFF
/*
* The index to this table is Bits 20-27 of the indirect register address
*/
static uint32_t indirect_to_base_map[] =
{
Q8_ADDR_UNDEFINED, /* 0x00 */
0x77300000, /* 0x01 */
0x29500000, /* 0x02 */
0x2A500000, /* 0x03 */
Q8_ADDR_UNDEFINED, /* 0x04 */
0x0D000000, /* 0x05 */
0x1B100000, /* 0x06 */
0x0E600000, /* 0x07 */
0x0E000000, /* 0x08 */
0x0E100000, /* 0x09 */
0x0E200000, /* 0x0A */
0x0E300000, /* 0x0B */
0x42000000, /* 0x0C */
0x41700000, /* 0x0D */
0x42100000, /* 0x0E */
0x34B00000, /* 0x0F */
0x40500000, /* 0x10 */
0x34000000, /* 0x11 */
0x34100000, /* 0x12 */
0x34200000, /* 0x13 */
0x34300000, /* 0x14 */
0x34500000, /* 0x15 */
0x34400000, /* 0x16 */
0x3C000000, /* 0x17 */
0x3C100000, /* 0x18 */
0x3C200000, /* 0x19 */
0x3C300000, /* 0x1A */
Q8_ADDR_UNDEFINED, /* 0x1B */
0x3C400000, /* 0x1C */
0x41000000, /* 0x1D */
Q8_ADDR_UNDEFINED, /* 0x1E */
0x0D100000, /* 0x1F */
Q8_ADDR_UNDEFINED, /* 0x20 */
0x77300000, /* 0x21 */
0x41600000, /* 0x22 */
Q8_ADDR_UNDEFINED, /* 0x23 */
Q8_ADDR_UNDEFINED, /* 0x24 */
Q8_ADDR_UNDEFINED, /* 0x25 */
Q8_ADDR_UNDEFINED, /* 0x26 */
Q8_ADDR_UNDEFINED, /* 0x27 */
0x41700000, /* 0x28 */
Q8_ADDR_UNDEFINED, /* 0x29 */
0x08900000, /* 0x2A */
0x70A00000, /* 0x2B */
0x70B00000, /* 0x2C */
0x70C00000, /* 0x2D */
0x08D00000, /* 0x2E */
0x08E00000, /* 0x2F */
0x70F00000, /* 0x30 */
0x40500000, /* 0x31 */
0x42000000, /* 0x32 */
0x42100000, /* 0x33 */
Q8_ADDR_UNDEFINED, /* 0x34 */
0x08800000, /* 0x35 */
0x09100000, /* 0x36 */
0x71200000, /* 0x37 */
0x40600000, /* 0x38 */
Q8_ADDR_UNDEFINED, /* 0x39 */
0x71800000, /* 0x3A */
0x19900000, /* 0x3B */
0x1A900000, /* 0x3C */
Q8_ADDR_UNDEFINED, /* 0x3D */
0x34600000, /* 0x3E */
Q8_ADDR_UNDEFINED, /* 0x3F */
};
/*
* Address Translation Table for CRB to offsets from PCI BAR0
*/
typedef struct _crb_to_pci {
uint32_t crb_addr;
uint32_t pci_addr;
} crb_to_pci_t;
static crb_to_pci_t crbinit_to_pciaddr[] = {
{(0x088 << 20), (0x035 << 20)},
{(0x089 << 20), (0x02A << 20)},
{(0x08D << 20), (0x02E << 20)},
{(0x08E << 20), (0x02F << 20)},
{(0x0C6 << 20), (0x023 << 20)},
{(0x0C7 << 20), (0x024 << 20)},
{(0x0C8 << 20), (0x025 << 20)},
{(0x0D0 << 20), (0x005 << 20)},
{(0x0D1 << 20), (0x01F << 20)},
{(0x0E0 << 20), (0x008 << 20)},
{(0x0E1 << 20), (0x009 << 20)},
{(0x0E2 << 20), (0x00A << 20)},
{(0x0E3 << 20), (0x00B << 20)},
{(0x0E6 << 20), (0x007 << 20)},
{(0x199 << 20), (0x03B << 20)},
{(0x1B1 << 20), (0x006 << 20)},
{(0x295 << 20), (0x002 << 20)},
{(0x29A << 20), (0x000 << 20)},
{(0x2A5 << 20), (0x003 << 20)},
{(0x340 << 20), (0x011 << 20)},
{(0x341 << 20), (0x012 << 20)},
{(0x342 << 20), (0x013 << 20)},
{(0x343 << 20), (0x014 << 20)},
{(0x344 << 20), (0x016 << 20)},
{(0x345 << 20), (0x015 << 20)},
{(0x3C0 << 20), (0x017 << 20)},
{(0x3C1 << 20), (0x018 << 20)},
{(0x3C2 << 20), (0x019 << 20)},
{(0x3C3 << 20), (0x01A << 20)},
{(0x3C4 << 20), (0x01C << 20)},
{(0x3C5 << 20), (0x01B << 20)},
{(0x405 << 20), (0x031 << 20)},
{(0x406 << 20), (0x038 << 20)},
{(0x410 << 20), (0x01D << 20)},
{(0x416 << 20), (0x022 << 20)},
{(0x417 << 20), (0x028 << 20)},
{(0x420 << 20), (0x032 << 20)},
{(0x421 << 20), (0x033 << 20)},
{(0x700 << 20), (0x00C << 20)},
{(0x701 << 20), (0x00D << 20)},
{(0x702 << 20), (0x00E << 20)},
{(0x703 << 20), (0x00F << 20)},
{(0x704 << 20), (0x010 << 20)},
{(0x70A << 20), (0x02B << 20)},
{(0x70B << 20), (0x02C << 20)},
{(0x70C << 20), (0x02D << 20)},
{(0x70F << 20), (0x030 << 20)},
{(0x718 << 20), (0x03A << 20)},
{(0x758 << 20), (0x026 << 20)},
{(0x759 << 20), (0x027 << 20)},
{(0x773 << 20), (0x001 << 20)}
};
#define Q8_INVALID_ADDRESS (-1)
#define Q8_ADDR_MASK (0xFFF << 20)
typedef struct _addr_val {
uint32_t addr;
uint32_t value;
uint32_t pci_addr;
uint32_t ind_addr;
} addr_val_t;
/*
* Name: qla_rdwr_indreg32
* Function: Read/Write an Indirect Register
*/
int
qla_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val, uint32_t rd)
{
uint32_t offset;
int count = 100;
offset = (addr & 0xFFF00000) >> 20;
if (offset > 0x3F) {
device_printf(ha->pci_dev, "%s: invalid addr 0x%08x\n",
__func__, addr);
return -1;
}
offset = indirect_to_base_map[offset];
if (offset == Q8_ADDR_UNDEFINED) {
device_printf(ha->pci_dev, "%s: undefined map 0x%08x\n",
__func__, addr);
return -1;
}
offset = offset | (addr & 0x000F0000);
if (qla_sem_lock(ha, Q8_SEM7_LOCK, 0, 0)) {
device_printf(ha->pci_dev, "%s: SEM7_LOCK failed\n", __func__);
return (-1);
}
WRITE_OFFSET32(ha, Q8_CRB_WINDOW_2M, offset);
while (offset != (READ_OFFSET32(ha, Q8_CRB_WINDOW_2M))) {
count--;
if (!count) {
qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
return -1;
}
qla_mdelay(__func__, 1);
}
if (rd) {
*val = READ_OFFSET32(ha, ((addr & 0xFFFF) | 0x1E0000));
} else {
WRITE_OFFSET32(ha, ((addr & 0xFFFF) | 0x1E0000), *val);
}
qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
return 0;
}
/*
* Name: qla_rdwr_offchip_mem
* Function: Read/Write OffChip Memory
*/
static int
qla_rdwr_offchip_mem(qla_host_t *ha, uint64_t addr, offchip_mem_val_t *val,
uint32_t rd)
{
uint32_t count = 100;
uint32_t data;
WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_ADDR_LO, (uint32_t)addr);
WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_ADDR_HI, (uint32_t)(addr >> 32));
if (!rd) {
WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_LO, val->data_lo);
WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_HI, val->data_hi);
WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_ULO, val->data_ulo);
WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_UHI, val->data_uhi);
WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL, 0x07); /* Write */
} else {
WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL, 0x03); /* Read */
}
while (count--) {
data = READ_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL);
if (!(data & BIT_3)) {
if (rd) {
val->data_lo = READ_OFFSET32(ha, \
Q8_MIU_TEST_AGT_RDDATA_LO);
val->data_hi = READ_OFFSET32(ha, \
Q8_MIU_TEST_AGT_RDDATA_HI);
val->data_ulo = READ_OFFSET32(ha, \
Q8_MIU_TEST_AGT_RDDATA_ULO);
val->data_uhi = READ_OFFSET32(ha, \
Q8_MIU_TEST_AGT_RDDATA_UHI);
}
return 0;
} else
qla_mdelay(__func__, 1);
}
device_printf(ha->pci_dev, "%s: failed[0x%08x]\n", __func__, data);
return (-1);
}
/*
* Name: qla_rd_flash32
* Function: Read Flash Memory
*/
int
qla_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data)
{
uint32_t val;
uint32_t count = 100;
if (qla_sem_lock(ha, Q8_SEM2_LOCK, 0, 0)) {
device_printf(ha->pci_dev, "%s: SEM2_LOCK failed\n", __func__);
return (-1);
}
WRITE_OFFSET32(ha, Q8_ROM_LOCKID, 0xa5a5a5a5);
val = addr;
qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
val = 0;
qla_rdwr_indreg32(ha, Q8_ROM_DUMMY_BYTE_COUNT, &val, 0);
val = 3;
qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
QLA_USEC_DELAY(100);
val = ROM_OPCODE_FAST_RD;
qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
while (!((val = READ_OFFSET32(ha, Q8_ROM_STATUS)) & BIT_1)) {
count--;
if (!count) {
qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
return -1;
}
}
val = 0;
qla_rdwr_indreg32(ha, Q8_ROM_DUMMY_BYTE_COUNT, &val, 0);
qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
QLA_USEC_DELAY(100);
qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, data, 1);
qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
return 0;
}
/*
* Name: qla_int_to_pci_addr_map
* Function: Convert's Internal(CRB) Address to Indirect Address
*/
static uint32_t
qla_int_to_pci_addr_map(qla_host_t *ha, uint32_t int_addr)
{
uint32_t crb_to_pci_table_size, i;
uint32_t addr;
crb_to_pci_table_size = sizeof(crbinit_to_pciaddr)/sizeof(crb_to_pci_t);
addr = int_addr & Q8_ADDR_MASK;
for (i = 0; i < crb_to_pci_table_size; i++) {
if (crbinit_to_pciaddr[i].crb_addr == addr) {
addr = (int_addr & ~Q8_ADDR_MASK) |
crbinit_to_pciaddr[i].pci_addr;
return (addr);
}
}
return (Q8_INVALID_ADDRESS);
}
/*
* Name: qla_filter_pci_addr
* Function: Filter's out Indirect Addresses which are not writeable
*/
static uint32_t
qla_filter_pci_addr(qla_host_t *ha, uint32_t addr)
{
if ((addr == Q8_INVALID_ADDRESS) ||
(addr == 0x00112040) ||
(addr == 0x00112048) ||
((addr & 0xFFFF0FFF) == 0x001100C4) ||
((addr & 0xFFFF0FFF) == 0x001100C8) ||
((addr & 0x0FF00000) == 0x00200000) ||
(addr == 0x022021FC) ||
(addr == 0x0330001C) ||
(addr == 0x03300024) ||
(addr == 0x033000A8) ||
(addr == 0x033000C8) ||
(addr == 0x033000BC) ||
((addr & 0x0FF00000) == 0x03A00000) ||
(addr == 0x03B0001C))
return (Q8_INVALID_ADDRESS);
else
return (addr);
}
/*
* Name: qla_crb_init
* Function: CRB Initialization - first step in the initialization after reset
* Essentially reads the address/value pairs from address = 0x00 and
* writes the value into address in the addr/value pair.
*/
static int
qla_crb_init(qla_host_t *ha)
{
uint32_t val, sig;
uint32_t offset, count, i;
addr_val_t *addr_val_map, *avmap;
qla_rd_flash32(ha, 0, &sig);
QL_DPRINT2((ha->pci_dev, "%s: val[0] = 0x%08x\n", __func__, val));
qla_rd_flash32(ha, 4, &val);
QL_DPRINT2((ha->pci_dev, "%s: val[4] = 0x%08x\n", __func__, val));
count = val >> 16;
offset = val & 0xFFFF;
offset = offset << 2;
QL_DPRINT2((ha->pci_dev, "%s: [sig,val]=[0x%08x, 0x%08x] %d pairs\n",
__func__, sig, val, count));
addr_val_map = avmap = malloc((sizeof(addr_val_t) * count),
M_QLA8XXXBUF, M_NOWAIT);
if (addr_val_map == NULL) {
device_printf(ha->pci_dev, "%s: malloc failed\n", __func__);
return (-1);
}
memset(avmap, 0, (sizeof(addr_val_t) * count));
count = count << 1;
for (i = 0; i < count; ) {
qla_rd_flash32(ha, (offset + (i * 4)), &avmap->value);
i++;
qla_rd_flash32(ha, (offset + (i * 4)), &avmap->addr);
i++;
avmap->pci_addr = qla_int_to_pci_addr_map(ha, avmap->addr);
avmap->ind_addr = qla_filter_pci_addr(ha, avmap->pci_addr);
QL_DPRINT2((ha->pci_dev,
"%s: [0x%02x][0x%08x:0x%08x:0x%08x] 0x%08x\n",
__func__, (i >> 1), avmap->addr, avmap->pci_addr,
avmap->ind_addr, avmap->value));
if (avmap->ind_addr != Q8_INVALID_ADDRESS) {
qla_rdwr_indreg32(ha, avmap->ind_addr, &avmap->value,0);
qla_mdelay(__func__, 1);
}
avmap++;
}
free (addr_val_map, M_QLA8XXXBUF);
return (0);
}
/*
* Name: qla_init_peg_regs
* Function: Protocol Engine Register Initialization
*/
static void
qla_init_peg_regs(qla_host_t *ha)
{
WRITE_OFFSET32(ha, Q8_PEG_D_RESET1, 0x001E);
WRITE_OFFSET32(ha, Q8_PEG_D_RESET2, 0x0008);
WRITE_OFFSET32(ha, Q8_PEG_I_RESET, 0x0008);
WRITE_OFFSET32(ha, Q8_PEG_0_CLR1, 0x0000);
WRITE_OFFSET32(ha, Q8_PEG_0_CLR2, 0x0000);
WRITE_OFFSET32(ha, Q8_PEG_1_CLR1, 0x0000);
WRITE_OFFSET32(ha, Q8_PEG_1_CLR2, 0x0000);
WRITE_OFFSET32(ha, Q8_PEG_2_CLR1, 0x0000);
WRITE_OFFSET32(ha, Q8_PEG_2_CLR2, 0x0000);
WRITE_OFFSET32(ha, Q8_PEG_3_CLR1, 0x0000);
WRITE_OFFSET32(ha, Q8_PEG_3_CLR2, 0x0000);
WRITE_OFFSET32(ha, Q8_PEG_4_CLR1, 0x0000);
WRITE_OFFSET32(ha, Q8_PEG_4_CLR2, 0x0000);
}
/*
* Name: qla_load_fw_from_flash
* Function: Reads the Bootloader from Flash and Loads into Offchip Memory
*/
static void
qla_load_fw_from_flash(qla_host_t *ha)
{
uint64_t mem_off = 0x10000;
uint32_t flash_off = 0x10000;
uint32_t count;
offchip_mem_val_t val;
/* only bootloader needs to be loaded into memory */
for (count = 0; count < 0x20000 ; ) {
qla_rd_flash32(ha, flash_off, &val.data_lo);
count = count + 4;
flash_off = flash_off + 4;
qla_rd_flash32(ha, flash_off, &val.data_hi);
count = count + 4;
flash_off = flash_off + 4;
qla_rd_flash32(ha, flash_off, &val.data_ulo);
count = count + 4;
flash_off = flash_off + 4;
qla_rd_flash32(ha, flash_off, &val.data_uhi);
count = count + 4;
flash_off = flash_off + 4;
qla_rdwr_offchip_mem(ha, mem_off, &val, 0);
mem_off = mem_off + 16;
}
return;
}
/*
* Name: qla_init_from_flash
* Function: Performs Initialization which consists of the following sequence
* - reset
* - CRB Init
* - Peg Init
* - Read the Bootloader from Flash and Load into Offchip Memory
* - Kick start the bootloader which loads the rest of the firmware
* and performs the remaining steps in the initialization process.
*/
static int
qla_init_from_flash(qla_host_t *ha)
{
uint32_t delay = 300;
uint32_t data;
qla_hw_reset(ha);
qla_mdelay(__func__, 100);
qla_crb_init(ha);
qla_mdelay(__func__, 10);
qla_init_peg_regs(ha);
qla_mdelay(__func__, 10);
qla_load_fw_from_flash(ha);
WRITE_OFFSET32(ha, Q8_CMDPEG_STATE, 0x00000000);
WRITE_OFFSET32(ha, Q8_PEG_0_RESET, 0x00001020);
WRITE_OFFSET32(ha, Q8_ASIC_RESET, 0x0080001E);
qla_mdelay(__func__, 100);
do {
data = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
QL_DPRINT2((ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n",
__func__, ha->pci_func, data));
if (data == CMDPEG_PHAN_INIT_COMPLETE) {
QL_DPRINT2((ha->pci_dev,
"%s: func[%d] init complete\n",
__func__, ha->pci_func));
return(0);
}
qla_mdelay(__func__, 100);
} while (delay--);
device_printf(ha->pci_dev,
"%s: func[%d] Q8_PEG_HALT_STATUS1[0x%08x] STATUS2[0x%08x]"
" HEARTBEAT[0x%08x] RCVPEG_STATE[0x%08x]"
" CMDPEG_STATE[0x%08x]\n",
__func__, ha->pci_func,
(READ_OFFSET32(ha, Q8_PEG_HALT_STATUS1)),
(READ_OFFSET32(ha, Q8_PEG_HALT_STATUS2)),
(READ_OFFSET32(ha, Q8_FIRMWARE_HEARTBEAT)),
(READ_OFFSET32(ha, Q8_RCVPEG_STATE)), data);
return (-1);
}
/*
* Name: qla_init_hw
* Function: Initializes P3+ hardware.
*/
int
qla_init_hw(qla_host_t *ha)
{
device_t dev;
int ret = 0;
uint32_t val, delay = 300;
dev = ha->pci_dev;
QL_DPRINT1((dev, "%s: enter\n", __func__));
qla_mdelay(__func__, 100);
if (ha->pci_func & 0x1) {
while ((ha->pci_func & 0x1) && delay--) {
val = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
if (val == CMDPEG_PHAN_INIT_COMPLETE) {
QL_DPRINT2((dev,
"%s: func = %d init complete\n",
__func__, ha->pci_func));
qla_mdelay(__func__, 100);
goto qla_init_exit;
}
qla_mdelay(__func__, 100);
}
return (-1);
}
val = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
if (val != CMDPEG_PHAN_INIT_COMPLETE) {
ret = qla_init_from_flash(ha);
qla_mdelay(__func__, 100);
}
qla_init_exit:
ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR);
ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR);
ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB);
ha->fw_ver_build = READ_OFFSET32(ha, Q8_FW_VER_BUILD);
return (ret);
}

1481
sys/dev/qlxgb/qla_os.c Normal file

File diff suppressed because it is too large Load Diff

176
sys/dev/qlxgb/qla_os.h Normal file
View File

@ -0,0 +1,176 @@
/*
* Copyright (c) 2010-2011 Qlogic 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 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.
*
* $FreeBSD$
*/
/*
* File: qla_os.h
* Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
*/
#ifndef _QLA_OS_H_
#define _QLA_OS_H_
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/sockio.h>
#include <sys/types.h>
#include <machine/atomic.h>
#include <sys/conf.h>
#if __FreeBSD_version < 700112
#error FreeBSD Version not supported - use version >= 700112
#endif
#include <net/if.h>
#include <net/if_arp.h>
#include <net/ethernet.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <net/bpf.h>
#include <net/if_types.h>
#include <net/if_vlan_var.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/in_var.h>
#include <netinet/tcp_lro.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/endian.h>
#include <sys/taskqueue.h>
#include <sys/pcpu.h>
#include <sys/unistd.h>
#include <sys/kthread.h>
#define QLA_USEC_DELAY(usec) DELAY(usec)
static __inline int qla_ms_to_hz(int ms)
{
int qla_hz;
struct timeval t;
t.tv_sec = ms / 1000;
t.tv_usec = (ms % 1000) * 1000;
qla_hz = tvtohz(&t);
if (qla_hz < 0)
qla_hz = 0x7fffffff;
if (!qla_hz)
qla_hz = 1;
return (qla_hz);
}
static __inline int qla_sec_to_hz(int sec)
{
struct timeval t;
t.tv_sec = sec;
t.tv_usec = 0;
return (tvtohz(&t));
}
#define qla_host_to_le16(x) htole16(x)
#define qla_host_to_le32(x) htole32(x)
#define qla_host_to_le64(x) htole64(x)
#define qla_host_to_be16(x) htobe16(x)
#define qla_host_to_be32(x) htobe32(x)
#define qla_host_to_be64(x) htobe64(x)
#define qla_le16_to_host(x) le16toh(x)
#define qla_le32_to_host(x) le32toh(x)
#define qla_le64_to_host(x) le64toh(x)
#define qla_be16_to_host(x) be16toh(x)
#define qla_be32_to_host(x) be32toh(x)
#define qla_be64_to_host(x) be64toh(x)
MALLOC_DECLARE(M_QLA8XXXBUF);
#define qla_mdelay(fn, msecs) \
{\
if (cold) \
DELAY((msecs * 1000)); \
else \
pause(fn, qla_ms_to_hz(msecs)); \
}
/*
* Locks
*/
#define QLA_LOCK(ha, str) qla_lock(ha, str);
#define QLA_UNLOCK(ha, str) qla_unlock(ha, str)
#define QLA_TX_LOCK(ha) mtx_lock(&ha->tx_lock);
#define QLA_TX_UNLOCK(ha) mtx_unlock(&ha->tx_lock);
#define QLA_RX_LOCK(ha) mtx_lock(&ha->rx_lock);
#define QLA_RX_UNLOCK(ha) mtx_unlock(&ha->rx_lock);
#define QLA_RXJ_LOCK(ha) mtx_lock(&ha->rxj_lock);
#define QLA_RXJ_UNLOCK(ha) mtx_unlock(&ha->rxj_lock);
/*
* structure encapsulating a DMA buffer
*/
struct qla_dma {
bus_size_t alignment;
uint32_t size;
void *dma_b;
bus_addr_t dma_addr;
bus_dmamap_t dma_map;
bus_dma_tag_t dma_tag;
};
typedef struct qla_dma qla_dma_t;
#define QL_ASSERT(x, y) if (!x) panic y
#endif /* #ifndef _QLA_OS_H_ */

248
sys/dev/qlxgb/qla_reg.h Normal file
View File

@ -0,0 +1,248 @@
/*
* Copyright (c) 2010-2011 Qlogic 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 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.
*
* $FreeBSD$
*/
/*
* File: qla_reg.h
* Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
*/
#ifndef _QLA_REG_H_
#define _QLA_REG_H_
/*
* Begin Definitions for QLA82xx Registers
*/
/*
* Register offsets for QLA8022
*/
/******************************
* PCIe Registers
******************************/
#define Q8_CRB_WINDOW_2M 0x130060
#define Q8_INT_VECTOR 0x130100
#define Q8_INT_MASK 0x130104
#define Q8_INT_TARGET_STATUS_F0 0x130118
#define Q8_INT_TARGET_MASK_F0 0x130128
#define Q8_INT_TARGET_STATUS_F1 0x130160
#define Q8_INT_TARGET_MASK_F1 0x130170
#define Q8_INT_TARGET_STATUS_F2 0x130164
#define Q8_INT_TARGET_MASK_F2 0x130174
#define Q8_INT_TARGET_STATUS_F3 0x130168
#define Q8_INT_TARGET_MASK_F3 0x130178
#define Q8_INT_TARGET_STATUS_F4 0x130360
#define Q8_INT_TARGET_MASK_F4 0x130370
#define Q8_INT_TARGET_STATUS_F5 0x130364
#define Q8_INT_TARGET_MASK_F5 0x130374
#define Q8_INT_TARGET_STATUS_F6 0x130368
#define Q8_INT_TARGET_MASK_F6 0x130378
#define Q8_INT_TARGET_STATUS_F7 0x13036C
#define Q8_INT_TARGET_MASK_F7 0x13037C
#define Q8_SEM2_LOCK 0x13C010
#define Q8_SEM2_UNLOCK 0x13C014
#define Q8_SEM3_LOCK 0x13C018
#define Q8_SEM3_UNLOCK 0x13C01C
#define Q8_SEM5_LOCK 0x13C028
#define Q8_SEM5_UNLOCK 0x13C02C
#define Q8_SEM7_LOCK 0x13C038
#define Q8_SEM7_UNLOCK 0x13C03C
/* Valid bit for a SEM<N>_LOCK registers */
#define SEM_LOCK_BIT 0x00000001
#define Q8_ROM_LOCKID 0x1B2100
/*******************************
* Firmware Interface Registers
*******************************/
#define Q8_FW_VER_MAJOR 0x1B2150
#define Q8_FW_VER_MINOR 0x1B2154
#define Q8_FW_VER_SUB 0x1B2158
#define Q8_FW_VER_BUILD 0x1B2168
#define Q8_CMDPEG_STATE 0x1B2250
#define Q8_RCVPEG_STATE 0x1B233C
/*
* definitions for Q8_CMDPEG_STATE
*/
#define CMDPEG_PHAN_INIT_COMPLETE 0xFF01
#define Q8_ROM_STATUS 0x1A0004
/*
* definitions for Q8_ROM_STATUS
* bit definitions for Q8_UNM_ROMUSB_GLB_STATUS
* 31:3 Reserved; Rest as below
*/
#define ROM_STATUS_RDY 0x0004
#define ROM_STATUS_DONE 0x0002
#define ROM_STATUS_AUTO_ROM_SHDW 0x0001
#define Q8_ASIC_RESET 0x1A0008
/*
* definitions for Q8_ASIC_RESET
*/
#define ASIC_RESET_RST_XDMA 0x00800000 /* Reset XDMA */
#define ASIC_RESET_PEG_ICACHE 0x00000020 /* Reset PEG_ICACHE */
#define ASIC_RESET_PEG_DCACHE 0x00000010 /* Reset PEG_DCACHE */
#define ASIC_RESET_PEG_3 0x00000008 /* Reset PEG_3 */
#define ASIC_RESET_PEG_2 0x00000004 /* Reset PEG_2 */
#define ASIC_RESET_PEG_1 0x00000002 /* Reset PEG_1 */
#define ASIC_RESET_PEG_0 0x00000001 /* Reset PEG_0 */
#define Q8_COLD_BOOT 0x1B21FC
/*
* definitions for Q8_COLD_BOOT
*/
#define COLD_BOOT_VALUE 0x12345678
#define Q8_MIU_TEST_AGT_CTRL 0x180090
#define Q8_MIU_TEST_AGT_ADDR_LO 0x180094
#define Q8_MIU_TEST_AGT_ADDR_HI 0x180098
#define Q8_MIU_TEST_AGT_WRDATA_LO 0x1800A0
#define Q8_MIU_TEST_AGT_WRDATA_HI 0x1800A4
#define Q8_MIU_TEST_AGT_RDDATA_LO 0x1800A8
#define Q8_MIU_TEST_AGT_RDDATA_HI 0x1800AC
#define Q8_MIU_TEST_AGT_WRDATA_ULO 0x1800B0
#define Q8_MIU_TEST_AGT_WRDATA_UHI 0x1800B4
#define Q8_MIU_TEST_AGT_RDDATA_ULO 0x1800B8
#define Q8_MIU_TEST_AGT_RDDATA_UHI 0x1800BC
#define Q8_PEG_0_RESET 0x160018
#define Q8_PEG_0_CLR1 0x160008
#define Q8_PEG_0_CLR2 0x16000C
#define Q8_PEG_1_CLR1 0x161008
#define Q8_PEG_1_CLR2 0x16100C
#define Q8_PEG_2_CLR1 0x162008
#define Q8_PEG_2_CLR2 0x16200C
#define Q8_PEG_3_CLR1 0x163008
#define Q8_PEG_3_CLR2 0x16300C
#define Q8_PEG_4_CLR1 0x164008
#define Q8_PEG_4_CLR2 0x16400C
#define Q8_PEG_D_RESET1 0x1650EC
#define Q8_PEG_D_RESET2 0x16504C
#define Q8_PEG_HALT_STATUS1 0x1B20A8
#define Q8_PEG_HALT_STATUS2 0x1B20AC
#define Q8_FIRMWARE_HEARTBEAT 0x1B20B0
#define Q8_PEG_I_RESET 0x16604C
#define Q8_CRB_MAC_BLOCK_START 0x1B21C0
/***************************************************
* Flash ROM Access Registers ( Indirect Registers )
***************************************************/
#define Q8_ROM_INSTR_OPCODE 0x03310004
/*
* bit definitions for Q8_ROM_INSTR_OPCODE
* 31:8 Reserved; Rest Below
*/
#define ROM_OPCODE_WR_STATUS_REG 0x01
#define ROM_OPCODE_PROG_PAGE 0x02
#define ROM_OPCODE_RD_BYTE 0x03
#define ROM_OPCODE_WR_DISABLE 0x04
#define ROM_OPCODE_RD_STATUS_REG 0x05
#define ROM_OPCODE_WR_ENABLE 0x06
#define ROM_OPCODE_FAST_RD 0x0B
#define ROM_OPCODE_REL_DEEP_PWR_DWN 0xAB
#define ROM_OPCODE_BULK_ERASE 0xC7
#define ROM_OPCODE_DEEP_PWR_DWN 0xC9
#define ROM_OPCODE_SECTOR_ERASE 0xD8
#define Q8_ROM_ADDRESS 0x03310008
/*
* bit definitions for Q8_ROM_ADDRESS
* 31:24 Reserved;
* 23:0 Physical ROM Address in bytes
*/
#define Q8_ROM_ADDR_BYTE_COUNT 0x03310010
/*
* bit definitions for Q8_ROM_ADDR_BYTE_COUNT
* 31:2 Reserved;
* 1:0 max address bytes for ROM Interface
*/
#define Q8_ROM_DUMMY_BYTE_COUNT 0x03310014
/*
* bit definitions for Q8_ROM_DUMMY_BYTE_COUNT
* 31:2 Reserved;
* 1:0 dummy bytes for ROM Instructions
*/
#define Q8_ROM_RD_DATA 0x03310018
#define Q8_NX_CDRP_CMD_RSP 0x1B2218
#define Q8_NX_CDRP_ARG1 0x1B221C
#define Q8_NX_CDRP_ARG2 0x1B2220
#define Q8_NX_CDRP_ARG3 0x1B2224
#define Q8_NX_CDRP_SIGNATURE 0x1B2228
#define Q8_LINK_STATE 0x1B2298
#define Q8_LINK_SPEED_0 0x1B22E8
/*
* Macros for reading and writing registers
*/
#if defined(__i386__) || defined(__amd64__)
#define Q8_MB() __asm volatile("mfence" ::: "memory")
#define Q8_WMB() __asm volatile("sfence" ::: "memory")
#define Q8_RMB() __asm volatile("lfence" ::: "memory")
#else
#define Q8_MB()
#define Q8_WMB()
#define Q8_RMB()
#endif
#define READ_REG32(ha, reg) bus_read_4((ha->pci_reg), reg)
#define READ_OFFSET32(ha, off) READ_REG32(ha, off)
#define WRITE_REG32(ha, reg, val) \
{\
bus_write_4((ha->pci_reg), reg, val);\
bus_read_4((ha->pci_reg), reg);\
}
#define WRITE_REG32_MB(ha, reg, val) \
{\
Q8_WMB();\
bus_write_4((ha->pci_reg), reg, val);\
}
#define WRITE_OFFSET32(ha, off, val)\
{\
bus_write_4((ha->pci_reg), off, val);\
bus_read_4((ha->pci_reg), off);\
}
#endif /* #ifndef _QLA_REG_H_ */

41
sys/dev/qlxgb/qla_ver.h Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2010-2011 Qlogic 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 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.
*
* $FreeBSD$
*/
/*
* File: qla_ver.h
* Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
*/
#ifndef _QLA_VER_H_
#define _QLA_VER_H_
#define QLA_VERSION_MAJOR 1
#define QLA_VERSION_MINOR 1
#define QLA_VERSION_BUILD 30
#endif /* #ifndef _QLA_VER_H_ */

View File

@ -255,6 +255,7 @@ SUBDIR= ${_3dfx} \
${_pst} \
pty \
puc \
${_qlxgb} \
ral \
ralfw \
${_random} \
@ -617,6 +618,7 @@ _opensolaris= opensolaris
_padlock= padlock
.endif
_pccard= pccard
_qlxgb= qlxgb
_rdma= rdma
_s3= s3
_safe= safe

View File

@ -0,0 +1,43 @@
#-
# Copyright (c) 2010-2011 Qlogic 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 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.
#
# File : Makefile
# Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
#
# $FreeBSD$
#
.PATH: ${.CURDIR}/../../dev/qlxgb
KMOD= if_qlxgb
SRCS= qla_os.c qla_dbg.c qla_hw.c qla_misc.c qla_isr.c qla_ioctl.c
SRCS+= device_if.h bus_if.h pci_if.h
clean:
rm -f opt_bdg.h device_if.h bus_if.h pci_if.h export_syms
rm -f *.o *.kld *.ko
rm -f @ machine
.include <bsd.kmod.mk>