xref: /onnv-gate/usr/src/uts/common/io/dmfe/dmfe_impl.h (revision 9860:20e31304c39b)
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