166f9d5cbSmlf /*
266f9d5cbSmlf  * CDDL HEADER START
366f9d5cbSmlf  *
466f9d5cbSmlf  * The contents of this file are subject to the terms of the
566f9d5cbSmlf  * Common Development and Distribution License (the "License").
666f9d5cbSmlf  * You may not use this file except in compliance with the License.
766f9d5cbSmlf  *
866f9d5cbSmlf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
966f9d5cbSmlf  * or http://www.opensolaris.org/os/licensing.
1066f9d5cbSmlf  * See the License for the specific language governing permissions
1166f9d5cbSmlf  * and limitations under the License.
1266f9d5cbSmlf  *
1366f9d5cbSmlf  * When distributing Covered Code, include this CDDL HEADER in each
1466f9d5cbSmlf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1566f9d5cbSmlf  * If applicable, add the following below this CDDL HEADER, with the
1666f9d5cbSmlf  * fields enclosed by brackets "[]" replaced with your own identifying
1766f9d5cbSmlf  * information: Portions Copyright [yyyy] [name of copyright owner]
1866f9d5cbSmlf  *
1966f9d5cbSmlf  * CDDL HEADER END
2066f9d5cbSmlf  */
2166f9d5cbSmlf 
2266f9d5cbSmlf /*
23ab0d082fSMark Logan  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
2466f9d5cbSmlf  */
2566f9d5cbSmlf 
2666f9d5cbSmlf #ifndef _SI3124VAR_H
2766f9d5cbSmlf #define	_SI3124VAR_H
2866f9d5cbSmlf 
2966f9d5cbSmlf #ifdef	__cplusplus
3066f9d5cbSmlf extern "C" {
3166f9d5cbSmlf #endif
3266f9d5cbSmlf 
3366f9d5cbSmlf #define	SI3124_MAX_PORTS		4
3466f9d5cbSmlf #define	SI3132_MAX_PORTS		2
35*b74cec98SCharles Stephens #define	SI3531_MAX_PORTS		1
3666f9d5cbSmlf #define	SI_MAX_PORTS			SI3124_MAX_PORTS
3766f9d5cbSmlf 
38e57ece5bSPraveen Kumar Dasaraju Rama #define	SI_LOGBUF_LEN			512
39e57ece5bSPraveen Kumar Dasaraju Rama 
4066f9d5cbSmlf #define	SI_SUCCESS			(0)	/* successful return */
4166f9d5cbSmlf #define	SI_TIMEOUT			(1)	/* timed out */
4266f9d5cbSmlf #define	SI_FAILURE			(-1)	/* unsuccessful return */
4366f9d5cbSmlf 
4481a0678eSxun ni - Sun Microsystems - Beijing China #define	SI_MAX_SGT_TABLES_PER_PRB	21844
4581a0678eSxun ni - Sun Microsystems - Beijing China #define	SI_DEFAULT_SGT_TABLES_PER_PRB	85
4681a0678eSxun ni - Sun Microsystems - Beijing China #define	SI_MIN_SGT_TABLES_PER_PRB	1
4766f9d5cbSmlf /*
4866f9d5cbSmlf  * While the si_sge_t and si_sgt_t correspond to the actual SGE and SGT
4966f9d5cbSmlf  * definitions as per the datasheet, the si_sgblock_t (i.e scatter gather
5081a0678eSxun ni - Sun Microsystems - Beijing China  * block) is a logical data structure which can hold dynamic SGEs and it
5181a0678eSxun ni - Sun Microsystems - Beijing China  * is tunable through global variables /etc/system si3124:si_dma_sg_number.
5281a0678eSxun ni - Sun Microsystems - Beijing China  * The idea is to use multiple tunable chained SGT tables per each PRB request.
5366f9d5cbSmlf  */
5466f9d5cbSmlf 
5566f9d5cbSmlf typedef struct si_sgblock {
5681a0678eSxun ni - Sun Microsystems - Beijing China 	si_sgt_t sgb_sgt[1];
5766f9d5cbSmlf } si_sgblock_t;
5866f9d5cbSmlf 
5966f9d5cbSmlf /*
6066f9d5cbSmlf  * Each SGT (Scatter Gather Table) has 4 SGEs (Scatter Gather Entries).
6166f9d5cbSmlf  * But each SGT effectively can host only 3 SGEs since the last SGE entry
6266f9d5cbSmlf  * is used to hold a link to the next SGT in the chain. However the last
6366f9d5cbSmlf  * SGT in the chain can host all the 4 entries since it does not need to
6466f9d5cbSmlf  * link any more.
6566f9d5cbSmlf  */
6681a0678eSxun ni - Sun Microsystems - Beijing China #define	SGE_LENGTH(x)	(3*(x)+1)
6781a0678eSxun ni - Sun Microsystems - Beijing China #define	SI_DEFAULT_SGL_LENGTH	SGE_LENGTH(SI_DEFAULT_SGT_TABLES_PER_PRB)
6866f9d5cbSmlf 
69832d3fc2SMark Logan /* Argument to be used for calls to timeout() */
70832d3fc2SMark Logan typedef struct si_event_arg {
71832d3fc2SMark Logan 	void *siea_ctlp;
72832d3fc2SMark Logan 	int siea_port;
73832d3fc2SMark Logan } si_event_arg_t;
74832d3fc2SMark Logan 
7566f9d5cbSmlf typedef struct si_portmult_state {
7666f9d5cbSmlf 	int sipm_num_ports;
7766f9d5cbSmlf 	uint8_t sipm_port_type[15];
7866f9d5cbSmlf 	/* one of PORT_TYPE_[NODEV | MULTIPLIER | ATAPI | DISK | UNKNOWN] */
7966f9d5cbSmlf 
8066f9d5cbSmlf 	/*
8166f9d5cbSmlf 	 * sipm_port_type[] is good enough to capture the state of ports
8266f9d5cbSmlf 	 * behind the multiplier. Since any of the port behind a multiplier
8366f9d5cbSmlf 	 * is accessed through the same main controller port, we don't need
8466f9d5cbSmlf 	 * additional si_port_state_t here.
8566f9d5cbSmlf 	 */
8666f9d5cbSmlf 
8766f9d5cbSmlf } si_portmult_state_t;
8866f9d5cbSmlf 
8966f9d5cbSmlf 
9066f9d5cbSmlf /* The following are for port types */
9166f9d5cbSmlf #define	PORT_TYPE_NODEV		0x0
9266f9d5cbSmlf #define	PORT_TYPE_MULTIPLIER	0x1
9366f9d5cbSmlf #define	PORT_TYPE_ATAPI		0x2
9466f9d5cbSmlf #define	PORT_TYPE_DISK		0x3
9566f9d5cbSmlf #define	PORT_TYPE_UNKNOWN	0x4
9666f9d5cbSmlf 
9766f9d5cbSmlf /* The following are for active state */
9866f9d5cbSmlf #define	PORT_INACTIVE		0x0
9966f9d5cbSmlf #define	PORT_ACTIVE		0x1
10066f9d5cbSmlf 
10166f9d5cbSmlf typedef struct si_port_state {
102e57ece5bSPraveen Kumar Dasaraju Rama 	struct si_ctl_state *siport_ctlp;	/* back pointer to controller */
103e57ece5bSPraveen Kumar Dasaraju Rama 
10466f9d5cbSmlf 	uint8_t siport_port_type;
10566f9d5cbSmlf 	/* one of PORT_TYPE_[NODEV | MULTIPLIER | ATAPI | DISK | UNKNOWN] */
10666f9d5cbSmlf 
10766f9d5cbSmlf 	uint8_t siport_active;		/* one of ACTIVE or INACTIVE */
10866f9d5cbSmlf 
109e57ece5bSPraveen Kumar Dasaraju Rama 	uint8_t siport_port_num;	/* port number */
110e57ece5bSPraveen Kumar Dasaraju Rama 
11166f9d5cbSmlf 	si_portmult_state_t siport_portmult_state;
11266f9d5cbSmlf 
11366f9d5cbSmlf 	si_prb_t *siport_prbpool; 	/* These are 31 incore PRBs */
11466f9d5cbSmlf 	uint64_t siport_prbpool_physaddr;
11566f9d5cbSmlf 	ddi_dma_handle_t siport_prbpool_dma_handle;
11666f9d5cbSmlf 	ddi_acc_handle_t siport_prbpool_acc_handle;
11766f9d5cbSmlf 
11866f9d5cbSmlf 
11966f9d5cbSmlf 	si_sgblock_t *siport_sgbpool; 	/* These are 31 incore sg blocks */
12066f9d5cbSmlf 	uint64_t siport_sgbpool_physaddr;
12166f9d5cbSmlf 	ddi_dma_handle_t siport_sgbpool_dma_handle;
12266f9d5cbSmlf 	ddi_acc_handle_t siport_sgbpool_acc_handle;
12366f9d5cbSmlf 
12466f9d5cbSmlf 	kmutex_t siport_mutex; 		/* main per port mutex */
12566f9d5cbSmlf 	uint32_t siport_pending_tags;	/* remembers the pending tags */
12666f9d5cbSmlf 	sata_pkt_t *siport_slot_pkts[SI_NUM_SLOTS];
12766f9d5cbSmlf 
12866f9d5cbSmlf 	/*
12966f9d5cbSmlf 	 * While the reset is in progress, we don't accept any more commands
13066f9d5cbSmlf 	 * until we receive the command with SATA_CLEAR_DEV_RESET_STATE flag.
13166f9d5cbSmlf 	 * However any commands with SATA_IGNORE_DEV_RESET_STATE are allowed in
13266f9d5cbSmlf 	 * during such blockage.
13366f9d5cbSmlf 	 */
13466f9d5cbSmlf 	int siport_reset_in_progress;
13566f9d5cbSmlf 
136832d3fc2SMark Logan 	/* Argument to be used for calls to timeout() */
137832d3fc2SMark Logan 	si_event_arg_t *siport_event_args;
138832d3fc2SMark Logan 
13966f9d5cbSmlf 	/*
14066f9d5cbSmlf 	 * We mop the commands for either abort, reset, timeout or
141cf6ed809SMark Logan 	 * error handling cases. This counts how many mops are in progress.
142cf6ed809SMark Logan 	 * It is also used to return BUSY in tran_start if a mop is going on.
14366f9d5cbSmlf 	 */
14466f9d5cbSmlf 	int mopping_in_progress;
14566f9d5cbSmlf 
14666f9d5cbSmlf 	/* error recovery related info */
14766f9d5cbSmlf 	uint32_t siport_err_tags_SDBERROR;
14866f9d5cbSmlf 	uint32_t siport_err_tags_nonSDBERROR;
14966f9d5cbSmlf 	int siport_pending_ncq_count;
15066f9d5cbSmlf 
15166f9d5cbSmlf } si_port_state_t;
15266f9d5cbSmlf 
15366f9d5cbSmlf /* Warlock annotation */
15466f9d5cbSmlf _NOTE(MUTEX_PROTECTS_DATA(si_port_state_t::siport_mutex, si_port_state_t))
15566f9d5cbSmlf _NOTE(READ_ONLY_DATA(si_port_state_t::siport_prbpool_dma_handle))
15666f9d5cbSmlf _NOTE(READ_ONLY_DATA(si_port_state_t::siport_sgbpool_dma_handle))
157e57ece5bSPraveen Kumar Dasaraju Rama _NOTE(DATA_READABLE_WITHOUT_LOCK(si_port_state_t::siport_ctlp))
158e57ece5bSPraveen Kumar Dasaraju Rama _NOTE(DATA_READABLE_WITHOUT_LOCK(si_port_state_t::siport_port_num))
15966f9d5cbSmlf 
16066f9d5cbSmlf 
16166f9d5cbSmlf typedef struct si_ctl_state {
16266f9d5cbSmlf 
16366f9d5cbSmlf 	dev_info_t *sictl_devinfop;
16466f9d5cbSmlf 
16566f9d5cbSmlf 	int sictl_num_ports;	/* number of controller ports */
16666f9d5cbSmlf 	si_port_state_t *sictl_ports[SI_MAX_PORTS];
16766f9d5cbSmlf 
168*b74cec98SCharles Stephens 	int sictl_devid; /* device id of the controller */
16966f9d5cbSmlf 	int sictl_flags; /* some important state of controller */
17066f9d5cbSmlf 	int sictl_power_level;
17166f9d5cbSmlf 
17266f9d5cbSmlf 	/* pci config space handle */
17366f9d5cbSmlf 	ddi_acc_handle_t sictl_pci_conf_handle;
17466f9d5cbSmlf 
17566f9d5cbSmlf 	/* mapping into bar 0 */
17666f9d5cbSmlf 	ddi_acc_handle_t sictl_global_acc_handle;
17766f9d5cbSmlf 	uintptr_t sictl_global_addr;
17866f9d5cbSmlf 
17966f9d5cbSmlf 	/* mapping into bar 1 */
18066f9d5cbSmlf 	ddi_acc_handle_t sictl_port_acc_handle;
18166f9d5cbSmlf 	uintptr_t sictl_port_addr;
18266f9d5cbSmlf 
18366f9d5cbSmlf 	struct sata_hba_tran *sictl_sata_hba_tran;
18466f9d5cbSmlf 	timeout_id_t sictl_timeout_id;
18566f9d5cbSmlf 
18666f9d5cbSmlf 	kmutex_t sictl_mutex; 			/* per controller mutex */
18766f9d5cbSmlf 
18866f9d5cbSmlf 	ddi_intr_handle_t *sictl_htable;	/* For array of interrupts */
18966f9d5cbSmlf 	int sictl_intr_type;			/* What type of interrupt */
19066f9d5cbSmlf 	int sictl_intr_cnt;			/* # of intrs count returned */
19166f9d5cbSmlf 	size_t sictl_intr_size;			/* Size of intr array */
19266f9d5cbSmlf 	uint_t sictl_intr_pri;			/* Interrupt priority */
19366f9d5cbSmlf 	int sictl_intr_cap;			/* Interrupt capabilities */
194ab0d082fSMark Logan 	int fm_capabilities;			/* FMA capabilities */
19566f9d5cbSmlf 
19666f9d5cbSmlf } si_ctl_state_t;
19766f9d5cbSmlf 
19866f9d5cbSmlf /* Warlock annotation */
19966f9d5cbSmlf _NOTE(MUTEX_PROTECTS_DATA(si_ctl_state_t::sictl_mutex,
20066f9d5cbSmlf 					si_ctl_state_t::sictl_ports))
20166f9d5cbSmlf _NOTE(MUTEX_PROTECTS_DATA(si_ctl_state_t::sictl_mutex,
20266f9d5cbSmlf 					si_ctl_state_t::sictl_power_level))
20366f9d5cbSmlf _NOTE(MUTEX_PROTECTS_DATA(si_ctl_state_t::sictl_mutex,
20466f9d5cbSmlf 					si_ctl_state_t::sictl_flags))
20566f9d5cbSmlf _NOTE(MUTEX_PROTECTS_DATA(si_ctl_state_t::sictl_mutex,
20666f9d5cbSmlf 					si_ctl_state_t::sictl_timeout_id))
207e57ece5bSPraveen Kumar Dasaraju Rama _NOTE(DATA_READABLE_WITHOUT_LOCK(si_ctl_state_t::sictl_ports))
20866f9d5cbSmlf /*
20966f9d5cbSmlf  * flags for si_flags
21066f9d5cbSmlf  */
21166f9d5cbSmlf #define	SI_PM			0x01
21266f9d5cbSmlf #define	SI_ATTACH		0x02
21366f9d5cbSmlf #define	SI_DETACH		0x04
21466f9d5cbSmlf #define	SI_NO_TIMEOUTS		0x08
21566f9d5cbSmlf #define	SI_FRAMEWORK_ATTACHED	0x10	/* are we attached to framework ? */
21666f9d5cbSmlf 
21766f9d5cbSmlf /* progress values for si_attach */
21866f9d5cbSmlf #define	ATTACH_PROGRESS_NONE			(1<<0)
21966f9d5cbSmlf #define	ATTACH_PROGRESS_STATEP_ALLOC		(1<<1)
220ab0d082fSMark Logan #define	ATTACH_PROGRESS_INIT_FMA		(1<<2)
221ab0d082fSMark Logan #define	ATTACH_PROGRESS_CONF_HANDLE		(1<<3)
222ab0d082fSMark Logan #define	ATTACH_PROGRESS_BAR0_MAP		(1<<4)
223ab0d082fSMark Logan #define	ATTACH_PROGRESS_BAR1_MAP		(1<<5)
224ab0d082fSMark Logan #define	ATTACH_PROGRESS_INTR_ADDED		(1<<6)
225ab0d082fSMark Logan #define	ATTACH_PROGRESS_MUTEX_INIT		(1<<7)
226ab0d082fSMark Logan #define	ATTACH_PROGRESS_HW_INIT			(1<<8)
22766f9d5cbSmlf 
22866f9d5cbSmlf #define	SI_10MS_TICKS	(drv_usectohz(10000))	/* ticks in 10 millisec */
22966f9d5cbSmlf #define	SI_1MS_TICKS	(drv_usectohz(1000))	/* ticks in 1 millisec */
23066f9d5cbSmlf #define	SI_1MS_USECS	(1000)			/* usecs in 1 millisec */
23166f9d5cbSmlf #define	SI_POLLRATE_SOFT_RESET		1000
23266f9d5cbSmlf #define	SI_POLLRATE_SSTATUS		10
23366f9d5cbSmlf #define	SI_POLLRATE_PORTREADY		50
23466f9d5cbSmlf #define	SI_POLLRATE_SLOTSTATUS		50
23566f9d5cbSmlf #define	SI_POLLRATE_RECOVERPORTMULT	1000
23666f9d5cbSmlf 
23766f9d5cbSmlf #define	PORTMULT_CONTROL_PORT		0xf
23866f9d5cbSmlf 
23966f9d5cbSmlf /* clearing & setting the n'th bit in a given tag */
24066f9d5cbSmlf #define	CLEAR_BIT(tag, bit)	(tag &= ~(0x1<<bit))
24166f9d5cbSmlf #define	SET_BIT(tag, bit)	(tag |= (0x1<<bit))
24266f9d5cbSmlf 
24366f9d5cbSmlf #if DEBUG
24466f9d5cbSmlf 
2450cfc6e4aSxun ni - Sun Microsystems - Beijing China #define	SI_DEBUG	1
24666f9d5cbSmlf 
247e57ece5bSPraveen Kumar Dasaraju Rama #endif /* DEBUG */
248e57ece5bSPraveen Kumar Dasaraju Rama 
249e57ece5bSPraveen Kumar Dasaraju Rama /* si_debug_flags */
25066f9d5cbSmlf #define	SIDBG_TEST	0x0001
25166f9d5cbSmlf #define	SIDBG_INIT	0x0002
25266f9d5cbSmlf #define	SIDBG_ENTRY	0x0004
25366f9d5cbSmlf #define	SIDBG_DUMP_PRB	0x0008
25466f9d5cbSmlf #define	SIDBG_EVENT	0x0010
25566f9d5cbSmlf #define	SIDBG_POLL_LOOP	0x0020
25666f9d5cbSmlf #define	SIDBG_PKTCOMP	0x0040
25766f9d5cbSmlf #define	SIDBG_TIMEOUT	0x0080
25866f9d5cbSmlf #define	SIDBG_INFO	0x0100
25966f9d5cbSmlf #define	SIDBG_VERBOSE	0x0200
26066f9d5cbSmlf #define	SIDBG_INTR	0x0400
26166f9d5cbSmlf #define	SIDBG_ERRS	0x0800
26266f9d5cbSmlf #define	SIDBG_COOKIES	0x1000
26366f9d5cbSmlf #define	SIDBG_POWER	0x2000
264e57ece5bSPraveen Kumar Dasaraju Rama #define	SIDBG_RESET	0x4000
26566f9d5cbSmlf 
266ab0d082fSMark Logan extern uint32_t si_debug_flags;
26766f9d5cbSmlf 
268e57ece5bSPraveen Kumar Dasaraju Rama #define	SIDBG(flag, format, args ...) \
26966f9d5cbSmlf 	if (si_debug_flags & (flag)) { \
270e57ece5bSPraveen Kumar Dasaraju Rama 		si_log(NULL, NULL, format, ## args); \
27166f9d5cbSmlf 	}
27266f9d5cbSmlf 
273e57ece5bSPraveen Kumar Dasaraju Rama #define	SIDBG_P(flag, si_portp, format, args ...) \
27466f9d5cbSmlf 	if (si_debug_flags & (flag)) { \
275e57ece5bSPraveen Kumar Dasaraju Rama 		si_log(NULL, si_portp, format, ## args); \
27666f9d5cbSmlf 	}
27766f9d5cbSmlf 
278e57ece5bSPraveen Kumar Dasaraju Rama #define	SIDBG_C(flag, si_ctlp, format, args ...) \
27966f9d5cbSmlf 	if (si_debug_flags & (flag)) { \
280e57ece5bSPraveen Kumar Dasaraju Rama 		si_log(si_ctlp, NULL, format, ## args); \
28166f9d5cbSmlf 	}
28266f9d5cbSmlf 
28366f9d5cbSmlf 
28466f9d5cbSmlf /* Flags controlling the reset behavior */
28566f9d5cbSmlf #define	SI_PORT_RESET		0x1	/* Reset the port */
28666f9d5cbSmlf #define	SI_DEVICE_RESET		0x2	/* Reset the device, not the port */
28766f9d5cbSmlf #define	SI_RESET_NO_EVENTS_UP	0x4	/* Don't send reset events up */
28866f9d5cbSmlf 
28966f9d5cbSmlf #ifdef	__cplusplus
29066f9d5cbSmlf }
29166f9d5cbSmlf #endif
29266f9d5cbSmlf 
29366f9d5cbSmlf #endif /* _SI3124VAR_H */
294