15181Sgd78059 /* 25181Sgd78059 * CDDL HEADER START 35181Sgd78059 * 45181Sgd78059 * The contents of this file are subject to the terms of the 55181Sgd78059 * Common Development and Distribution License (the "License"). 65181Sgd78059 * You may not use this file except in compliance with the License. 75181Sgd78059 * 85181Sgd78059 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95181Sgd78059 * or http://www.opensolaris.org/os/licensing. 105181Sgd78059 * See the License for the specific language governing permissions 115181Sgd78059 * and limitations under the License. 125181Sgd78059 * 135181Sgd78059 * When distributing Covered Code, include this CDDL HEADER in each 145181Sgd78059 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155181Sgd78059 * If applicable, add the following below this CDDL HEADER, with the 165181Sgd78059 * fields enclosed by brackets "[]" replaced with your own identifying 175181Sgd78059 * information: Portions Copyright [yyyy] [name of copyright owner] 185181Sgd78059 * 195181Sgd78059 * CDDL HEADER END 205181Sgd78059 */ 215181Sgd78059 /* 22*9860Sgdamore@opensolaris.org * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 235181Sgd78059 * Use is subject to license terms. 245181Sgd78059 */ 255181Sgd78059 265181Sgd78059 #ifndef _SYS_DMFE_IMPL_H 275181Sgd78059 #define _SYS_DMFE_IMPL_H 285181Sgd78059 295181Sgd78059 #include <sys/types.h> 305181Sgd78059 #include <sys/stream.h> 315181Sgd78059 #include <sys/strsun.h> 325181Sgd78059 #include <sys/stat.h> 335181Sgd78059 #include <sys/pci.h> 345181Sgd78059 #include <sys/note.h> 355181Sgd78059 #include <sys/modctl.h> 365181Sgd78059 #include <sys/kstat.h> 375181Sgd78059 #include <sys/ethernet.h> 385181Sgd78059 #include <sys/devops.h> 395181Sgd78059 #include <sys/debug.h> 405181Sgd78059 #include <sys/conf.h> 415181Sgd78059 425181Sgd78059 #include <sys/vlan.h> 435181Sgd78059 445181Sgd78059 #include <sys/dditypes.h> 455181Sgd78059 #include <sys/ddi.h> 465181Sgd78059 #include <sys/sunddi.h> 475181Sgd78059 48*9860Sgdamore@opensolaris.org #include <sys/mii.h> 498275SEric Cheng #include <sys/mac_provider.h> 505181Sgd78059 #include <sys/mac_ether.h> 515181Sgd78059 #include "dmfe.h" 525181Sgd78059 535181Sgd78059 #define DMFE_MAX_PKT_SIZE (VLAN_TAGSZ + ETHERMAX + ETHERFCSL) 545181Sgd78059 555181Sgd78059 565181Sgd78059 #define DRIVER_NAME "dmfe" 575181Sgd78059 585181Sgd78059 /* 595181Sgd78059 * Describes the identity of a specific chip 605181Sgd78059 */ 615181Sgd78059 typedef struct { 625181Sgd78059 uint16_t vendor; 635181Sgd78059 uint16_t device; 645181Sgd78059 uint8_t revision; 655181Sgd78059 uint8_t spare; 665181Sgd78059 } chip_id_t; 675181Sgd78059 685181Sgd78059 /* 695181Sgd78059 * Describes the state of a descriptor ring 705181Sgd78059 * 715181Sgd78059 * NOTE: n_free and next_busy are only used for the Tx descriptors 725181Sgd78059 * and are not valid on the receive side. 735181Sgd78059 */ 745181Sgd78059 typedef struct { 755181Sgd78059 uint32_t n_desc; /* # of descriptors */ 765181Sgd78059 uint32_t n_free; /* # of free descriptors */ 775181Sgd78059 uint32_t next_free; /* next index to use/check */ 785181Sgd78059 uint32_t next_busy; /* next index to reclaim */ 795181Sgd78059 } desc_state_t; 805181Sgd78059 815181Sgd78059 /* 825181Sgd78059 * Describes one chunk of allocated DMA-able memory 835181Sgd78059 */ 845181Sgd78059 typedef struct { 855181Sgd78059 ddi_dma_handle_t dma_hdl; 865181Sgd78059 ddi_acc_handle_t acc_hdl; 875181Sgd78059 size_t alength; /* allocated size */ 885181Sgd78059 caddr_t mem_va; /* CPU VA of memory */ 895181Sgd78059 uint32_t spare1; 905181Sgd78059 uint32_t mem_dvma; /* DVMA addr of memory */ 915181Sgd78059 caddr_t setup_va; 925181Sgd78059 uint32_t spare2; 935181Sgd78059 uint32_t setup_dvma; 945181Sgd78059 int spare3; 955181Sgd78059 int ncookies; 965181Sgd78059 } dma_area_t; 975181Sgd78059 985181Sgd78059 /* 995181Sgd78059 * Indexes into the driver-specific kstats, divided into: 1005181Sgd78059 * 1015181Sgd78059 * cyclic activity 1025181Sgd78059 * reasons for waking the factotum 1035181Sgd78059 * the factotum's activities 1045181Sgd78059 */ 1055181Sgd78059 enum { 1065181Sgd78059 KS_CYCLIC_RUN, 1075181Sgd78059 1085181Sgd78059 KS_INTERRUPT, 1095181Sgd78059 KS_TX_STALL, 1105181Sgd78059 KS_CHIP_ERROR, 1115181Sgd78059 1125181Sgd78059 KS_FACTOTUM_RUN, 1135181Sgd78059 KS_RECOVERY, 1145181Sgd78059 1155181Sgd78059 KS_DRV_COUNT 1165181Sgd78059 }; 1175181Sgd78059 1185181Sgd78059 /* 1195181Sgd78059 * Actual state of the DM9102A chip 1205181Sgd78059 */ 1215181Sgd78059 enum chip_state { 1225181Sgd78059 CHIP_ERROR = -1, /* error, need reset */ 1235181Sgd78059 CHIP_UNKNOWN, /* Initial state only */ 1245181Sgd78059 CHIP_RESET, /* reset, need init */ 1255181Sgd78059 CHIP_STOPPED, /* Tx/Rx stopped */ 1265181Sgd78059 CHIP_TX_ONLY, /* Tx (re)started */ 1275181Sgd78059 CHIP_TX_RX, /* Tx & Rx (re)started */ 1285181Sgd78059 CHIP_RUNNING /* with interrupts */ 1295181Sgd78059 }; 1305181Sgd78059 1315181Sgd78059 /* 1325181Sgd78059 * Required state according to MAC 1335181Sgd78059 */ 1345181Sgd78059 enum mac_state { 1355181Sgd78059 DMFE_MAC_UNKNOWN, 1365181Sgd78059 DMFE_MAC_RESET, 1375181Sgd78059 DMFE_MAC_STOPPED, 1385181Sgd78059 DMFE_MAC_STARTED 1395181Sgd78059 }; 1405181Sgd78059 1415181Sgd78059 /* 1425181Sgd78059 * (Internal) return values from ioctl subroutines 1435181Sgd78059 */ 1445181Sgd78059 enum ioc_reply { 1455181Sgd78059 IOC_INVAL = -1, /* bad, NAK with EINVAL */ 1465181Sgd78059 IOC_DONE, /* OK, reply sent */ 1475181Sgd78059 IOC_REPLY, /* OK, just send reply */ 1485181Sgd78059 IOC_ACK, /* OK, just send ACK */ 1495181Sgd78059 IOC_RESTART, /* OK, restart & reply */ 1505181Sgd78059 IOC_RESTART_ACK /* OK, restart & ACK */ 1515181Sgd78059 }; 1525181Sgd78059 1535181Sgd78059 /* 1545181Sgd78059 * Per-instance soft-state structure 1555181Sgd78059 */ 1565181Sgd78059 typedef struct dmfe { 1575181Sgd78059 /* 1585181Sgd78059 * These fields are set by attach() and unchanged thereafter ... 1595181Sgd78059 */ 1605181Sgd78059 dev_info_t *devinfo; /* device instance */ 1615181Sgd78059 mac_handle_t mh; /* MAC instance data */ 162*9860Sgdamore@opensolaris.org mii_handle_t mii; /* MII handle */ 1635181Sgd78059 ddi_acc_handle_t io_handle; /* DDI I/O handle */ 1645181Sgd78059 caddr_t io_reg; /* mapped registers */ 165*9860Sgdamore@opensolaris.org boolean_t suspended; 1665181Sgd78059 1675181Sgd78059 uint32_t debug; /* per-instance debug */ 1685181Sgd78059 uint32_t progress; /* attach tracking */ 1695181Sgd78059 chip_id_t chipid; 1705181Sgd78059 uint8_t vendor_addr[ETHERADDRL]; 1715181Sgd78059 char ifname[12]; /* "dmfeXXXX" */ 1725181Sgd78059 1735181Sgd78059 dma_area_t tx_desc; /* transmit descriptors */ 1745181Sgd78059 dma_area_t tx_buff; /* transmit buffers */ 1755181Sgd78059 dma_area_t rx_desc; /* receive descriptors */ 1765181Sgd78059 dma_area_t rx_buff; /* receive buffers */ 1775181Sgd78059 1785181Sgd78059 ddi_periodic_t cycid; /* periodical callback */ 1795181Sgd78059 ddi_softintr_t factotum_id; /* identity of factotum */ 1805181Sgd78059 ddi_iblock_cookie_t iblk; 1815181Sgd78059 1825181Sgd78059 /* 1835181Sgd78059 * Locks: 1845181Sgd78059 * 1855181Sgd78059 * <milock> is used only by the MII (PHY) level code, to ensure 1865181Sgd78059 * exclusive access during the bit-twiddling needed to send 1875181Sgd78059 * signals along the MII serial bus. These operations are 1885181Sgd78059 * --S--L--O--W-- so we keep this lock separate, so that 1895181Sgd78059 * faster operations (e.g. interrupts) aren't delayed by 1905181Sgd78059 * waiting for it. 1915181Sgd78059 * 1925181Sgd78059 * <oplock> is a general "outer" lock, protecting most r/w data 1935181Sgd78059 * and chip state. It is also acquired by the interrupt 1945181Sgd78059 * handler. 1955181Sgd78059 * 1965181Sgd78059 * <rxlock> is used to protect the Rx-side buffers, descriptors, 1975181Sgd78059 * and statistics during a single call to dmfe_getp(). 1985181Sgd78059 * This is called from inside the interrupt handler, but 1995181Sgd78059 * <oplock> is not held across this call. 2005181Sgd78059 * 2015181Sgd78059 * <txlock> is an "inner" lock, and protects only the Tx-side 2025181Sgd78059 * data below and in the ring buffers/descriptors. The 2035181Sgd78059 * Tx-side code uses only this lock, avoiding contention 2045181Sgd78059 * with the receive-side code. 2055181Sgd78059 * 2065181Sgd78059 * Any of the locks can be acquired singly, but where multiple 2075181Sgd78059 * locks are acquired, they *must* be in the order: 2085181Sgd78059 * 2095181Sgd78059 * milock >>> oplock >>> rxlock >>> txlock. 2105181Sgd78059 * 2115181Sgd78059 * *None* of these locks may be held across calls out to the 2125181Sgd78059 * MAC routines mac_rx() or mac_tx_notify(); MAC locks must 2135181Sgd78059 * be regarded as *outermost* locks in all cases, as they will 2145181Sgd78059 * already be held before calling the ioctl() or get_stats() 2155181Sgd78059 * entry points - which then have to acquire multiple locks, in 2165181Sgd78059 * the order described here. 2175181Sgd78059 */ 2185181Sgd78059 kmutex_t milock[1]; 2195181Sgd78059 kmutex_t oplock[1]; 2205181Sgd78059 kmutex_t rxlock[1]; 2215181Sgd78059 kmutex_t txlock[1]; 2225181Sgd78059 2235181Sgd78059 /* 2245181Sgd78059 * DMFE Extended kstats, protected by <oplock> 2255181Sgd78059 */ 2265181Sgd78059 kstat_t *ksp_drv; 2275181Sgd78059 kstat_named_t *knp_drv; 2285181Sgd78059 2295181Sgd78059 /* 2305181Sgd78059 * GLD statistics; the prefix tells which lock each is protected by. 2315181Sgd78059 */ 2325181Sgd78059 2335181Sgd78059 uint64_t rx_stats_ipackets; 2345181Sgd78059 uint64_t rx_stats_multi; 2355181Sgd78059 uint64_t rx_stats_bcast; 2365181Sgd78059 uint64_t rx_stats_ierrors; 2375181Sgd78059 uint64_t rx_stats_norcvbuf; 2385181Sgd78059 uint64_t rx_stats_rbytes; 2395181Sgd78059 uint64_t rx_stats_missed; 2405181Sgd78059 uint64_t rx_stats_align; 2415181Sgd78059 uint64_t rx_stats_fcs; 2425181Sgd78059 uint64_t rx_stats_toolong; 2435181Sgd78059 uint64_t rx_stats_macrcv_errors; 2445181Sgd78059 uint64_t rx_stats_overflow; 2455181Sgd78059 uint64_t rx_stats_short; 2465181Sgd78059 2475181Sgd78059 uint64_t tx_stats_oerrors; 2485181Sgd78059 uint64_t tx_stats_opackets; 2495181Sgd78059 uint64_t tx_stats_multi; 2505181Sgd78059 uint64_t tx_stats_bcast; 2515181Sgd78059 uint64_t tx_stats_obytes; 2525181Sgd78059 uint64_t tx_stats_collisions; 2535181Sgd78059 uint64_t tx_stats_nocarrier; 2545181Sgd78059 uint64_t tx_stats_xmtlatecoll; 2555181Sgd78059 uint64_t tx_stats_excoll; 2565181Sgd78059 uint64_t tx_stats_macxmt_errors; 2575181Sgd78059 uint64_t tx_stats_jabber; 2585181Sgd78059 uint64_t tx_stats_defer; 2595181Sgd78059 uint64_t tx_stats_first_coll; 2605181Sgd78059 uint64_t tx_stats_multi_coll; 2615181Sgd78059 uint64_t tx_stats_underflow; 2625181Sgd78059 2635181Sgd78059 /* 2645181Sgd78059 * These two sets of desciptors are manipulated during 2655181Sgd78059 * packet receive/transmit respectively. 2665181Sgd78059 */ 2675181Sgd78059 desc_state_t rx; /* describes Rx ring */ 2685181Sgd78059 desc_state_t tx; /* describes Tx ring */ 2695181Sgd78059 2705181Sgd78059 /* 2715181Sgd78059 * Miscellaneous Tx-side variables (protected by txlock) 2725181Sgd78059 */ 2735181Sgd78059 uint32_t tx_pending_tix; /* tix since reclaim */ 2745181Sgd78059 uint8_t *tx_mcast; /* bitmask: pkt is mcast */ 2755181Sgd78059 uint8_t *tx_bcast; /* bitmask: pkt is bcast */ 2765181Sgd78059 2775181Sgd78059 /* 2785181Sgd78059 * Miscellaneous operating variables (protected by oplock) 2795181Sgd78059 */ 2805181Sgd78059 uint16_t factotum_flag; /* callback pending */ 2815181Sgd78059 uint16_t need_setup; /* send-setup pending */ 2825181Sgd78059 uint32_t opmode; /* operating mode shadow */ 2835181Sgd78059 uint32_t imask; /* interrupt mask shadow */ 2845181Sgd78059 enum mac_state mac_state; /* RESET/STOPPED/STARTED */ 2855181Sgd78059 enum chip_state chip_state; /* see above */ 2865181Sgd78059 2875181Sgd78059 /* 2885181Sgd78059 * Current Ethernet address & multicast map ... 2895181Sgd78059 */ 2905181Sgd78059 uint8_t curr_addr[ETHERADDRL]; 2915181Sgd78059 uint8_t mcast_refs[MCASTBUF_SIZE]; 2925181Sgd78059 boolean_t addr_set; 2935181Sgd78059 2945181Sgd78059 /* 2955181Sgd78059 * Guard element used to check data integrity 2965181Sgd78059 */ 2975181Sgd78059 uint64_t dmfe_guard; 2985181Sgd78059 } dmfe_t; 2995181Sgd78059 3005181Sgd78059 /* 3015181Sgd78059 * 'Progress' bit flags ... 3025181Sgd78059 */ 3035181Sgd78059 #define PROGRESS_CONFIG 0x0001 /* config space initialised */ 304*9860Sgdamore@opensolaris.org #define PROGRESS_MUTEX 0x0002 /* mutexes initialized */ 3055181Sgd78059 #define PROGRESS_REGS 0x0004 /* registers mapped */ 3065181Sgd78059 #define PROGRESS_BUFS 0x0008 /* buffers allocated */ 3075181Sgd78059 #define PROGRESS_SOFTINT 0x0010 /* softint registered */ 3085181Sgd78059 #define PROGRESS_HWINT 0x0020 /* h/w interrupt registered */ 3095181Sgd78059 3105181Sgd78059 /* 3115181Sgd78059 * Sync a DMA area described by a dma_area_t 3125181Sgd78059 */ 3135181Sgd78059 #define DMA_SYNC(descp, flag) ((void) ddi_dma_sync((descp)->dma_hdl, \ 3145181Sgd78059 0, (descp)->alength, flag)) 3155181Sgd78059 3165181Sgd78059 /* 3175181Sgd78059 * Next value of a cyclic index 3185181Sgd78059 */ 3195181Sgd78059 #define NEXT(index, limit) ((index)+1 < (limit) ? (index)+1 : 0); 3205181Sgd78059 3215181Sgd78059 /* 3225181Sgd78059 * Copy an ethernet address 3235181Sgd78059 */ 3245181Sgd78059 #define ethaddr_copy(src, dst) bcopy((src), (dst), ETHERADDRL) 3255181Sgd78059 3265181Sgd78059 /* 3275181Sgd78059 * Get/set/increment a (64-bit) driver-private kstat 3285181Sgd78059 */ 3295181Sgd78059 #define DRV_KS_GET(dmfep, id) \ 3305181Sgd78059 (((dmfep)->knp_drv) ? ((dmfep)->knp_drv)[id].value.ui64 : 0) 3315181Sgd78059 3325181Sgd78059 #define DRV_KS_SET(dmfep, id, val) \ 3335181Sgd78059 do { \ 3345181Sgd78059 if ((dmfep)->knp_drv) \ 3355181Sgd78059 ((dmfep)->knp_drv)[id].value.ui64 = (val); \ 3365181Sgd78059 _NOTE(CONSTANTCONDITION) \ 3375181Sgd78059 } while (0) 3385181Sgd78059 3395181Sgd78059 #define DRV_KS_INC(dmfep, id) \ 3405181Sgd78059 do { \ 3415181Sgd78059 if ((dmfep)->knp_drv) \ 3425181Sgd78059 ((dmfep)->knp_drv)[id].value.ui64 += 1; \ 3435181Sgd78059 _NOTE(CONSTANTCONDITION) \ 3445181Sgd78059 } while (0) 3455181Sgd78059 3465181Sgd78059 3475181Sgd78059 #define DMFE_GUARD 0x1919603003090218 3485181Sgd78059 3495181Sgd78059 /* 3505181Sgd78059 * Inter-source-file linkage ... 3515181Sgd78059 */ 3525181Sgd78059 3535181Sgd78059 /* dmfe_log.c */ 3545181Sgd78059 void dmfe_warning(dmfe_t *dmfep, const char *fmt, ...); 3555181Sgd78059 void dmfe_error(dmfe_t *dmfep, const char *fmt, ...); 3565181Sgd78059 void dmfe_notice(dmfe_t *dmfep, const char *fmt, ...); 3575181Sgd78059 void dmfe_log(dmfe_t *dmfep, const char *fmt, ...); 3585181Sgd78059 void dmfe_log_init(void); 3595181Sgd78059 void dmfe_log_fini(void); 3605181Sgd78059 3615181Sgd78059 /* dmfe_main.c */ 3625181Sgd78059 uint32_t dmfe_chip_get32(dmfe_t *dmfep, off_t offset); 3635181Sgd78059 void dmfe_chip_put32(dmfe_t *dmfep, off_t offset, uint32_t value); 3645181Sgd78059 3655181Sgd78059 /* dmfe_mii.c */ 3665181Sgd78059 void dmfe_read_eeprom(dmfe_t *dmfep, uint16_t addr, uint8_t *ptr, int cnt); 3675181Sgd78059 boolean_t dmfe_init_phy(dmfe_t *dmfep); 3685181Sgd78059 3695181Sgd78059 #endif /* _SYS_DMFE_IMPL_H */ 370