/* * 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 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_NGE_H #define _SYS_NGE_H #pragma ident "%Z%%M% %I% %E% SMI" #ifdef __cplusplus extern "C" { #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Reconfiguring the network devices requires the net_config privilege * in Solaris 10+. */ extern int secpolicy_net_config(const cred_t *, boolean_t); #include #include #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_HALFTICK 268435456LL /* 2**28 ns! */ #define NGE_CYCLIC_PERIOD (4*NGE_HALFTICK) /* ~0.5s */ #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_POLL_QUIET_TIME 100 #define NGE_POLL_BUSY_TIME 2 #define NGE_TX_N_INTR 128 /* * 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 * 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 */ uint64_t tx_hwmark; uint64_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 */ uint64_t tx_next; /* next slot to use */ uint64_t tx_flow; /* * These counters/indexes are manipulated in the transmit * path using atomics rather than mutexes for speed */ uint64_t tx_free; /* # of slots available */ /* * index (tc_next). */ kmutex_t tc_lock[1]; uint64_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); uint32_t (*txd_check)(const void *, size_t *); }; 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 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 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; uint32_t stint_count; 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; int param_tx_n_intr; } 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 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 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 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); extern uint32_t nge_sum_txd_check(const void *, size_t *); /* * 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); extern uint32_t nge_hot_txd_check(const void *, size_t *); #ifdef __cplusplus } #endif #endif /* _SYS_NGE_H */