unm_gem.c revision de710d24d2fae4468e64da999e1d952a247f142c
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 NetXen, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/ethernet.h>
#include <sys/dditypes.h>
#include <sys/sysmacros.h>
#include <sys/ddi_intr.h>
#include "unm_nic.h"
#include "unm_nic_hw.h"
#include "unm_brdcfg.h"
#include "nic_cmn.h"
#include "nic_phan_reg.h"
#include "unm_nic_ioctl.h"
#include "nx_hw_pci_regs.h"
char ident[] = "Netxen nic driver v" UNM_NIC_VERSIONID;
char unm_nic_driver_name[] = "ntxn";
int verbmsg = 0;
static char txbcopythreshold_propname[] = "tx_bcopy_threshold";
static char rxbcopythreshold_propname[] = "rx_bcopy_threshold";
static char rxringsize_propname[] = "rx_ring_size";
static char jumborxringsize_propname[] = "jumbo_rx_ring_size";
static char txringsize_propname[] = "tx_ring_size";
static char defaultmtu_propname[] = "default_mtu";
static char dmesg_propname[] = "verbose_driver";
#define STRUCT_COPY(a, b) bcopy(&(b), &(a), sizeof (a))
extern int unm_nic_suspend(unm_adapter *);
/* Data access requirements. */
static struct ddi_device_acc_attr unm_dev_attr = {
};
static struct ddi_device_acc_attr unm_buf_attr = {
};
static ddi_dma_attr_t unm_dma_attr_desc = {
DMA_ATTR_V0, /* dma_attr_version */
0, /* dma_attr_addr_lo */
0xffffffffull, /* dma_attr_addr_hi */
0x000fffffull, /* dma_attr_count_max */
4096, /* dma_attr_align */
0x000fffffull, /* dma_attr_burstsizes */
4, /* dma_attr_minxfer */
0x003fffffull, /* dma_attr_maxxfer */
0xffffffffull, /* dma_attr_seg */
1, /* dma_attr_sgllen */
1, /* dma_attr_granular */
0 /* dma_attr_flags */
};
static ddi_dma_attr_t unm_dma_attr_rxbuf = {
DMA_ATTR_V0, /* dma_attr_version */
0, /* dma_attr_addr_lo */
0x7ffffffffULL, /* dma_attr_addr_hi */
0xffffull, /* dma_attr_count_max */
4096, /* dma_attr_align */
0xfff8ull, /* dma_attr_burstsizes */
1, /* dma_attr_minxfer */
0xffffffffull, /* dma_attr_maxxfer */
0xffffull, /* dma_attr_seg */
1, /* dma_attr_sgllen */
1, /* dma_attr_granular */
0 /* dma_attr_flags */
};
static ddi_dma_attr_t unm_dma_attr_cmddesc = {
DMA_ATTR_V0, /* dma_attr_version */
0, /* dma_attr_addr_lo */
0x7ffffffffULL, /* dma_attr_addr_hi */
0xffffull, /* dma_attr_count_max */
1, /* dma_attr_align */
0xfff8ull, /* dma_attr_burstsizes */
1, /* dma_attr_minxfer */
0xffff0ull, /* dma_attr_maxxfer */
0xffffull, /* dma_attr_seg */
16, /* dma_attr_sgllen */
1, /* dma_attr_granular */
0 /* dma_attr_flags */
};
static int
{
int ret = 0;
if (val == 0x55555555) {
/* This is the first boot after power up */
&val, 4);
if (val != 0x80000f)
ret = -1;
/* Start P2 boot loader */
}
}
return (ret);
}
static int
{
int i, addr;
return (-1);
ptr32++;
}
int local;
return (-1);
}
return (0);
}
static int
{
// FOR P3, read from CAM RAM
if (pci_func & 1) {
&temp, 4);
*pmac16 = 0;
} else {
&temp, 4);
*pmac16 = 0;
}
return (0);
}
pmac) == -1)
return (-1);
return (-1);
return (-1);
}
return (0);
}
static int
{
return (DDI_ENOMEM);
}
&hi, 4);
&lo, 4);
&temp, 4);
}
return (DDI_SUCCESS);
}
void
{
}
}
static int
{
int *reg_options;
int ret;
struct nx_legacy_intr_set *legacy_intrp;
if (vendor_id != 0x4040) {
return (DDI_FAILURE);
}
if (ret != DDI_PROP_SUCCESS) {
return (DDI_FAILURE);
}
/*
* Need this check so that MEZZ card mgmt interface ntxn0 could fail
* attach & return and proceed to next interfaces ntxn1 and ntxn2
*/
return (DDI_FAILURE);
}
/*
* Refuse to work with dubious P3 cards.
*/
return (DDI_FAILURE);
}
/*
* Save error reporting settings; clear [19:16] error status bits.
* Set max read request [14:12] to 0 for 128 bytes. Set max payload
* size[7:5] to 0 for for 128 bytes.
*/
pexsizes &= 7;
pexsizes |= 0xF0000;
}
else
legacy_intrp = &legacy_intr[0];
return (DDI_SUCCESS);
}
static void
{
int i;
}
nodep++;
}
}
static int
{
int i;
goto alloc_hdl_fail;
}
if (i > 0)
nodep++;
}
return (DDI_SUCCESS);
return (DDI_FAILURE);
}
static void
{
}
}
}
}
}
static int
{
int ret;
if (ret != DDI_SUCCESS) {
goto dma_mem_fail;
}
if (ret != DDI_SUCCESS) {
goto dma_mem_fail;
}
if (actual_size < size) {
goto dma_mem_fail;
}
goto dma_mem_fail;
}
return (DDI_SUCCESS);
return (DDI_FAILURE);
}
static void
{
int i;
struct unm_cmd_buffer *cmd_buf;
for (i = 0; i < adapter->MaxTxDescCount; i++) {
}
cmd_buf++;
}
}
static int
{
struct unm_cmd_buffer *cmd_buf;
for (i = 0; i < adapter->MaxTxDescCount; i++) {
if (ret != DDI_SUCCESS)
goto alloc_tx_buffer_fail;
allocated++;
cmd_buf++;
}
return (DDI_SUCCESS);
for (i = 0; i < allocated; i++) {
cmd_buf++;
}
return (DDI_FAILURE);
}
/*
* Called by freemsg() to "free" the resource.
*/
static void
unm_rx_buffer_recycle(char *arg)
{
}
static void
{
for (i = 0; i < total_buf; i++) {
buf_pool++;
}
rcv_desc->rx_buf_free = 0;
}
static int
{
/* temporarily set the total rx buffers two times of MaxRxDescCount */
for (i = 0; i < total_buf; i++) {
if (ret != DDI_SUCCESS)
goto alloc_mem_failed;
else {
allocate++;
sreoff);
rx_buffer++;
}
}
for (i = 0; i < (total_buf - 1); i++) {
}
return (DDI_SUCCESS);
}
return (DDI_FAILURE);
}
static void
{
/*
* Reduce number of regular rcv desc to half on x86.
*/
#if !defined(_LP64)
maxrx /= 2;
#endif /* !_LP64 */
dmesg_propname, 0);
} else {
".conf value is not 2 power aligned in range 256 - %d\n",
}
if (rx_desc >= NX_MIN_DRIVER_RDS_SIZE &&
} else {
".conf value is not 2 power aligned in range %d - %d\n",
}
if (rx_jdesc >= NX_MIN_DRIVER_RDS_SIZE &&
} else {
".conf value is not 2 power aligned in range %d - %d\n",
}
/*
* Solaris does not use LRO, but older firmware needs to have a
* couple of descriptors for initialization.
*/
}
}
/*
* If we are not expecting to receive jumbo frames, save memory and
* do not allocate.
*/
for (i = 0; i < MAX_RCV_CTX; ++i) {
switch (RCV_DESC_TYPE(ring)) {
case RCV_DESC_NORMAL:
} else {
}
break;
case RCV_DESC_JUMBO:
} else {
if (NX_IS_REVISION_P2(revid))
else
}
break;
case RCV_RING_LRO:
break;
default:
break;
}
}
}
}
static void
{
}
static void
{
}
static int
{
int ret;
unsigned long pci_len0;
unsigned long first_page_group_start, first_page_group_end;
/* map register space */
if (ret != DDI_SUCCESS) {
return (DDI_FAILURE);
}
if (ret != DDI_SUCCESS) {
return (DDI_FAILURE);
}
if (regsize == UNM_PCI_128MB_SIZE) {
} else if (regsize == UNM_PCI_32MB_SIZE) {
pci_len0 = 0;
first_page_group_end = 0;
} else if (regsize == UNM_PCI_2MB_SIZE) {
first_page_group_end = 0;
else
} else {
return (DDI_FAILURE);
}
/* map doorbell */
if (ret != DDI_SUCCESS) {
return (DDI_FAILURE);
}
return (DDI_SUCCESS);
}
static int
{
int ret;
if (ret != DDI_SUCCESS) {
return (DDI_FAILURE);
}
goto found_msi;
"ddi_intr_get_nintrs() failure ret=%d\n", ret);
return (DDI_FAILURE);
}
if (type == DDI_INTR_TYPE_MSI)
/* Get number of available interrupts */
ret);
return (DDI_FAILURE);
}
return (DDI_FAILURE);
}
if (ret != DDI_SUCCESS) {
}
/* Call ddi_intr_add_handler() */
if (ret != DDI_SUCCESS) {
return (DDI_FAILURE);
}
/* Add softintr if required */
return (DDI_SUCCESS);
}
void
{
/* disable interrupt */
else
/* Remove the software intr handler */
}
static void
{
static int wol_port_mode = UNM_PORT_MODE_AUTO_NEG_1G;
static int port_mode = UNM_PORT_MODE_AUTO_NEG;
if ((port_mode != UNM_PORT_MODE_802_3_AP) &&
(port_mode != UNM_PORT_MODE_XG) &&
(port_mode != UNM_PORT_MODE_AUTO_NEG_1G) &&
&data, 4);
if ((wol_port_mode != UNM_PORT_MODE_802_3_AP) &&
(wol_port_mode != UNM_PORT_MODE_XG) &&
&wol_port_mode, 4);
}
}
static void
{
&chicken, 4);
chicken |= 0x01000000;
&chicken, 4);
}
static int
{
unsigned char *p;
int i;
return (-1);
else
for (i = 0; i < 6; i++)
return (-1);
return (0);
}
static int
{
int i, first_driver = 0;
switch (cmd) {
case DDI_ATTACH:
break;
case DDI_RESUME:
case DDI_PM_RESUME:
default:
return (DDI_FAILURE);
}
if (ret != DDI_SUCCESS) {
goto attach_setup_err;
}
if (ret != DDI_SUCCESS)
goto attach_err;
if (ret != DDI_SUCCESS)
goto attach_err;
goto attach_unmap_regs;
/*
* Set the CRB window to invalid. If any register in window 0 is
* accessed it should set window to 0 and then reset it to 1.
*/
else
if (ret != DDI_SUCCESS) {
goto attach_destroy_intr;
}
/* Mezz cards have PCI function 0, 2, 3 enabled */
}
default:
break;
}
first_driver = 1;
} else {
first_driver = 1;
}
if (first_driver) {
UNM_CAM_RAM(0x1fc));
if (check_hw_init(adapter) != 0) {
goto attach_destroy_intr;
}
if (first_boot != 0x55555555) {
temp = 0;
&temp, 4);
if (pinit_from_rom(adapter, 0) != 0)
goto attach_destroy_intr;
drv_usecwait(500);
if (ret != DDI_SUCCESS)
goto attach_destroy_intr;
}
goto attach_destroy_intr;
/*
* Tell the hardware our version number.
*/
i = (_UNM_NIC_MAJOR << 16) |
&i, 4);
/* Unlock the HW, prompting the boot sequence */
if ((first_boot == 0x55555555) &&
/* Handshake with the card before we register the devices. */
goto attach_destroy_intr;
}
/*
* See if the firmware gave us a virtual-physical port mapping.
*/
if (i != 0x55555555)
if (receive_peg_ready(adapter)) {
goto free_dummy_dma;
}
if (netxen_read_mac_addr(adapter))
if (verbmsg != 0) {
case UNM_NIC_GBE:
break;
case UNM_NIC_XGBE:
break;
}
}
if (ret != DDI_SUCCESS) {
goto free_dummy_dma;
}
return (DDI_SUCCESS);
if (first_driver)
return (ret);
}
static int
{
return (DDI_FAILURE);
switch (cmd) {
case DDI_DETACH:
return (DDI_SUCCESS);
case DDI_SUSPEND:
return (unm_nic_suspend(adapter));
default:
break;
}
return (DDI_FAILURE);
}
int
{
int i, ring;
KM_SLEEP);
for (i = 0; i < MAX_RCV_CTX; ++i) {
goto attach_free_cmdbufs;
}
}
goto attach_free_cmdbufs;
goto attach_free_tx_dmahdl;
return (DDI_SUCCESS);
for (i = 0; i < MAX_RCV_CTX; ++i) {
}
}
return (DDI_FAILURE);
}
void
{
}
}
}
#ifdef SOLARIS11
#else
#endif
&mod_driverops, /* Type of module. This one is a driver */
ident,
&unm_ops, /* driver ops */
};
static struct modlinkage modlinkage = {
(&modldrv),
};
int
_init(void)
{
int ret;
if (ret != DDI_SUCCESS) {
}
return (ret);
}
int
_fini(void)
{
int ret;
if (ret == DDI_SUCCESS)
return (ret);
}
int
{
}