15c1d0199Sgd78059 /* 25c1d0199Sgd78059 * CDDL HEADER START 35c1d0199Sgd78059 * 45c1d0199Sgd78059 * The contents of this file are subject to the terms of the 55c1d0199Sgd78059 * Common Development and Distribution License (the "License"). 65c1d0199Sgd78059 * You may not use this file except in compliance with the License. 75c1d0199Sgd78059 * 85c1d0199Sgd78059 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95c1d0199Sgd78059 * or http://www.opensolaris.org/os/licensing. 105c1d0199Sgd78059 * See the License for the specific language governing permissions 115c1d0199Sgd78059 * and limitations under the License. 125c1d0199Sgd78059 * 135c1d0199Sgd78059 * When distributing Covered Code, include this CDDL HEADER in each 145c1d0199Sgd78059 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155c1d0199Sgd78059 * If applicable, add the following below this CDDL HEADER, with the 165c1d0199Sgd78059 * fields enclosed by brackets "[]" replaced with your own identifying 175c1d0199Sgd78059 * information: Portions Copyright [yyyy] [name of copyright owner] 185c1d0199Sgd78059 * 195c1d0199Sgd78059 * CDDL HEADER END 205c1d0199Sgd78059 */ 215c1d0199Sgd78059 /* 22*bdb9230aSGarrett D'Amore * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 235c1d0199Sgd78059 * Use is subject to license terms. 245c1d0199Sgd78059 */ 255c1d0199Sgd78059 265c1d0199Sgd78059 #ifndef _SYS_DMFE_IMPL_H 275c1d0199Sgd78059 #define _SYS_DMFE_IMPL_H 285c1d0199Sgd78059 295c1d0199Sgd78059 #include <sys/types.h> 305c1d0199Sgd78059 #include <sys/stream.h> 315c1d0199Sgd78059 #include <sys/strsun.h> 325c1d0199Sgd78059 #include <sys/stat.h> 335c1d0199Sgd78059 #include <sys/pci.h> 345c1d0199Sgd78059 #include <sys/note.h> 355c1d0199Sgd78059 #include <sys/modctl.h> 365c1d0199Sgd78059 #include <sys/kstat.h> 375c1d0199Sgd78059 #include <sys/ethernet.h> 385c1d0199Sgd78059 #include <sys/devops.h> 395c1d0199Sgd78059 #include <sys/debug.h> 405c1d0199Sgd78059 #include <sys/conf.h> 415c1d0199Sgd78059 425c1d0199Sgd78059 #include <sys/vlan.h> 435c1d0199Sgd78059 445c1d0199Sgd78059 #include <sys/dditypes.h> 455c1d0199Sgd78059 #include <sys/ddi.h> 465c1d0199Sgd78059 #include <sys/sunddi.h> 475c1d0199Sgd78059 48*bdb9230aSGarrett D'Amore #include <sys/mii.h> 49da14cebeSEric Cheng #include <sys/mac_provider.h> 505c1d0199Sgd78059 #include <sys/mac_ether.h> 515c1d0199Sgd78059 #include "dmfe.h" 525c1d0199Sgd78059 535c1d0199Sgd78059 #define DMFE_MAX_PKT_SIZE (VLAN_TAGSZ + ETHERMAX + ETHERFCSL) 545c1d0199Sgd78059 555c1d0199Sgd78059 565c1d0199Sgd78059 #define DRIVER_NAME "dmfe" 575c1d0199Sgd78059 585c1d0199Sgd78059 /* 595c1d0199Sgd78059 * Describes the identity of a specific chip 605c1d0199Sgd78059 */ 615c1d0199Sgd78059 typedef struct { 625c1d0199Sgd78059 uint16_t vendor; 635c1d0199Sgd78059 uint16_t device; 645c1d0199Sgd78059 uint8_t revision; 655c1d0199Sgd78059 uint8_t spare; 665c1d0199Sgd78059 } chip_id_t; 675c1d0199Sgd78059 685c1d0199Sgd78059 /* 695c1d0199Sgd78059 * Describes the state of a descriptor ring 705c1d0199Sgd78059 * 715c1d0199Sgd78059 * NOTE: n_free and next_busy are only used for the Tx descriptors 725c1d0199Sgd78059 * and are not valid on the receive side. 735c1d0199Sgd78059 */ 745c1d0199Sgd78059 typedef struct { 755c1d0199Sgd78059 uint32_t n_desc; /* # of descriptors */ 765c1d0199Sgd78059 uint32_t n_free; /* # of free descriptors */ 775c1d0199Sgd78059 uint32_t next_free; /* next index to use/check */ 785c1d0199Sgd78059 uint32_t next_busy; /* next index to reclaim */ 795c1d0199Sgd78059 } desc_state_t; 805c1d0199Sgd78059 815c1d0199Sgd78059 /* 825c1d0199Sgd78059 * Describes one chunk of allocated DMA-able memory 835c1d0199Sgd78059 */ 845c1d0199Sgd78059 typedef struct { 855c1d0199Sgd78059 ddi_dma_handle_t dma_hdl; 865c1d0199Sgd78059 ddi_acc_handle_t acc_hdl; 875c1d0199Sgd78059 size_t alength; /* allocated size */ 885c1d0199Sgd78059 caddr_t mem_va; /* CPU VA of memory */ 895c1d0199Sgd78059 uint32_t spare1; 905c1d0199Sgd78059 uint32_t mem_dvma; /* DVMA addr of memory */ 915c1d0199Sgd78059 caddr_t setup_va; 925c1d0199Sgd78059 uint32_t spare2; 935c1d0199Sgd78059 uint32_t setup_dvma; 945c1d0199Sgd78059 int spare3; 955c1d0199Sgd78059 int ncookies; 965c1d0199Sgd78059 } dma_area_t; 975c1d0199Sgd78059 985c1d0199Sgd78059 /* 995c1d0199Sgd78059 * Indexes into the driver-specific kstats, divided into: 1005c1d0199Sgd78059 * 1015c1d0199Sgd78059 * cyclic activity 1025c1d0199Sgd78059 * reasons for waking the factotum 1035c1d0199Sgd78059 * the factotum's activities 1045c1d0199Sgd78059 */ 1055c1d0199Sgd78059 enum { 1065c1d0199Sgd78059 KS_CYCLIC_RUN, 1075c1d0199Sgd78059 1085c1d0199Sgd78059 KS_INTERRUPT, 1095c1d0199Sgd78059 KS_TX_STALL, 1105c1d0199Sgd78059 KS_CHIP_ERROR, 1115c1d0199Sgd78059 1125c1d0199Sgd78059 KS_FACTOTUM_RUN, 1135c1d0199Sgd78059 KS_RECOVERY, 1145c1d0199Sgd78059 1155c1d0199Sgd78059 KS_DRV_COUNT 1165c1d0199Sgd78059 }; 1175c1d0199Sgd78059 1185c1d0199Sgd78059 /* 1195c1d0199Sgd78059 * Actual state of the DM9102A chip 1205c1d0199Sgd78059 */ 1215c1d0199Sgd78059 enum chip_state { 1225c1d0199Sgd78059 CHIP_ERROR = -1, /* error, need reset */ 1235c1d0199Sgd78059 CHIP_UNKNOWN, /* Initial state only */ 1245c1d0199Sgd78059 CHIP_RESET, /* reset, need init */ 1255c1d0199Sgd78059 CHIP_STOPPED, /* Tx/Rx stopped */ 1265c1d0199Sgd78059 CHIP_TX_ONLY, /* Tx (re)started */ 1275c1d0199Sgd78059 CHIP_TX_RX, /* Tx & Rx (re)started */ 1285c1d0199Sgd78059 CHIP_RUNNING /* with interrupts */ 1295c1d0199Sgd78059 }; 1305c1d0199Sgd78059 1315c1d0199Sgd78059 /* 1325c1d0199Sgd78059 * Required state according to MAC 1335c1d0199Sgd78059 */ 1345c1d0199Sgd78059 enum mac_state { 1355c1d0199Sgd78059 DMFE_MAC_UNKNOWN, 1365c1d0199Sgd78059 DMFE_MAC_RESET, 1375c1d0199Sgd78059 DMFE_MAC_STOPPED, 1385c1d0199Sgd78059 DMFE_MAC_STARTED 1395c1d0199Sgd78059 }; 1405c1d0199Sgd78059 1415c1d0199Sgd78059 /* 1425c1d0199Sgd78059 * (Internal) return values from ioctl subroutines 1435c1d0199Sgd78059 */ 1445c1d0199Sgd78059 enum ioc_reply { 1455c1d0199Sgd78059 IOC_INVAL = -1, /* bad, NAK with EINVAL */ 1465c1d0199Sgd78059 IOC_DONE, /* OK, reply sent */ 1475c1d0199Sgd78059 IOC_REPLY, /* OK, just send reply */ 1485c1d0199Sgd78059 IOC_ACK, /* OK, just send ACK */ 1495c1d0199Sgd78059 IOC_RESTART, /* OK, restart & reply */ 1505c1d0199Sgd78059 IOC_RESTART_ACK /* OK, restart & ACK */ 1515c1d0199Sgd78059 }; 1525c1d0199Sgd78059 1535c1d0199Sgd78059 /* 1545c1d0199Sgd78059 * Per-instance soft-state structure 1555c1d0199Sgd78059 */ 1565c1d0199Sgd78059 typedef struct dmfe { 1575c1d0199Sgd78059 /* 1585c1d0199Sgd78059 * These fields are set by attach() and unchanged thereafter ... 1595c1d0199Sgd78059 */ 1605c1d0199Sgd78059 dev_info_t *devinfo; /* device instance */ 1615c1d0199Sgd78059 mac_handle_t mh; /* MAC instance data */ 162*bdb9230aSGarrett D'Amore mii_handle_t mii; /* MII handle */ 1635c1d0199Sgd78059 ddi_acc_handle_t io_handle; /* DDI I/O handle */ 1645c1d0199Sgd78059 caddr_t io_reg; /* mapped registers */ 165*bdb9230aSGarrett D'Amore boolean_t suspended; 1665c1d0199Sgd78059 1675c1d0199Sgd78059 uint32_t debug; /* per-instance debug */ 1685c1d0199Sgd78059 uint32_t progress; /* attach tracking */ 1695c1d0199Sgd78059 chip_id_t chipid; 1705c1d0199Sgd78059 uint8_t vendor_addr[ETHERADDRL]; 1715c1d0199Sgd78059 char ifname[12]; /* "dmfeXXXX" */ 1725c1d0199Sgd78059 1735c1d0199Sgd78059 dma_area_t tx_desc; /* transmit descriptors */ 1745c1d0199Sgd78059 dma_area_t tx_buff; /* transmit buffers */ 1755c1d0199Sgd78059 dma_area_t rx_desc; /* receive descriptors */ 1765c1d0199Sgd78059 dma_area_t rx_buff; /* receive buffers */ 1775c1d0199Sgd78059 1785c1d0199Sgd78059 ddi_periodic_t cycid; /* periodical callback */ 1795c1d0199Sgd78059 ddi_softintr_t factotum_id; /* identity of factotum */ 1805c1d0199Sgd78059 ddi_iblock_cookie_t iblk; 1815c1d0199Sgd78059 1825c1d0199Sgd78059 /* 1835c1d0199Sgd78059 * Locks: 1845c1d0199Sgd78059 * 1855c1d0199Sgd78059 * <milock> is used only by the MII (PHY) level code, to ensure 1865c1d0199Sgd78059 * exclusive access during the bit-twiddling needed to send 1875c1d0199Sgd78059 * signals along the MII serial bus. These operations are 1885c1d0199Sgd78059 * --S--L--O--W-- so we keep this lock separate, so that 1895c1d0199Sgd78059 * faster operations (e.g. interrupts) aren't delayed by 1905c1d0199Sgd78059 * waiting for it. 1915c1d0199Sgd78059 * 1925c1d0199Sgd78059 * <oplock> is a general "outer" lock, protecting most r/w data 1935c1d0199Sgd78059 * and chip state. It is also acquired by the interrupt 1945c1d0199Sgd78059 * handler. 1955c1d0199Sgd78059 * 1965c1d0199Sgd78059 * <rxlock> is used to protect the Rx-side buffers, descriptors, 1975c1d0199Sgd78059 * and statistics during a single call to dmfe_getp(). 1985c1d0199Sgd78059 * This is called from inside the interrupt handler, but 1995c1d0199Sgd78059 * <oplock> is not held across this call. 2005c1d0199Sgd78059 * 2015c1d0199Sgd78059 * <txlock> is an "inner" lock, and protects only the Tx-side 2025c1d0199Sgd78059 * data below and in the ring buffers/descriptors. The 2035c1d0199Sgd78059 * Tx-side code uses only this lock, avoiding contention 2045c1d0199Sgd78059 * with the receive-side code. 2055c1d0199Sgd78059 * 2065c1d0199Sgd78059 * Any of the locks can be acquired singly, but where multiple 2075c1d0199Sgd78059 * locks are acquired, they *must* be in the order: 2085c1d0199Sgd78059 * 2095c1d0199Sgd78059 * milock >>> oplock >>> rxlock >>> txlock. 2105c1d0199Sgd78059 * 2115c1d0199Sgd78059 * *None* of these locks may be held across calls out to the 2125c1d0199Sgd78059 * MAC routines mac_rx() or mac_tx_notify(); MAC locks must 2135c1d0199Sgd78059 * be regarded as *outermost* locks in all cases, as they will 2145c1d0199Sgd78059 * already be held before calling the ioctl() or get_stats() 2155c1d0199Sgd78059 * entry points - which then have to acquire multiple locks, in 2165c1d0199Sgd78059 * the order described here. 2175c1d0199Sgd78059 */ 2185c1d0199Sgd78059 kmutex_t milock[1]; 2195c1d0199Sgd78059 kmutex_t oplock[1]; 2205c1d0199Sgd78059 kmutex_t rxlock[1]; 2215c1d0199Sgd78059 kmutex_t txlock[1]; 2225c1d0199Sgd78059 2235c1d0199Sgd78059 /* 2245c1d0199Sgd78059 * DMFE Extended kstats, protected by <oplock> 2255c1d0199Sgd78059 */ 2265c1d0199Sgd78059 kstat_t *ksp_drv; 2275c1d0199Sgd78059 kstat_named_t *knp_drv; 2285c1d0199Sgd78059 2295c1d0199Sgd78059 /* 2305c1d0199Sgd78059 * GLD statistics; the prefix tells which lock each is protected by. 2315c1d0199Sgd78059 */ 2325c1d0199Sgd78059 2335c1d0199Sgd78059 uint64_t rx_stats_ipackets; 2345c1d0199Sgd78059 uint64_t rx_stats_multi; 2355c1d0199Sgd78059 uint64_t rx_stats_bcast; 2365c1d0199Sgd78059 uint64_t rx_stats_ierrors; 2375c1d0199Sgd78059 uint64_t rx_stats_norcvbuf; 2385c1d0199Sgd78059 uint64_t rx_stats_rbytes; 2395c1d0199Sgd78059 uint64_t rx_stats_missed; 2405c1d0199Sgd78059 uint64_t rx_stats_align; 2415c1d0199Sgd78059 uint64_t rx_stats_fcs; 2425c1d0199Sgd78059 uint64_t rx_stats_toolong; 2435c1d0199Sgd78059 uint64_t rx_stats_macrcv_errors; 2445c1d0199Sgd78059 uint64_t rx_stats_overflow; 2455c1d0199Sgd78059 uint64_t rx_stats_short; 2465c1d0199Sgd78059 2475c1d0199Sgd78059 uint64_t tx_stats_oerrors; 2485c1d0199Sgd78059 uint64_t tx_stats_opackets; 2495c1d0199Sgd78059 uint64_t tx_stats_multi; 2505c1d0199Sgd78059 uint64_t tx_stats_bcast; 2515c1d0199Sgd78059 uint64_t tx_stats_obytes; 2525c1d0199Sgd78059 uint64_t tx_stats_collisions; 2535c1d0199Sgd78059 uint64_t tx_stats_nocarrier; 2545c1d0199Sgd78059 uint64_t tx_stats_xmtlatecoll; 2555c1d0199Sgd78059 uint64_t tx_stats_excoll; 2565c1d0199Sgd78059 uint64_t tx_stats_macxmt_errors; 2575c1d0199Sgd78059 uint64_t tx_stats_jabber; 2585c1d0199Sgd78059 uint64_t tx_stats_defer; 2595c1d0199Sgd78059 uint64_t tx_stats_first_coll; 2605c1d0199Sgd78059 uint64_t tx_stats_multi_coll; 2615c1d0199Sgd78059 uint64_t tx_stats_underflow; 2625c1d0199Sgd78059 2635c1d0199Sgd78059 /* 2645c1d0199Sgd78059 * These two sets of desciptors are manipulated during 2655c1d0199Sgd78059 * packet receive/transmit respectively. 2665c1d0199Sgd78059 */ 2675c1d0199Sgd78059 desc_state_t rx; /* describes Rx ring */ 2685c1d0199Sgd78059 desc_state_t tx; /* describes Tx ring */ 2695c1d0199Sgd78059 2705c1d0199Sgd78059 /* 2715c1d0199Sgd78059 * Miscellaneous Tx-side variables (protected by txlock) 2725c1d0199Sgd78059 */ 2735c1d0199Sgd78059 uint32_t tx_pending_tix; /* tix since reclaim */ 2745c1d0199Sgd78059 uint8_t *tx_mcast; /* bitmask: pkt is mcast */ 2755c1d0199Sgd78059 uint8_t *tx_bcast; /* bitmask: pkt is bcast */ 2765c1d0199Sgd78059 2775c1d0199Sgd78059 /* 2785c1d0199Sgd78059 * Miscellaneous operating variables (protected by oplock) 2795c1d0199Sgd78059 */ 2805c1d0199Sgd78059 uint16_t factotum_flag; /* callback pending */ 2815c1d0199Sgd78059 uint16_t need_setup; /* send-setup pending */ 2825c1d0199Sgd78059 uint32_t opmode; /* operating mode shadow */ 2835c1d0199Sgd78059 uint32_t imask; /* interrupt mask shadow */ 2845c1d0199Sgd78059 enum mac_state mac_state; /* RESET/STOPPED/STARTED */ 2855c1d0199Sgd78059 enum chip_state chip_state; /* see above */ 2865c1d0199Sgd78059 2875c1d0199Sgd78059 /* 2885c1d0199Sgd78059 * Current Ethernet address & multicast map ... 2895c1d0199Sgd78059 */ 2905c1d0199Sgd78059 uint8_t curr_addr[ETHERADDRL]; 2915c1d0199Sgd78059 uint8_t mcast_refs[MCASTBUF_SIZE]; 2925c1d0199Sgd78059 boolean_t addr_set; 2935c1d0199Sgd78059 2945c1d0199Sgd78059 /* 2955c1d0199Sgd78059 * Guard element used to check data integrity 2965c1d0199Sgd78059 */ 2975c1d0199Sgd78059 uint64_t dmfe_guard; 2985c1d0199Sgd78059 } dmfe_t; 2995c1d0199Sgd78059 3005c1d0199Sgd78059 /* 3015c1d0199Sgd78059 * 'Progress' bit flags ... 3025c1d0199Sgd78059 */ 3035c1d0199Sgd78059 #define PROGRESS_CONFIG 0x0001 /* config space initialised */ 304*bdb9230aSGarrett D'Amore #define PROGRESS_MUTEX 0x0002 /* mutexes initialized */ 3055c1d0199Sgd78059 #define PROGRESS_REGS 0x0004 /* registers mapped */ 3065c1d0199Sgd78059 #define PROGRESS_BUFS 0x0008 /* buffers allocated */ 3075c1d0199Sgd78059 #define PROGRESS_SOFTINT 0x0010 /* softint registered */ 3085c1d0199Sgd78059 #define PROGRESS_HWINT 0x0020 /* h/w interrupt registered */ 3095c1d0199Sgd78059 3105c1d0199Sgd78059 /* 3115c1d0199Sgd78059 * Sync a DMA area described by a dma_area_t 3125c1d0199Sgd78059 */ 3135c1d0199Sgd78059 #define DMA_SYNC(descp, flag) ((void) ddi_dma_sync((descp)->dma_hdl, \ 3145c1d0199Sgd78059 0, (descp)->alength, flag)) 3155c1d0199Sgd78059 3165c1d0199Sgd78059 /* 3175c1d0199Sgd78059 * Next value of a cyclic index 3185c1d0199Sgd78059 */ 3195c1d0199Sgd78059 #define NEXT(index, limit) ((index)+1 < (limit) ? (index)+1 : 0); 3205c1d0199Sgd78059 3215c1d0199Sgd78059 /* 3225c1d0199Sgd78059 * Copy an ethernet address 3235c1d0199Sgd78059 */ 3245c1d0199Sgd78059 #define ethaddr_copy(src, dst) bcopy((src), (dst), ETHERADDRL) 3255c1d0199Sgd78059 3265c1d0199Sgd78059 /* 3275c1d0199Sgd78059 * Get/set/increment a (64-bit) driver-private kstat 3285c1d0199Sgd78059 */ 3295c1d0199Sgd78059 #define DRV_KS_GET(dmfep, id) \ 3305c1d0199Sgd78059 (((dmfep)->knp_drv) ? ((dmfep)->knp_drv)[id].value.ui64 : 0) 3315c1d0199Sgd78059 3325c1d0199Sgd78059 #define DRV_KS_SET(dmfep, id, val) \ 3335c1d0199Sgd78059 do { \ 3345c1d0199Sgd78059 if ((dmfep)->knp_drv) \ 3355c1d0199Sgd78059 ((dmfep)->knp_drv)[id].value.ui64 = (val); \ 3365c1d0199Sgd78059 _NOTE(CONSTANTCONDITION) \ 3375c1d0199Sgd78059 } while (0) 3385c1d0199Sgd78059 3395c1d0199Sgd78059 #define DRV_KS_INC(dmfep, id) \ 3405c1d0199Sgd78059 do { \ 3415c1d0199Sgd78059 if ((dmfep)->knp_drv) \ 3425c1d0199Sgd78059 ((dmfep)->knp_drv)[id].value.ui64 += 1; \ 3435c1d0199Sgd78059 _NOTE(CONSTANTCONDITION) \ 3445c1d0199Sgd78059 } while (0) 3455c1d0199Sgd78059 3465c1d0199Sgd78059 3475c1d0199Sgd78059 #define DMFE_GUARD 0x1919603003090218 3485c1d0199Sgd78059 3495c1d0199Sgd78059 /* 3505c1d0199Sgd78059 * Inter-source-file linkage ... 3515c1d0199Sgd78059 */ 3525c1d0199Sgd78059 3535c1d0199Sgd78059 /* dmfe_log.c */ 3545c1d0199Sgd78059 void dmfe_warning(dmfe_t *dmfep, const char *fmt, ...); 3555c1d0199Sgd78059 void dmfe_error(dmfe_t *dmfep, const char *fmt, ...); 3565c1d0199Sgd78059 void dmfe_notice(dmfe_t *dmfep, const char *fmt, ...); 3575c1d0199Sgd78059 void dmfe_log(dmfe_t *dmfep, const char *fmt, ...); 3585c1d0199Sgd78059 void dmfe_log_init(void); 3595c1d0199Sgd78059 void dmfe_log_fini(void); 3605c1d0199Sgd78059 3615c1d0199Sgd78059 /* dmfe_main.c */ 3625c1d0199Sgd78059 uint32_t dmfe_chip_get32(dmfe_t *dmfep, off_t offset); 3635c1d0199Sgd78059 void dmfe_chip_put32(dmfe_t *dmfep, off_t offset, uint32_t value); 3645c1d0199Sgd78059 3655c1d0199Sgd78059 /* dmfe_mii.c */ 3665c1d0199Sgd78059 void dmfe_read_eeprom(dmfe_t *dmfep, uint16_t addr, uint8_t *ptr, int cnt); 3675c1d0199Sgd78059 boolean_t dmfe_init_phy(dmfe_t *dmfep); 3685c1d0199Sgd78059 3695c1d0199Sgd78059 #endif /* _SYS_DMFE_IMPL_H */ 370