/*
* 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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* This file is part of the Chelsio T1 Ethernet driver.
*
* Copyright (C) 2003-2005 Chelsio Communications. All rights reserved.
*/
/*
* Solaris Multithreaded STREAMS Chelsio PCI Ethernet Driver.
* Interface code
*/
#include <sys/byteorder.h>
#include <sys/ethernet.h>
#endif
#include "ostypes.h"
#include "common.h"
#include "oschtoe.h"
#ifdef CONFIG_CHELSIO_T1_1G
#include "fpga_defs.h"
#endif
#include "regs.h"
#ifdef CONFIG_CHELSIO_T1_OFFLOAD
#include "mc3.h"
#include "mc4.h"
#endif
#include "sge.h"
#include "tp.h"
#ifdef CONFIG_CHELSIO_T1_OFFLOAD
#include "ulp.h"
#endif
#include "espi.h"
#include "elmer0.h"
#include "gmac.h"
#include "cphy.h"
#include "suni1x10gexp_regs.h"
#include "ch.h"
extern uint32_t buffers_in_use[];
extern uint32_t in_use_index;
/*
* CPL5 Defines (from netinet/cpl5_commands.h)
*/
/*
* See PCI register 0xc definition.
*/
/*
* TCP and UDP.
*/
/*
* Multiplier for freelist pool.
*/
{
return (DDI_INTR_CLAIMED);
}
return (DDI_INTR_UNCLAIMED);
}
/*
* Each setup struct will call this function to
* initialize.
*/
void
{
int i = 0;
/*
* Need to count the number of times this routine is called
* because we only want the resources to be allocated once.
* The 7500 has four ports and so this routine can be called
* once for each port.
*/
if (sa->init_counter == 0) {
/*
* We only want to initialize the line if it is down.
*/
}
}
(void) t1_init_hw_modules(sa);
/*
*/
/* Notify that HW will do the checksum. */
}
/* Notify that HW will do the checksum. */
}
/* Notify that HW will do the checksum. */
}
}
sa->init_counter++;
}
/*
* Enable interrupts after starting the SGE so
* that the SGE is ready to handle interrupts.
*/
/*
* set mtu (either 1500 or bigger)
*/
(void) pe_change_mtu(sa);
#ifdef HOST_PAUSE
/*
* get the configured value of the MAC.
*/
#endif
}
/* ARGSUSED */
static void
{
}
/*
* turn off interrupts...
*/
void
{
/*
* we can still be running an interrupt thread in sge_data_in().
* If we are, we'll block on the ch_intr lock
*/
}
/*
* output mblk to SGE level and out to the wire.
*/
int
{
uint32_t);
#if defined(__sparc)
uint32_t);
#endif
#ifdef CONFIG_CHELSIO_T1_OFFLOAD
if (flg & CH_OFFLOAD) {
/* make sure data is flushed to physical memory */
return (0);
}
/*
* set a flag so we'll restart upper layer when
* resources become available.
*/
return (1);
}
#endif /* CONFIG_CHELSIO_T1_OFFLOAD */
/* writes from toe will always have CPL header in place */
/* PR2928 & PR3309 */
if (ethertype == ETHERTYPE_ARP) {
/*
* We assume here that the arp will be
* contained in one mblk.
*/
return (0);
}
} else {
}
}
}
/*
* if space in front of packet big enough for CPL
* header, then use it. We'll allocate an mblk
* otherwise.
*/
} else {
#ifdef SUN_KSTATS
#endif
return (0);
}
freeme = 1;
}
/* fill in cpl header */
cpl->l4_csum_dis =
}
#ifdef SUN_KSTATS
#endif
while (mp) {
int len;
/* skip mlks with no data */
if (len == 0) {
continue;
}
/*
* if we've run out of space on stack, then we
* allocate a temporary buffer to hold the
* information. This will kill the the performance,
* but since it shouldn't really occur, we can live
* with it. Since jumbo frames may map multiple
* descriptors, we reallocate the hmp[] array before
* we reach the end.
*/
int j;
KM_SLEEP);
for (j = 0; j < nseg; j++)
if (cm_flg) {
} else
cm_flg = 1;
/*
* We've used up ch table on stack
*/
}
#if defined(__sparc)
/*
* ran out of space. Gonna bale
*/
rv = 0;
/*
* we may have processed
* previous mblks and have
* descriptors. If so, we need
* to free the meta struct
* entries before freeing
* the mblk.
*/
if (nseg)
goto error;
goto error1;
}
}
} else {
/*
* ran out of space. Gona bale
*/
rv = 0;
/*
* we may have processed previous
* mblks and have descriptors. If so,
* we need to free the meta struct
* entries before freeing the mblk.
*/
if (nseg)
goto error;
goto error1;
}
}
#else /* defined(__sparc) */
/*
* ran out of space. Gona bale
*/
rv = 0;
/*
* we may have processed previous mblks and
* have descriptors. If so, we need to free
* the meta struct entries before freeing
* the mblk.
*/
if (nseg)
goto error;
goto error1;
}
#endif /* defined(__sparc) */
}
/*
* SHOULD NEVER OCCUR, BUT...
* no data if nseg 0 or
* nseg 1 and a CPL mblk (CPL mblk only with offload mode)
* and no data
*/
rv = 0;
goto error1;
}
} else {
int len;
/* we assume that we always have data with one packet */
#if defined(__sparc)
&hmp[0], 16);
&hmp[0], 16);
/*
* ran out of space. Gona bale
*/
rv = 0;
goto error1;
}
}
} else {
/*
* ran out of space. Gona bale
*/
rv = 0;
goto error1;
}
}
#else /* defined(__sparc) */
/*
* ran out of space. Gona bale
*/
rv = 0;
goto error1;
}
#endif /* defined(__sparc) */
/*
* dummy arp message to handle PR3309 & PR2928
*/
}
if (cm_flg)
return (0);
}
/*
* set a flag so we'll restart upper layer when
* resources become available.
*/
rv = 1;
/*
* unmap the physical addresses allocated earlier.
*/
#if defined(__sparc)
else
#endif
}
cmp++;
}
/* free the temporary array */
if (cm_flg)
/*
* if we've allocated an mblk above, then we need to free it
* before returning. This is safe since we haven't done anything to
* the original message. The caller, gld, will still have a pointer
* to the original mblk.
*/
if (rv == 1) {
if (freeme) {
/* we had to allocate an mblk. Free it. */
} else {
/* adjust the mblk back to original start */
}
} else {
}
return (rv);
}
/* KLUDGE ALERT. HARD WIRED TO PORT ZERO */
void
{
}
/* KLUDGE ALERT. HARD WIRED TO PORT ZERO */
unsigned char *
{
}
/* KLUDGE ALERT. HARD WIRED TO ONE PORT */
void
{
switch (flag) {
case 0: /* turn off promiscuous mode */
break;
case 1: /* turn on promiscuous mode */
break;
case 2: /* turn on multicast reception */
break;
}
}
int
{
if (flg == GLD_MULTI_ENABLE) {
return (GLD_NORESOURCES);
} else if (flg == GLD_MULTI_DISABLE) {
while (*p) {
q = *p;
*p = (*p)->cmc_next;
kmem_free(q, sizeof (*q));
break;
}
p = &(*p)->cmc_next;
}
if (q == NULL)
return (GLD_BADARG);
} else
return (GLD_BADARG);
return (GLD_SUCCESS);
}
/*
* return: speed - bandwidth of interface
* return: intrcnt - # interrupts
* return: norcvbuf - # recedived packets dropped by driver
* return: oerrors - # bad send packets
* return: ierrors - # bad receive packets
* return: underrun - # bad underrun xmit packets
* return: overrun - # bad overrun recv packets
* return: framing - # bad aligned recv packets
* return: crc - # bad FCS (crc) recv packets
* return: carrier - times carrier was lost
* return: collisions - # xmit collisions
* return: xcollisions - # xmit pkts dropped due to collisions
* return: late - # late xmit collisions
* return: defer - # deferred xmit packets
* return: xerrs - # xmit dropped packets
* return: rerrs - # recv dropped packets
* return: toolong - # recv pkts too long
* return: runt - # recv runt pkts
* return: multixmt - # multicast pkts xmitted
* return: multircv - # multicast pkts recved
* return: brdcstxmt - # broadcast pkts xmitted
* return: brdcstrcv - # broadcast pkts rcv
*/
int
{
int line_speed;
int line_duplex;
int line_is_active;
uint64_t v;
switch (line_speed) {
case SPEED_10:
*speed = 10000000;
break;
case SPEED_100:
*speed = 100000000;
break;
case SPEED_1000:
*speed = 1000000000;
break;
case SPEED_10000:
/*
* kludge to get 10,000,000,000 constant (and keep
* compiler happy).
*/
v = 10000000;
v *= 1000;
*speed = v;
break;
default:
goto error;
}
/*
* not sure this is correct. # aborted at driver level +
* # at hardware level
*/
*carrier = 0; /* need to find this */
return (0);
*speed = 0;
*intrcnt = 0;
*norcvbuf = 0;
*norcvbuf = 0;
*oerrors = 0;
*ierrors = 0;
*underrun = 0;
*overrun = 0;
*framing = 0;
*crc = 0;
*carrier = 0;
*collisions = 0;
*xcollisions = 0;
*late = 0;
*defer = 0;
*xerrs = 0;
*rerrs = 0;
*toolong = 0;
*runt = 0;
*multixmt = 0;
*multircv = 0;
*brdcstxmt = 0;
*brdcstrcv = 0;
return (1);
}
int
{
(void) ch_set_config_data(chp);
if (bi == 0)
return (1);
return (1);
return (1);
return (1);
/*
* We gain significaint performance improvements when we
* increase the PCI's maximum memory read byte count to
* 2K(HW doesn't support 4K at this time) and set the PCI's
* maximum outstanding split transactions to 4. We want to do
* this for 10G. Done by software utility.
*/
&pcix_cmd);
/*
* if the burstsize is set, then use it instead of default
*/
pcix_cmd &= ~0xc0000;
}
/*
* if the split transaction count is set, then use it.
*/
pcix_cmd &= ~ 0x700000;
}
/*
* set ralaxed ordering flag as configured in chxge.conf
*/
pcix_cmd);
}
/*
* set the latency time to F8 for 10G cards.
* Done by software utiltiy.
*/
if (enable_latency_timer) {
}
}
/*
* update mtu table (regs: 0x404 - 0x420) with bigger values than
* default.
*/
/*
* Clear all interrupts now. Don't enable
* them until later.
*/
/*
* Function succeeded.
*/
return_val = 0;
return (return_val);
}
/*
* DESC: Read variables set in /boot/loader.conf and save
* them internally. These internal values are then
* used to make decisions at run-time on behavior thus
* allowing a certain level of customization.
* OUT: p_config - pointer to config structure that
* contains all of the new values.
* RTN: 0 - Success;
*/
static int
{
/*
* Global Tunnel Mode configuration
*/
/*
* MC5 configuration.
*/
/*
* Link configuration.
*
* 5-auto-neg 2-1000Gbps; 1-100Gbps; 0-10Gbps
*/
/*
* Catp options
*/
/*
* SGE configuration.
*/
return (0);
}
static const struct board_info *
{
"The adapter with device_id %d %d is not supported.\n",
return (NULL);
}
return ((const struct board_info *)NULL);
}
return (bi);
}
/*
* allocate pool of small receive buffers (with vaddr & paddr) and
* receiver buffer control structure (ch_esb_t *rbp).
* XXX we should allow better tuning of the # of preallocated
* free buffers against the # of freelist entries.
*/
static int
{
int i;
extern uint32_t sge_flq0_cnt;
extern uint32_t sge_flq1_cnt;
int size;
uint32_t j;
else
j = in_use_index++;
if (in_use_index >= SZ_INUSE)
in_use_index = 0;
sa->ch_sm_index = j;
for (i = 0; i < size; i++) {
goto error;
/*
* add entry to free list
*/
/*
* add entry to owned list
*/
}
return (1);
/* free whatever we've already allocated */
return (0);
}
/*
* allocate pool of receive buffers (with vaddr & paddr) and
* receiver buffer control structure (ch_esb_t *rbp).
* XXX we should allow better tuning of the # of preallocated
* free buffers against the # of freelist entries.
*/
static int
{
int i;
extern uint32_t sge_flq0_cnt;
extern uint32_t sge_flq1_cnt;
int size;
uint32_t j;
else
j = in_use_index++;
if (in_use_index >= SZ_INUSE)
in_use_index = 0;
sa->ch_big_index = j;
for (i = 0; i < size; i++) {
goto error;
/*
* add entry to owned list
*/
}
return (1);
/* free whatever we've already allocated */
return (0);
}
/*
* allocate receive buffer structure and dma mapped buffer (SGE_SM_BUF_SZ bytes)
* note that we will DMA at a 2 byte offset for Solaris when checksum offload
* is enabled.
*/
static ch_esb_t *
{
return ((ch_esb_t *)0);
}
#if BYTE_ORDER == BIG_ENDIAN
#else
#endif
return ((ch_esb_t *)0);
}
return (rbp);
}
/*
* allocate receive buffer structure and dma mapped buffer (SGE_BG_BUF_SZ bytes)
* note that we will DMA at a 2 byte offset for Solaris when checksum offload
* is enabled.
*/
static ch_esb_t *
{
return ((ch_esb_t *)0);
}
#if BYTE_ORDER == BIG_ENDIAN
#else
#endif
return ((ch_esb_t *)0);
}
return (rbp);
}
/*
* free entries on the receive buffer list.
*/
void
{
/*
* Now set-up the rest to commit suicide.
*/
while (sa->ch_small_owner) {
}
/* advance head ptr to next entry */
/* free private buffer allocated in ch_alloc_esbbuf() */
/* free descripter buffer */
}
/* destroy ch_esbl lock */
/*
* Now set-up the rest to commit suicide.
*/
while (sa->ch_big_owner) {
}
/* advance head ptr to next entry */
/* free private buffer allocated in ch_alloc_esbbuf() */
/* free descripter buffer */
}
/* destroy ch_esbl lock */
}
void
{
uint32_t i;
/*
* free private buffer allocated in ch_alloc_esbbuf()
*/
/*
* free descripter buffer
*/
/*
* decrement count of receive buffers freed by callback
* We decrement here so anyone trying to do fini will
* only remove the driver once the counts go to 0.
*/
atomic_dec_32(&buffers_in_use[i]);
return;
}
/*
* decrement count of receive buffers freed by callback
*/
}
/*
* callback function from freeb() when esballoced mblk freed.
*/
void
{
uint32_t i;
/*
* free private buffer allocated in ch_alloc_esbbuf()
*/
/*
* free descripter buffer
*/
/*
* decrement count of receive buffers freed by callback
* We decrement here so anyone trying to do fini will
* only remove the driver once the counts go to 0.
*/
atomic_dec_32(&buffers_in_use[i]);
return;
}
/*
* decrement count of receive buffers freed by callback
*/
}
/*
* get a pre-allocated, pre-mapped receive buffer from free list.
* (used sge.c)
*/
ch_esb_t *
{
if (rbp) {
}
return (rbp);
}
/*
* get a pre-allocated, pre-mapped receive buffer from free list.
* (used sge.c)
*/
ch_esb_t *
{
if (rbp) {
}
return (rbp);
}
void
{
}
static void
{
if (sa) {
/* free pool of receive buffers */
}
}
/*
* Processes elmer0 external interrupts in process context.
*/
static void
{
(void) elmer0_ext_intr_handler(adapter);
/* Now reenable external interrupts */
}
/*
* Interrupt-context handler for elmer0 external interrupts.
*/
void
{
#ifdef NOTYET
#else
#endif
}
uint8_t *
{
}
return (addr);
}
void
{
#if defined(__sparc)
break;
}
#endif
while (cnt--) {
return;
}
}
/*
* Write new values to the MTU table. Caller must validate that the new MTUs
* are in ascending order. params.mtus[] is initialized by init_mtus()
* called in t1_init_sw_modules().
*/
static void
{
int i;
for (i = 0; i < NMTUS; ++i) {
}
}
static int
{
int ret;
return (EOPNOTSUPP);
}
return (EINVAL);
}
return (ret);
}
return (0);
}
typedef struct fake_arp {
char fa_hln;
char fa_pln;
} fake_arp_t;
/*
* PR2928 & PR3309
* construct packet in mblk and attach it to sge structure.
*/
static int
{
return (1);
}
/* fill in cpl header */
return (0);
}
/*
* PR2928 & PR3309
* free the fake arp's mblk on sge structure.
*/
void
{
}
/*
* extract ip address of nic from first outgoing arp.
*/
static uint32_t
{
/*
* first copy packet to buffer so we know
* it will be properly aligned.
*/
}
/* ARGSUSED */
void
{
if (link_status) {
/*
* Link states should be reported to user
* whenever it changes
*/
} else {
/*
* Link states should be reported to user
* whenever it changes
*/
}
}