| /* |
| * 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 |
| * or http://www.opensolaris.org/os/licensing. |
| * 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 2009 Sun Microsystems, Inc. All rights reserved. |
| * Use is subject to license terms. |
| */ |
| |
| #ifndef _SYS_NGE_H |
| #define _SYS_NGE_H |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| |
| #include <sys/types.h> |
| #include <sys/stream.h> |
| #include <sys/strsun.h> |
| #include <sys/strsubr.h> |
| #include <sys/stat.h> |
| #include <sys/pci.h> |
| #include <sys/note.h> |
| #include <sys/modctl.h> |
| #include <sys/kstat.h> |
| #include <sys/ethernet.h> |
| #include <sys/pattr.h> |
| #include <sys/errno.h> |
| #include <sys/dlpi.h> |
| #include <sys/devops.h> |
| #include <sys/debug.h> |
| #include <sys/conf.h> |
| #include <sys/callb.h> |
| |
| #include <netinet/ip6.h> |
| |
| #include <inet/common.h> |
| #include <inet/ip.h> |
| #include <netinet/udp.h> |
| #include <inet/mi.h> |
| #include <inet/nd.h> |
| |
| #include <sys/ddi.h> |
| #include <sys/sunddi.h> |
| |
| #include <sys/mac_provider.h> |
| #include <sys/mac_ether.h> |
| |
| /* |
| * Reconfiguring the network devices requires the net_config privilege |
| * in Solaris 10+. |
| */ |
| extern int secpolicy_net_config(const cred_t *, boolean_t); |
| |
| #include <sys/netlb.h> |
| #include <sys/miiregs.h> |
| |
| #include "nge_chip.h" |
| |
| #define PIO_ADDR(ngep, offset) ((void *)((caddr_t)(ngep)->io_regs+(offset))) |
| /* |
| * Copy an ethernet address |
| */ |
| #define ethaddr_copy(src, dst) bcopy((src), (dst), ETHERADDRL) |
| #define ether_eq(a, b) (bcmp((caddr_t)(a), (caddr_t)(b), (ETHERADDRL)) == 0) |
| |
| #define BIS(w, b) (((w) & (b)) ? B_TRUE : B_FALSE) |
| #define BIC(w, b) (((w) & (b)) ? B_FALSE : B_TRUE) |
| #define UPORDOWN(x) ((x) ? "up" : "down") |
| |
| #define NGE_DRIVER_NAME "nge" |
| |
| /* |
| * 'Progress' bit flags ... |
| */ |
| #define PROGRESS_CFG 0x0001 /* config space mapped */ |
| #define PROGRESS_REGS 0x0002 /* registers mapped */ |
| #define PROGRESS_BUFS 0x0004 /* registers mapped */ |
| #define PROGRESS_RESCHED 0x0008 /* resched softint registered */ |
| #define PROGRESS_FACTOTUM 0x0010 /* factotum softint registered */ |
| #define PROGRESS_SWINT 0x0020 /* s/w interrupt registered */ |
| #define PROGRESS_INTR 0x0040 /* h/w interrupt registered */ |
| /* and mutexen initialised */ |
| #define PROGRESS_HWINT 0x0080 |
| #define PROGRESS_PHY 0x0100 /* PHY initialised */ |
| #define PROGRESS_NDD 0x0200 /* NDD parameters set up */ |
| #define PROGRESS_KSTATS 0x0400 /* kstats created */ |
| #define PROGRESS_READY 0x0800 /* ready for work */ |
| |
| #define NGE_HW_ERR 0x00 |
| #define NGE_HW_LINK 0x01 |
| #define NGE_HW_BM 0x02 |
| #define NGE_HW_RCHAN 0x03 |
| #define NGE_HW_TCHAN 0x04 |
| #define NGE_HW_ROM 0x05 |
| #define NGE_SW_PROBLEM_ID 0x06 |
| |
| |
| /* |
| * NOTES: |
| * |
| * #defines: |
| * |
| * NGE_PCI_CONFIG_RNUMBER and NGE_PCI_OPREGS_RNUMBER are the |
| * register-set numbers to use for the config space registers |
| * and the operating registers respectively. On an OBP-based |
| * machine, regset 0 refers to CONFIG space, and regset 1 will |
| * be the operating registers in MEMORY space. If an expansion |
| * ROM is fitted, it may appear as a further register set. |
| * |
| * NGE_DMA_MODE defines the mode (STREAMING/CONSISTENT) used |
| * for the data buffers. The descriptors are always set up |
| * in CONSISTENT mode. |
| * |
| * NGE_HEADROOM defines how much space we'll leave in allocated |
| * mblks before the first valid data byte. This should be chosen |
| * to be 2 modulo 4, so that once the ethernet header (14 bytes) |
| * has been stripped off, the packet data will be 4-byte aligned. |
| * The remaining space can be used by upstream modules to prepend |
| * any headers required. |
| */ |
| |
| |
| #define NGE_PCI_OPREGS_RNUMBER 1 |
| #define NGE_DMA_MODE DDI_DMA_STREAMING |
| #define NGE_HEADROOM 6 |
| #define ETHER_HEAD_LEN 14 |
| #ifndef VTAG_SIZE |
| #define VTAG_SIZE 4 |
| #endif |
| |
| #define NGE_CYCLIC_PERIOD (1000000000) |
| |
| #define NGE_DEFAULT_MTU 1500 |
| #define NGE_DEFAULT_SDU 1518 |
| #define NGE_MTU_2500 2500 |
| #define NGE_MTU_4500 4500 |
| #define NGE_MAX_MTU 9000 |
| #define NGE_MAX_SDU 9018 |
| |
| #define NGE_DESC_MIN 0x200 |
| |
| #define NGE_STD_BUFSZ 1792 |
| #define NGE_JB2500_BUFSZ (3*1024) |
| #define NGE_JB4500_BUFSZ (5*1024) |
| #define NGE_JB9000_BUFSZ (9*1024) |
| |
| #define NGE_SEND_SLOTS_DESC_1024 1024 |
| #define NGE_SEND_SLOTS_DESC_3072 3072 |
| #define NGE_SEND_JB2500_SLOTS_DESC 3072 |
| #define NGE_SEND_JB4500_SLOTS_DESC 2048 |
| #define NGE_SEND_JB9000_SLOTS_DESC 1024 |
| #define NGE_SEND_LOWMEM_SLOTS_DESC 1024 |
| #define NGE_SEND_SLOTS_BUF 3072 |
| |
| #define NGE_RECV_SLOTS_DESC_1024 1024 |
| #define NGE_RECV_SLOTS_DESC_3072 3072 |
| #define NGE_RECV_JB2500_SLOTS_DESC 3072 |
| #define NGE_RECV_JB4500_SLOTS_DESC 2048 |
| #define NGE_RECV_JB9000_SLOTS_DESC 1024 |
| #define NGE_RECV_LOWMEM_SLOTS_DESC 1024 |
| #define NGE_RECV_SLOTS_BUF 6144 |
| |
| #define NGE_SPLIT_32 32 |
| #define NGE_SPLIT_96 96 |
| #define NGE_SPLIT_256 256 |
| |
| #define NGE_RX_COPY_SIZE 512 |
| #define NGE_TX_COPY_SIZE 512 |
| #define NGE_MAP_FRAGS 3 |
| #define NGE_MAX_COOKIES 3 |
| #define NGE_MAX_DMA_HDR (4*1024) |
| |
| /* Used by interrupt moderation */ |
| #define NGE_TFINT_DEFAULT 32 |
| #define NGE_POLL_TUNE 80000 |
| #define NGE_POLL_ENTER 10000 |
| #define NGE_POLL_MAX 1280000 |
| #define NGE_POLL_QUIET_TIME 100 |
| #define NGE_POLL_BUSY_TIME 2 |
| |
| /* |
| * NGE-specific ioctls ... |
| */ |
| #define NGE_IOC ((((('N' << 8) + 'G') << 8) + 'E') << 8) |
| |
| /* |
| * PHY register read/write ioctls, used by cable test software |
| */ |
| #define NGE_MII_READ (NGE_IOC|1) |
| #define NGE_MII_WRITE (NGE_IOC|2) |
| |
| /* |
| * SEEPROM read/write ioctls, for use by SEEPROM upgrade utility |
| * |
| * Note: SEEPROMs can only be accessed as 32-bit words, so <see_addr> |
| * must be a multiple of 4. Not all systems have a SEEPROM fitted! |
| */ |
| #define NGE_SEE_READ (NGE_IOC|3) |
| #define NGE_SEE_WRITE (NGE_IOC|4) |
| |
| |
| /* |
| * These diagnostic IOCTLS are enabled only in DEBUG drivers |
| */ |
| #define NGE_DIAG (NGE_IOC|5) /* currently a no-op */ |
| #define NGE_PEEK (NGE_IOC|6) |
| #define NGE_POKE (NGE_IOC|7) |
| #define NGE_PHY_RESET (NGE_IOC|8) |
| #define NGE_SOFT_RESET (NGE_IOC|9) |
| #define NGE_HARD_RESET (NGE_IOC|10) |
| |
| |
| enum NGE_HW_OP { |
| NGE_CLEAR = 0, |
| NGE_SET |
| }; |
| |
| /* |
| * Required state according to GLD |
| */ |
| enum nge_mac_state { |
| NGE_MAC_UNKNOWN, |
| NGE_MAC_RESET, |
| NGE_MAC_STOPPED, |
| NGE_MAC_STARTED, |
| NGE_MAC_UNATTACH |
| }; |
| enum loop_type { |
| NGE_LOOP_NONE = 0, |
| NGE_LOOP_EXTERNAL_100, |
| NGE_LOOP_EXTERNAL_10, |
| NGE_LOOP_INTERNAL_PHY, |
| }; |
| |
| /* |
| * (Internal) return values from send_msg subroutines |
| */ |
| enum send_status { |
| SEND_COPY_FAIL = -1, /* => GLD_NORESOURCES */ |
| SEND_MAP_FAIL, /* => GLD_NORESOURCES */ |
| SEND_COPY_SUCESS, /* OK, msg queued */ |
| SEND_MAP_SUCCESS /* OK, free msg */ |
| }; |
| |
| /* |
| * (Internal) return values from ioctl subroutines |
| */ |
| enum ioc_reply { |
| IOC_INVAL = -1, /* bad, NAK with EINVAL */ |
| IOC_DONE, /* OK, reply sent */ |
| IOC_ACK, /* OK, just send ACK */ |
| IOC_REPLY, /* OK, just send reply */ |
| IOC_RESTART_ACK, /* OK, restart & ACK */ |
| IOC_RESTART_REPLY /* OK, restart & reply */ |
| }; |
| |
| enum nge_pp_type { |
| NGE_PP_SPACE_CFG = 0, |
| NGE_PP_SPACE_REG, |
| NGE_PP_SPACE_NIC, |
| NGE_PP_SPACE_MII, |
| NGE_PP_SPACE_NGE, |
| NGE_PP_SPACE_TXDESC, |
| NGE_PP_SPACE_TXBUFF, |
| NGE_PP_SPACE_RXDESC, |
| NGE_PP_SPACE_RXBUFF, |
| NGE_PP_SPACE_STATISTICS, |
| NGE_PP_SPACE_SEEPROM, |
| NGE_PP_SPACE_FLASH |
| }; |
| |
| /* |
| * Flag to kstat type |
| */ |
| enum nge_kstat_type { |
| NGE_KSTAT_RAW = 0, |
| NGE_KSTAT_STATS, |
| NGE_KSTAT_CHIPID, |
| NGE_KSTAT_DEBUG, |
| NGE_KSTAT_COUNT |
| }; |
| |
| |
| /* |
| * Actual state of the nvidia's chip |
| */ |
| enum nge_chip_state { |
| NGE_CHIP_FAULT = -2, /* fault, need reset */ |
| NGE_CHIP_ERROR, /* error, want reset */ |
| NGE_CHIP_INITIAL, /* Initial state only */ |
| NGE_CHIP_RESET, /* reset, need init */ |
| NGE_CHIP_STOPPED, /* Tx/Rx stopped */ |
| NGE_CHIP_RUNNING /* with interrupts */ |
| }; |
| |
| enum nge_eeprom_size { |
| EEPROM_1K = 0, |
| EEPROM_2K, |
| EEPROM_4K, |
| EEPROM_8K, |
| EEPROM_16K, |
| EEPROM_32K, |
| EEPROM_64K |
| }; |
| |
| enum nge_eeprom_access_wid { |
| ACCESS_8BIT = 0, |
| ACCESS_16BIT |
| }; |
| |
| /* |
| * MDIO operation |
| */ |
| enum nge_mdio_operation { |
| NGE_MDIO_READ = 0, |
| NGE_MDIO_WRITE |
| }; |
| |
| /* |
| * Speed selection |
| */ |
| enum nge_speed { |
| UNKOWN_SPEED = 0, |
| NGE_10M, |
| NGE_100M, |
| NGE_1000M |
| }; |
| |
| /* |
| * Duplex selection |
| */ |
| enum nge_duplex { |
| UNKOWN_DUPLEX = 0, |
| NGE_HD, |
| NGE_FD |
| }; |
| |
| typedef struct { |
| ether_addr_t addr; /* in canonical form */ |
| uint8_t spare; |
| uint8_t set; /* nonzero => valid */ |
| } nge_mac_addr_t; |
| |
| struct nge; |
| |
| |
| #define CHIP_FLAG_COPPER 0x40 |
| |
| /* |
| * Collection of physical-layer functions to: |
| * (re)initialise the physical layer |
| * update it to match software settings |
| * check for link status change |
| */ |
| typedef struct { |
| boolean_t (*phys_restart)(struct nge *); |
| void (*phys_update)(struct nge *); |
| boolean_t (*phys_check)(struct nge *); |
| } phys_ops_t; |
| |
| struct nge_see_rw { |
| uint32_t see_addr; /* Byte offset within SEEPROM */ |
| uint32_t see_data; /* Data read/data to write */ |
| }; |
| |
| typedef struct { |
| uint64_t pp_acc_size; /* in bytes: 1,2,4,8 */ |
| uint64_t pp_acc_space; /* See #defines below */ |
| uint64_t pp_acc_offset; |
| uint64_t pp_acc_data; /* output for peek */ |
| /* input for poke */ |
| } nge_peekpoke_t; |
| |
| typedef uintptr_t nge_regno_t; /* register # (offset) */ |
| |
| typedef struct _mul_list { |
| struct _mul_list *next; |
| uint32_t ref_cnt; |
| ether_addr_t mul_addr; |
| }mul_item, *pmul_item; |
| |
| /* |
| * Describes one chunk of allocated DMA-able memory |
| * |
| * In some cases, this is a single chunk as allocated from the system; |
| * but we also use this structure to represent slices carved off such |
| * a chunk. Even when we don't really need all the information, we |
| * use this structure as a convenient way of correlating the various |
| * ways of looking at a piece of memory (kernel VA, IO space DVMA, |
| * handle+offset, etc). |
| */ |
| typedef struct dma_area |
| { |
| |
| caddr_t private; /* pointer to nge */ |
| frtn_t rx_recycle; /* recycle function */ |
| mblk_t *mp; |
| ddi_acc_handle_t acc_hdl; /* handle for memory */ |
| void *mem_va; /* CPU VA of memory */ |
| uint32_t nslots; /* number of slots */ |
| uint32_t size; /* size per slot */ |
| size_t alength; /* allocated size */ |
| /* >= product of above */ |
| ddi_dma_handle_t dma_hdl; /* DMA handle */ |
| offset_t offset; /* relative to handle */ |
| ddi_dma_cookie_t cookie; /* associated cookie */ |
| uint32_t ncookies; |
| uint32_t signature; /* buffer signature */ |
| /* for deciding to free */ |
| /* or to reuse buffers */ |
| boolean_t rx_delivered; /* hold by upper layer */ |
| struct dma_area *next; |
| } dma_area_t; |
| |
| #define HOST_OWN 0x00000000 |
| #define CONTROLER_OWN 0x00000001 |
| #define NGE_END_PACKET 0x00000002 |
| |
| |
| typedef struct nge_dmah_node |
| { |
| struct nge_dmah_node *next; |
| ddi_dma_handle_t hndl; |
| } nge_dmah_node_t; |
| |
| typedef struct nge_dmah_list |
| { |
| nge_dmah_node_t *head; |
| nge_dmah_node_t *tail; |
| } nge_dmah_list_t; |
| |
| /* |
| * Software version of the Recv Descriptor |
| * There's one of these for each recv buffer (up to 512 per ring) |
| */ |
| typedef struct sw_rx_sbd { |
| |
| dma_area_t desc; /* (const) related h/w */ |
| /* descriptor area */ |
| dma_area_t *bufp; /* (const) related */ |
| /* buffer area */ |
| uint8_t flags; |
| } sw_rx_sbd_t; |
| |
| /* |
| * Software version of the send Buffer Descriptor |
| * There's one of these for each send buffer (up to 512 per ring) |
| */ |
| typedef struct sw_tx_sbd { |
| |
| dma_area_t desc; /* (const) related h/w */ |
| /* descriptor area */ |
| dma_area_t pbuf; /* (const) related */ |
| /* buffer area */ |
| void (*tx_recycle)(struct sw_tx_sbd *); |
| uint32_t flags; |
| mblk_t *mp; /* related mblk, if any */ |
| nge_dmah_list_t mp_hndl; |
| uint32_t frags; |
| uint32_t ncookies; /* dma cookie number */ |
| |
| } sw_tx_sbd_t; |
| |
| /* |
| * Software Receive Buffer (Producer) Ring Control Block |
| * There's one of these for each receiver producer ring (up to 3), |
| * but each holds buffers of a different size. |
| */ |
| typedef struct buff_ring { |
| |
| uint64_t nslots; /* descriptor area */ |
| struct nge *ngep; /* (const) containing */ |
| /* driver soft state */ |
| /* initialise same */ |
| uint64_t rx_hold; |
| sw_rx_sbd_t *sw_rbds; /* software descriptors */ |
| sw_rx_sbd_t *free_rbds; /* free ring */ |
| dma_area_t *free_list; /* available buffer queue */ |
| dma_area_t *recycle_list; /* recycling buffer queue */ |
| kmutex_t recycle_lock[1]; |
| uint32_t buf_sign; /* buffer ring signature */ |
| /* for deciding to free */ |
| /* or to reuse buffers */ |
| boolean_t rx_bcopy; |
| } buff_ring_t; |
| |
| /* |
| * Software Receive (Return) Ring Control Block |
| * There's one of these for each receiver return ring (up to 16). |
| */ |
| typedef struct recv_ring { |
| /* |
| * The elements flagged (const) in the comments below are |
| * set up once during initialiation and thereafter unchanged. |
| */ |
| dma_area_t desc; /* (const) related h/w */ |
| /* descriptor area */ |
| struct nge *ngep; /* (const) containing */ |
| /* driver soft state */ |
| uint16_t prod_index; /* (const) ptr to h/w */ |
| /* "producer index" */ |
| mac_resource_handle_t handle; |
| } recv_ring_t; |
| |
| |
| |
| /* |
| * Software Send Ring Control Block |
| * There's one of these for each of (up to) 1 send rings |
| */ |
| typedef struct send_ring { |
| /* |
| * The elements flagged (const) in the comments below are |
| * set up once during initialiation and thereafter unchanged. |
| */ |
| dma_area_t desc; /* (const) related h/w */ |
| /* descriptor area */ |
| dma_area_t buf[NGE_SEND_SLOTS_BUF]; |
| /* buffer area(s) */ |
| struct nge *ngep; /* (const) containing */ |
| /* driver soft state */ |
| |
| uint32_t tx_hwmark; |
| uint32_t tx_lwmark; |
| |
| /* |
| * The tx_lock must be held when updating |
| * the s/w producer index |
| * (tx_next) |
| */ |
| kmutex_t tx_lock[1]; /* serialize h/w update */ |
| uint32_t tx_next; /* next slot to use */ |
| uint32_t tx_flow; |
| |
| /* |
| * These counters/indexes are manipulated in the transmit |
| * path using atomics rather than mutexes for speed |
| */ |
| uint32_t tx_free; /* # of slots available */ |
| |
| /* |
| * index (tc_next). |
| */ |
| kmutex_t tc_lock[1]; |
| uint32_t tc_next; /* next slot to recycle */ |
| /* ("consumer index") */ |
| |
| sw_tx_sbd_t *sw_sbds; /* software descriptors */ |
| |
| kmutex_t dmah_lock; |
| nge_dmah_list_t dmah_free; |
| nge_dmah_node_t dmahndl[NGE_MAX_DMA_HDR]; |
| |
| } send_ring_t; |
| |
| |
| typedef struct { |
| uint32_t businfo; /* from private reg */ |
| uint16_t command; /* saved during attach */ |
| |
| uint16_t vendor; /* vendor-id */ |
| uint16_t device; /* device-id */ |
| uint16_t subven; /* subsystem-vendor-id */ |
| uint16_t subdev; /* subsystem-id */ |
| uint8_t class_code; |
| uint8_t revision; /* revision-id */ |
| uint8_t clsize; /* cache-line-size */ |
| uint8_t latency; /* latency-timer */ |
| uint8_t flags; |
| |
| uint16_t phy_type; /* Fiber module type */ |
| uint64_t hw_mac_addr; /* from chip register */ |
| nge_mac_addr_t vendor_addr; /* transform of same */ |
| } chip_info_t; |
| |
| |
| typedef struct { |
| offset_t index; |
| char *name; |
| } nge_ksindex_t; |
| |
| typedef struct { |
| uint64_t tso_err_mss; |
| uint64_t tso_dis; |
| uint64_t tso_err_nosum; |
| uint64_t tso_err_hov; |
| uint64_t tso_err_huf; |
| uint64_t tso_err_l2; |
| uint64_t tso_err_ip; |
| uint64_t tso_err_l4; |
| uint64_t tso_err_tcp; |
| uint64_t hsum_err_ip; |
| uint64_t hsum_err_l4; |
| }fe_statistics_t; |
| |
| /* |
| * statistics parameters to tune the driver |
| */ |
| typedef struct { |
| uint64_t intr_count; |
| uint64_t intr_lval; |
| uint64_t recv_realloc; |
| uint64_t poll_time; |
| uint64_t recy_free; |
| uint64_t recv_count; |
| uint64_t xmit_count; |
| uint64_t obytes; |
| uint64_t rbytes; |
| uint64_t mp_alloc_err; |
| uint64_t dma_alloc_err; |
| uint64_t kmem_alloc_err; |
| uint64_t load_context; |
| uint64_t ip_hwsum_err; |
| uint64_t tcp_hwsum_err; |
| uint64_t rx_nobuffer; |
| uint64_t rx_err; |
| uint64_t tx_stop_err; |
| uint64_t tx_stall; |
| uint64_t tx_rsrv_fail; |
| uint64_t tx_resched; |
| fe_statistics_t fe_err; |
| }nge_sw_statistics_t; |
| |
| typedef struct { |
| nge_hw_statistics_t hw_statistics; |
| nge_sw_statistics_t sw_statistics; |
| }nge_statistics_t; |
| |
| struct nge_desc_attr { |
| |
| size_t rxd_size; |
| size_t txd_size; |
| |
| ddi_dma_attr_t *dma_attr; |
| ddi_dma_attr_t *tx_dma_attr; |
| |
| void (*rxd_fill)(void *, const ddi_dma_cookie_t *, size_t); |
| uint32_t (*rxd_check)(const void *, size_t *); |
| |
| void (*txd_fill)(void *, const ddi_dma_cookie_t *, size_t, |
| uint32_t, boolean_t, boolean_t); |
| |
| uint32_t (*txd_check)(const void *); |
| }; |
| |
| typedef struct nge_desc_attr nge_desc_attr_t; |
| |
| /* |
| * Structure used to hold the device-specific config parameters. |
| * The setting of such parameters may not consistent with the |
| * hardware feature of the device. It's used for software purpose. |
| */ |
| typedef struct nge_dev_spec_param { |
| boolean_t msi; /* specifies msi support */ |
| boolean_t msi_x; /* specifies msi_x support */ |
| boolean_t vlan; /* specifies vlan support */ |
| boolean_t advanced_pm; /* advanced power management support */ |
| boolean_t mac_addr_order; /* mac address order */ |
| boolean_t tx_pause_frame; /* specifies tx pause frame support */ |
| boolean_t rx_pause_frame; /* specifies rx pause frame support */ |
| boolean_t jumbo; /* jumbo frame support */ |
| boolean_t tx_rx_64byte; /* set the max tx/rx prd fetch size */ |
| boolean_t rx_hw_checksum; /* specifies tx hw checksum feature */ |
| uint32_t tx_hw_checksum; /* specifies rx hw checksum feature */ |
| uint32_t desc_type; /* specifies descriptor type */ |
| uint32_t rx_desc_num; /* specifies rx descriptor number */ |
| uint32_t tx_desc_num; /* specifies tx descriptor number */ |
| uint32_t nge_split; /* specifies the split number */ |
| } nge_dev_spec_param_t; |
| |
| typedef struct nge { |
| /* |
| * These fields are set by attach() and unchanged thereafter ... |
| */ |
| dev_info_t *devinfo; /* device instance */ |
| mac_handle_t mh; /* mac module handle */ |
| chip_info_t chipinfo; |
| ddi_acc_handle_t cfg_handle; /* DDI I/O handle */ |
| ddi_acc_handle_t io_handle; /* DDI I/O handle */ |
| void *io_regs; /* mapped registers */ |
| |
| ddi_periodic_t periodic_id; /* periodical callback */ |
| uint32_t factotum_flag; |
| ddi_softint_handle_t factotum_hdl; /* factotum callback */ |
| ddi_softint_handle_t resched_hdl; /* reschedule callback */ |
| uint_t soft_pri; |
| |
| ddi_intr_handle_t *htable; /* for array of interrupts */ |
| int intr_type; /* type of interrupt */ |
| int intr_actual_cnt; /* alloc intrs count */ |
| int intr_req_cnt; /* request intrs count */ |
| uint_t intr_pri; /* interrupt priority */ |
| int intr_cap; /* interrupt capabilities */ |
| |
| uint32_t progress; /* attach tracking */ |
| uint32_t debug; /* flag to debug function */ |
| |
| char ifname[8]; /* "nge0" ... "nge999" */ |
| |
| |
| enum nge_mac_state nge_mac_state; /* definitions above */ |
| enum nge_chip_state nge_chip_state; /* definitions above */ |
| boolean_t promisc; |
| boolean_t record_promisc; |
| boolean_t suspended; |
| |
| int resched_needed; |
| uint32_t default_mtu; |
| uint32_t max_sdu; |
| uint32_t buf_size; |
| uint32_t rx_desc; |
| uint32_t tx_desc; |
| uint32_t rx_buf; |
| uint32_t nge_split; |
| uint32_t watchdog; |
| uint32_t lowmem_mode; |
| |
| |
| /* |
| * Runtime read-write data starts here ... |
| * 1 Receive Rings |
| * 1 Send Rings |
| * |
| * Note: they're not necessarily all used. |
| */ |
| struct buff_ring buff[1]; |
| struct recv_ring recv[1]; |
| struct send_ring send[1]; |
| |
| |
| kmutex_t genlock[1]; |
| krwlock_t rwlock[1]; |
| kmutex_t softlock[1]; |
| uint32_t intr_masks; |
| boolean_t poll; |
| boolean_t ch_intr_mode; |
| boolean_t intr_moderation; |
| uint32_t recv_count; |
| uint32_t quiet_time; |
| uint32_t busy_time; |
| uint64_t tpkts_last; |
| uint32_t tfint_threshold; |
| uint32_t sw_intr_intv; |
| nge_mac_addr_t cur_uni_addr; |
| uint32_t rx_datahwm; |
| uint32_t rx_prdlwm; |
| uint32_t rx_prdhwm; |
| uint32_t rx_def; |
| uint32_t desc_mode; |
| |
| mul_item *pcur_mulist; |
| nge_mac_addr_t cur_mul_addr; |
| nge_mac_addr_t cur_mul_mask; |
| |
| nge_desc_attr_t desc_attr; |
| |
| /* |
| * Link state data (protected by genlock) |
| */ |
| int32_t link_state; /* See GLD #defines */ |
| uint32_t stall_cknum; /* Stall check number */ |
| |
| uint32_t phy_xmii_addr; |
| uint32_t phy_id; |
| uint32_t phy_mode; |
| const phys_ops_t *physops; |
| uint16_t phy_gen_status; |
| |
| uint32_t param_loop_mode; |
| |
| kstat_t *nge_kstats[NGE_KSTAT_COUNT]; |
| nge_statistics_t statistics; |
| |
| nge_dev_spec_param_t dev_spec_param; |
| |
| uint32_t param_en_pause:1, |
| param_en_asym_pause:1, |
| param_en_1000hdx:1, |
| param_en_1000fdx:1, |
| param_en_100fdx:1, |
| param_en_100hdx:1, |
| param_en_10fdx:1, |
| param_en_10hdx:1, |
| param_adv_autoneg:1, |
| param_adv_pause:1, |
| param_adv_asym_pause:1, |
| param_adv_1000fdx:1, |
| param_adv_1000hdx:1, |
| param_adv_100fdx:1, |
| param_adv_100hdx:1, |
| param_adv_10fdx:1, |
| param_adv_10hdx:1, |
| param_lp_autoneg:1, |
| param_lp_pause:1, |
| param_lp_asym_pause:1, |
| param_lp_1000fdx:1, |
| param_lp_1000hdx:1, |
| param_lp_100fdx:1, |
| param_lp_100hdx:1, |
| param_lp_10fdx:1, |
| param_lp_10hdx:1, |
| param_link_up:1, |
| param_link_autoneg:1, |
| param_link_rx_pause:1, |
| param_link_tx_pause:1, |
| param_pad_to_32:2; |
| uint64_t param_link_speed; |
| link_duplex_t param_link_duplex; |
| int param_txbcopy_threshold; |
| int param_rxbcopy_threshold; |
| int param_recv_max_packet; |
| int param_poll_quiet_time; |
| int param_poll_busy_time; |
| int param_rx_intr_hwater; |
| int param_rx_intr_lwater; |
| } nge_t; |
| |
| extern const nge_ksindex_t nge_statistics[]; |
| |
| /* |
| * Sync a DMA area described by a dma_area_t |
| */ |
| #define DMA_SYNC(area, flag) ((void) ddi_dma_sync((area).dma_hdl, \ |
| (area).offset, (area).alength, (flag))) |
| |
| /* |
| * Find the (kernel virtual) address of block of memory |
| * described by a dma_area_t |
| */ |
| #define DMA_VPTR(area) ((area).mem_va) |
| |
| /* |
| * Zero a block of memory described by a dma_area_t |
| */ |
| #define DMA_ZERO(area) bzero(DMA_VPTR(area), (area).alength) |
| |
| /* |
| * Next/Prev value of a cyclic index |
| */ |
| #define NEXT(index, limit) ((index) + 1 < (limit) ? (index) + 1 : 0) |
| #define PREV(index, limit) (0 == (index) ? (limit - 1) : (index) - 1) |
| |
| #define NEXT_INDEX(ndx, num, lim)\ |
| (((ndx) + (num) < (lim)) ? ((ndx) + (num)) : ((ndx) + (num) - (lim))) |
| |
| |
| /* |
| * Property lookups |
| */ |
| #define NGE_PROP_EXISTS(d, n) ddi_prop_exists(DDI_DEV_T_ANY, (d), \ |
| DDI_PROP_DONTPASS, (n)) |
| #define NGE_PROP_GET_INT(d, n) ddi_prop_get_int(DDI_DEV_T_ANY, (d), \ |
| DDI_PROP_DONTPASS, (n), -1) |
| |
| |
| /* |
| * Debugging ... |
| */ |
| #ifdef DEBUG |
| #define NGE_DEBUGGING 1 |
| #else |
| #define NGE_DEBUGGING 0 |
| #endif /* DEBUG */ |
| |
| /* |
| * Bit flags in the 'debug' word ... |
| */ |
| #define NGE_DBG_STOP 0x00000001 /* early debug_enter() */ |
| #define NGE_DBG_TRACE 0x00000002 /* general flow tracing */ |
| |
| #define NGE_DBG_MII 0x00000010 /* low-level MII access */ |
| #define NGE_DBG_CHIP 0x00000020 /* low(ish)-level code */ |
| |
| #define NGE_DBG_RECV 0x00000100 /* receive-side code */ |
| #define NGE_DBG_SEND 0x00000200 /* packet-send code */ |
| |
| #define NGE_DBG_INIT 0x00100000 /* initialisation */ |
| #define NGE_DBG_NEMO 0x00200000 /* MAC layer entry points */ |
| #define NGE_DBG_STATS 0x00400000 /* statistics */ |
| |
| #define NGE_DBG_BADIOC 0x01000000 /* unknown ioctls */ |
| |
| #define NGE_DBG_NDD 0x10000000 /* NDD operations */ |
| |
| |
| |
| /* |
| * 'Do-if-debugging' macro. The parameter <command> should be one or more |
| * C statements (but without the *final* semicolon), which will either be |
| * compiled inline or completely ignored, depending on the NGE_DEBUGGING |
| * compile-time flag. |
| * |
| * You should get a compile-time error (at least on a DEBUG build) if |
| * your statement isn't actually a statement, rather than unexpected |
| * run-time behaviour caused by unintended matching of if-then-elses etc. |
| * |
| * Note that the NGE_DDB() macro itself can only be used as a statement, |
| * not an expression, and should always be followed by a semicolon. |
| */ |
| #if NGE_DEBUGGING |
| #define NGE_DDB(command) do { \ |
| { command; } \ |
| _NOTE(CONSTANTCONDITION) \ |
| } while (0) |
| #else /* NGE_DEBUGGING */ |
| #define NGE_DDB(command) |
| /* |
| * Old way of debugging. This is a poor way, as it leeaves empty |
| * statements that cause lint to croak. |
| * #define NGE_DDB(command) do { \ |
| * { _NOTE(EMPTY); } \ |
| * _NOTE(CONSTANTCONDITION) \ |
| * } while (0) |
| */ |
| #endif /* NGE_DEBUGGING */ |
| |
| /* |
| * 'Internal' macros used to construct the TRACE/DEBUG macros below. |
| * These provide the primitive conditional-call capability required. |
| * Note: the parameter <args> is a parenthesised list of the actual |
| * printf-style arguments to be passed to the debug function ... |
| */ |
| #define NGE_XDB(b, w, f, args) NGE_DDB(if ((b) & (w)) f args) |
| #define NGE_GDB(b, args) NGE_XDB(b, nge_debug, (*nge_gdb()), args) |
| #define NGE_LDB(b, args) NGE_XDB(b, ngep->debug, \ |
| (*nge_db(ngep)), args) |
| #define NGE_CDB(f, args) NGE_XDB(NGE_DBG, ngep->debug, f, args) |
| |
| /* |
| * Conditional-print macros. |
| * |
| * Define NGE_DBG to be the relevant member of the set of NGE_DBG_* values |
| * above before using the NGE_GDEBUG() or NGE_DEBUG() macros. The 'G' |
| * versions look at the Global debug flag word (nge_debug); the non-G |
| * versions look in the per-instance data (ngep->debug) and so require a |
| * variable called 'ngep' to be in scope (and initialised!) before use. |
| * |
| * You could redefine NGE_TRC too if you really need two different |
| * flavours of debugging output in the same area of code, but I don't |
| * really recommend it. |
| * |
| * Note: the parameter <args> is a parenthesised list of the actual |
| * arguments to be passed to the debug function, usually a printf-style |
| * format string and corresponding values to be formatted. |
| */ |
| |
| #define NGE_TRC NGE_DBG_TRACE |
| |
| #define NGE_GTRACE(args) NGE_GDB(NGE_TRC, args) |
| #define NGE_GDEBUG(args) NGE_GDB(NGE_DBG, args) |
| #define NGE_TRACE(args) NGE_LDB(NGE_TRC, args) |
| #define NGE_DEBUG(args) NGE_LDB(NGE_DBG, args) |
| |
| /* |
| * Debug-only action macros |
| */ |
| |
| |
| #define NGE_REPORT(args) NGE_DDB(nge_log args) |
| |
| boolean_t nge_atomic_decrease(uint64_t *count_p, uint64_t n); |
| void nge_atomic_increase(uint64_t *count_p, uint64_t n); |
| |
| int nge_alloc_dma_mem(nge_t *ngep, size_t memsize, |
| ddi_device_acc_attr_t *attr_p, uint_t dma_flags, dma_area_t *dma_p); |
| void nge_free_dma_mem(dma_area_t *dma_p); |
| int nge_restart(nge_t *ngep); |
| void nge_wake_factotum(nge_t *ngep); |
| |
| uint8_t nge_reg_get8(nge_t *ngep, nge_regno_t regno); |
| void nge_reg_put8(nge_t *ngep, nge_regno_t regno, uint8_t data); |
| uint16_t nge_reg_get16(nge_t *ngep, nge_regno_t regno); |
| void nge_reg_put16(nge_t *ngep, nge_regno_t regno, uint16_t data); |
| uint32_t nge_reg_get32(nge_t *ngep, nge_regno_t regno); |
| void nge_reg_put32(nge_t *ngep, nge_regno_t regno, uint32_t data); |
| uint_t nge_chip_factotum(caddr_t args1, caddr_t args2); |
| void nge_chip_cfg_init(nge_t *ngep, chip_info_t *infop, boolean_t reset); |
| void nge_init_dev_spec_param(nge_t *ngep); |
| int nge_chip_stop(nge_t *ngep, boolean_t fault); |
| void nge_restore_mac_addr(nge_t *ngep); |
| int nge_chip_reset(nge_t *ngep); |
| int nge_chip_start(nge_t *ngep); |
| void nge_chip_sync(nge_t *ngep); |
| |
| uint_t nge_chip_intr(caddr_t arg1, caddr_t arg2); |
| enum ioc_reply nge_chip_ioctl(nge_t *ngep, mblk_t *mp, struct iocblk *iocp); |
| |
| void nge_phys_init(nge_t *ngep); |
| boolean_t nge_phy_reset(nge_t *ngep); |
| uint16_t nge_mii_get16(nge_t *ngep, nge_regno_t regno); |
| void nge_mii_put16(nge_t *ngep, nge_regno_t regno, uint16_t data); |
| |
| void nge_recv_recycle(caddr_t arg); |
| void nge_receive(nge_t *ngep); |
| |
| uint_t nge_reschedule(caddr_t args1, caddr_t args2); |
| mblk_t *nge_m_tx(void *arg, mblk_t *mp); |
| |
| void nge_tx_recycle(nge_t *ngep, boolean_t is_intr); |
| void nge_tx_recycle_all(nge_t *ngep); |
| |
| int nge_nd_init(nge_t *ngep); |
| void nge_nd_cleanup(nge_t *ngep); |
| |
| |
| void nge_init_kstats(nge_t *ngep, int instance); |
| void nge_fini_kstats(nge_t *ngep); |
| int nge_m_stat(void *arg, uint_t stat, uint64_t *val); |
| |
| uint32_t nge_atomic_shl32(uint32_t *sp, uint_t count); |
| |
| void nge_log(nge_t *ngep, const char *fmt, ...); |
| void nge_problem(nge_t *ngep, const char *fmt, ...); |
| void nge_error(nge_t *ngep, const char *fmt, ...); |
| void |
| nge_report(nge_t *ngep, uint8_t error_id); |
| |
| void (*nge_db(nge_t *ngep))(const char *fmt, ...); |
| void (*nge_gdb(void))(const char *fmt, ...); |
| extern uint32_t nge_debug; |
| |
| /* |
| * DESC MODE 2 |
| */ |
| |
| extern void nge_sum_rxd_fill(void *, const ddi_dma_cookie_t *, size_t); |
| extern uint32_t nge_sum_rxd_check(const void *, size_t *); |
| |
| extern void nge_sum_txd_fill(void *, const ddi_dma_cookie_t *, |
| size_t, uint32_t, boolean_t, boolean_t); |
| extern uint32_t nge_sum_txd_check(const void *); |
| |
| /* |
| * DESC MODE 3 |
| */ |
| |
| extern void nge_hot_rxd_fill(void *, const ddi_dma_cookie_t *, size_t); |
| extern uint32_t nge_hot_rxd_check(const void *, size_t *); |
| |
| extern void nge_hot_txd_fill(void *, const ddi_dma_cookie_t *, |
| size_t, uint32_t, boolean_t, boolean_t); |
| extern uint32_t nge_hot_txd_check(const void *); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* _SYS_NGE_H */ |