1*80c94ecdSKeith M Wesolowski /*
2*80c94ecdSKeith M Wesolowski  * This file and its contents are supplied under the terms of the
3*80c94ecdSKeith M Wesolowski  * Common Development and Distribution License ("CDDL"), version 1.0.
4*80c94ecdSKeith M Wesolowski  * You may only use this file in accordance with the terms of version
5*80c94ecdSKeith M Wesolowski  * 1.0 of the CDDL.
6*80c94ecdSKeith M Wesolowski  *
7*80c94ecdSKeith M Wesolowski  * A full copy of the text of the CDDL should have accompanied this
8*80c94ecdSKeith M Wesolowski  * source.  A copy of the CDDL is also available via the Internet at
9*80c94ecdSKeith M Wesolowski  * http://www.illumos.org/license/CDDL.
10*80c94ecdSKeith M Wesolowski  */
11*80c94ecdSKeith M Wesolowski 
12*80c94ecdSKeith M Wesolowski /*
13*80c94ecdSKeith M Wesolowski  * Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
14*80c94ecdSKeith M Wesolowski  */
15*80c94ecdSKeith M Wesolowski 
16*80c94ecdSKeith M Wesolowski /*
17*80c94ecdSKeith M Wesolowski  * This module contains routines that program the controller. All
18*80c94ecdSKeith M Wesolowski  * operations  viz.,  initialization of  controller,  submision &
19*80c94ecdSKeith M Wesolowski  * retrieval  of  commands, enabling &  disabling of  interrupts,
20*80c94ecdSKeith M Wesolowski  * checking interrupt status are performed here.
21*80c94ecdSKeith M Wesolowski  */
22*80c94ecdSKeith M Wesolowski 
23*80c94ecdSKeith M Wesolowski #include <sys/sdt.h>
24*80c94ecdSKeith M Wesolowski #include "cpqary3.h"
25*80c94ecdSKeith M Wesolowski 
26*80c94ecdSKeith M Wesolowski /*
27*80c94ecdSKeith M Wesolowski  * Local Functions Definitions
28*80c94ecdSKeith M Wesolowski  */
29*80c94ecdSKeith M Wesolowski uint8_t cpqary3_check_simple_ctlr_intr(cpqary3_t *cpqary3p);
30*80c94ecdSKeith M Wesolowski uint8_t cpqary3_check_perf_ctlr_intr(cpqary3_t *cpqary3p);
31*80c94ecdSKeith M Wesolowski uint8_t cpqary3_check_perf_e200_intr(cpqary3_t *cpqary3p);
32*80c94ecdSKeith M Wesolowski uint8_t cpqary3_check_ctlr_init(cpqary3_t *);
33*80c94ecdSKeith M Wesolowski 
34*80c94ecdSKeith M Wesolowski /*
35*80c94ecdSKeith M Wesolowski  * Function	: 	cpqary3_check_simple_ctlr_intr
36*80c94ecdSKeith M Wesolowski  * Description	: 	This routine determines if the controller did interrupt.
37*80c94ecdSKeith M Wesolowski  * Called By	: 	cpqary3_hw_isr()
38*80c94ecdSKeith M Wesolowski  * Parameters	: 	per-controller
39*80c94ecdSKeith M Wesolowski  * Calls	: 	None
40*80c94ecdSKeith M Wesolowski  * Return Values: 	SUCCESS : This controller did interrupt.
41*80c94ecdSKeith M Wesolowski  *			FAILURE : It did not.
42*80c94ecdSKeith M Wesolowski  */
43*80c94ecdSKeith M Wesolowski uint8_t
cpqary3_check_simple_ctlr_intr(cpqary3_t * cpqary3p)44*80c94ecdSKeith M Wesolowski cpqary3_check_simple_ctlr_intr(cpqary3_t *cpqary3p)
45*80c94ecdSKeith M Wesolowski {
46*80c94ecdSKeith M Wesolowski 	uint32_t	intr_pending_mask = 0;
47*80c94ecdSKeith M Wesolowski 
48*80c94ecdSKeith M Wesolowski 	/*
49*80c94ecdSKeith M Wesolowski 	 * Read the Interrupt Status Register and
50*80c94ecdSKeith M Wesolowski 	 * if bit 3 is set, it indicates that we have completed commands
51*80c94ecdSKeith M Wesolowski 	 * in the controller
52*80c94ecdSKeith M Wesolowski 	 */
53*80c94ecdSKeith M Wesolowski 	intr_pending_mask = cpqary3p->bddef->bd_intrpendmask;
54*80c94ecdSKeith M Wesolowski 
55*80c94ecdSKeith M Wesolowski 	if (intr_pending_mask &
56*80c94ecdSKeith M Wesolowski 	    (ddi_get32(cpqary3p->isr_handle, (uint32_t *)cpqary3p->isr)))
57*80c94ecdSKeith M Wesolowski 		return (CPQARY3_SUCCESS);
58*80c94ecdSKeith M Wesolowski 
59*80c94ecdSKeith M Wesolowski 	return (CPQARY3_FAILURE);
60*80c94ecdSKeith M Wesolowski }
61*80c94ecdSKeith M Wesolowski 
62*80c94ecdSKeith M Wesolowski /*
63*80c94ecdSKeith M Wesolowski  * Function	:      	cpqary3_check_perf_ctlr_intr
64*80c94ecdSKeith M Wesolowski  * Description	:      	This routine determines if the
65*80c94ecdSKeith M Wesolowski  *			controller did interrupt.
66*80c94ecdSKeith M Wesolowski  * Called By	:      	cpqary3_hw_isr()
67*80c94ecdSKeith M Wesolowski  * Parameters	:      	per-controller
68*80c94ecdSKeith M Wesolowski  * Calls	:      	None
69*80c94ecdSKeith M Wesolowski  * Return Values:      	SUCCESS : This controller did interrupt.
70*80c94ecdSKeith M Wesolowski  *			FAILURE : It did not.
71*80c94ecdSKeith M Wesolowski  */
72*80c94ecdSKeith M Wesolowski uint8_t
cpqary3_check_perf_ctlr_intr(cpqary3_t * cpqary3p)73*80c94ecdSKeith M Wesolowski cpqary3_check_perf_ctlr_intr(cpqary3_t *cpqary3p)
74*80c94ecdSKeith M Wesolowski {
75*80c94ecdSKeith M Wesolowski 	/*
76*80c94ecdSKeith M Wesolowski 	 * Read the Interrupt Status Register and
77*80c94ecdSKeith M Wesolowski 	 * if bit 3 is set, it indicates that we have completed commands
78*80c94ecdSKeith M Wesolowski 	 * in the controller
79*80c94ecdSKeith M Wesolowski 	 */
80*80c94ecdSKeith M Wesolowski 	if (0x1 & (ddi_get32(cpqary3p->isr_handle,
81*80c94ecdSKeith M Wesolowski 	    (uint32_t *)cpqary3p->isr))) {
82*80c94ecdSKeith M Wesolowski 		return (CPQARY3_SUCCESS);
83*80c94ecdSKeith M Wesolowski 	}
84*80c94ecdSKeith M Wesolowski 
85*80c94ecdSKeith M Wesolowski 	return (CPQARY3_FAILURE);
86*80c94ecdSKeith M Wesolowski }
87*80c94ecdSKeith M Wesolowski 
88*80c94ecdSKeith M Wesolowski /*
89*80c94ecdSKeith M Wesolowski  * Function	:      	cpqary3_check_perf_e200_intr
90*80c94ecdSKeith M Wesolowski  * Description	:      	This routine determines if the controller
91*80c94ecdSKeith M Wesolowski  *			did interrupt.
92*80c94ecdSKeith M Wesolowski  * Called By	:      	cpqary3_hw_isr()
93*80c94ecdSKeith M Wesolowski  * Parameters	:      	per-controller
94*80c94ecdSKeith M Wesolowski  * Calls	:      	None
95*80c94ecdSKeith M Wesolowski  * Return Values:      	SUCCESS : This controller did interrupt.
96*80c94ecdSKeith M Wesolowski  *			FAILURE : It did not.
97*80c94ecdSKeith M Wesolowski  */
98*80c94ecdSKeith M Wesolowski uint8_t
cpqary3_check_perf_e200_intr(cpqary3_t * cpqary3p)99*80c94ecdSKeith M Wesolowski cpqary3_check_perf_e200_intr(cpqary3_t *cpqary3p)
100*80c94ecdSKeith M Wesolowski {
101*80c94ecdSKeith M Wesolowski 	/*
102*80c94ecdSKeith M Wesolowski 	 * Read the Interrupt Status Register and
103*80c94ecdSKeith M Wesolowski 	 * if bit 3 is set, it indicates that we have completed commands
104*80c94ecdSKeith M Wesolowski 	 * in the controller
105*80c94ecdSKeith M Wesolowski 	 */
106*80c94ecdSKeith M Wesolowski 	if (0x4 & (ddi_get32(cpqary3p->isr_handle,
107*80c94ecdSKeith M Wesolowski 	    (uint32_t *)cpqary3p->isr))) {
108*80c94ecdSKeith M Wesolowski 		return (CPQARY3_SUCCESS);
109*80c94ecdSKeith M Wesolowski 	}
110*80c94ecdSKeith M Wesolowski 
111*80c94ecdSKeith M Wesolowski 	return (CPQARY3_FAILURE);
112*80c94ecdSKeith M Wesolowski }
113*80c94ecdSKeith M Wesolowski 
114*80c94ecdSKeith M Wesolowski 
115*80c94ecdSKeith M Wesolowski /*
116*80c94ecdSKeith M Wesolowski  * Function	: 	cpqary3_retrieve
117*80c94ecdSKeith M Wesolowski  * Description	: 	This routine retrieves the completed command from the
118*80c94ecdSKeith M Wesolowski  *			controller reply queue.
119*80c94ecdSKeith M Wesolowski  *			and processes the completed commands.
120*80c94ecdSKeith M Wesolowski  * Called By	:  	cpqary3_sw_isr(), cpqary3_handle_flag_nointr()
121*80c94ecdSKeith M Wesolowski  * Parameters	: 	per-controller
122*80c94ecdSKeith M Wesolowski  * Calls	: 	packet completion routines
123*80c94ecdSKeith M Wesolowski  * Return Values: 	SUCCESS : A completed command has been retrieved
124*80c94ecdSKeith M Wesolowski  *			and processed.
125*80c94ecdSKeith M Wesolowski  *			FAILURE : No completed command was in the controller.
126*80c94ecdSKeith M Wesolowski  */
127*80c94ecdSKeith M Wesolowski uint8_t
cpqary3_retrieve(cpqary3_t * cpqary3p)128*80c94ecdSKeith M Wesolowski cpqary3_retrieve(cpqary3_t *cpqary3p)
129*80c94ecdSKeith M Wesolowski {
130*80c94ecdSKeith M Wesolowski 	uint32_t			tag;
131*80c94ecdSKeith M Wesolowski 	uint32_t			CmdsOutMax;
132*80c94ecdSKeith M Wesolowski 	cpqary3_cmdpvt_t		*cpqary3_cmdpvtp;
133*80c94ecdSKeith M Wesolowski 	cpqary3_drvr_replyq_t		*replyq_ptr;
134*80c94ecdSKeith M Wesolowski 
135*80c94ecdSKeith M Wesolowski 	/*
136*80c94ecdSKeith M Wesolowski 	 * Get the Reply Command List Addr
137*80c94ecdSKeith M Wesolowski 	 * Update the returned Tag in that particular command structure.
138*80c94ecdSKeith M Wesolowski 	 * If a valid one, de-q that from the SUBMITTED Q and
139*80c94ecdSKeith M Wesolowski 	 * enqueue that to the RETRIEVED Q.
140*80c94ecdSKeith M Wesolowski 	 */
141*80c94ecdSKeith M Wesolowski 
142*80c94ecdSKeith M Wesolowski 	RETURN_FAILURE_IF_NULL(cpqary3p);
143*80c94ecdSKeith M Wesolowski 
144*80c94ecdSKeith M Wesolowski 	/* PERF */
145*80c94ecdSKeith M Wesolowski 	replyq_ptr = (cpqary3_drvr_replyq_t *)cpqary3p->drvr_replyq;
146*80c94ecdSKeith M Wesolowski 	CmdsOutMax = cpqary3p->ctlr_maxcmds;
147*80c94ecdSKeith M Wesolowski 
148*80c94ecdSKeith M Wesolowski 	while ((replyq_ptr->replyq_headptr[0] & 0x01) ==
149*80c94ecdSKeith M Wesolowski 	    replyq_ptr->cyclic_indicator) {
150*80c94ecdSKeith M Wesolowski 		/* command has completed */
151*80c94ecdSKeith M Wesolowski 		/* Get the tag */
152*80c94ecdSKeith M Wesolowski 
153*80c94ecdSKeith M Wesolowski 		tag = replyq_ptr->replyq_headptr[0];
154*80c94ecdSKeith M Wesolowski 		if ((tag >> CPQARY3_GET_MEM_TAG) >= (CmdsOutMax / 3) * 3) {
155*80c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN,
156*80c94ecdSKeith M Wesolowski 			    "CPQary3 : HBA returned Spurious Tag");
157*80c94ecdSKeith M Wesolowski 			return (CPQARY3_FAILURE);
158*80c94ecdSKeith M Wesolowski 		}
159*80c94ecdSKeith M Wesolowski 
160*80c94ecdSKeith M Wesolowski 		cpqary3_cmdpvtp = &cpqary3p->cmdmemlistp->pool[
161*80c94ecdSKeith M Wesolowski 		    tag >> CPQARY3_GET_MEM_TAG];
162*80c94ecdSKeith M Wesolowski 		cpqary3_cmdpvtp->cmdlist_memaddr->
163*80c94ecdSKeith M Wesolowski 		    Header.Tag.drvinfo_n_err = (tag & 0xF) >> 1;
164*80c94ecdSKeith M Wesolowski 		mutex_enter(&cpqary3p->sw_mutex);
165*80c94ecdSKeith M Wesolowski 		cpqary3_cmdpvtp->complete(cpqary3_cmdpvtp);
166*80c94ecdSKeith M Wesolowski 		mutex_exit(&cpqary3p->sw_mutex);
167*80c94ecdSKeith M Wesolowski 
168*80c94ecdSKeith M Wesolowski 		/* Traverse to the next command in reply queue */
169*80c94ecdSKeith M Wesolowski 
170*80c94ecdSKeith M Wesolowski 		++replyq_ptr->index;
171*80c94ecdSKeith M Wesolowski 		if (replyq_ptr->index == replyq_ptr->max_index) {
172*80c94ecdSKeith M Wesolowski 			replyq_ptr->index = 0;
173*80c94ecdSKeith M Wesolowski 			/* Toggle at wraparound */
174*80c94ecdSKeith M Wesolowski 			replyq_ptr->cyclic_indicator =
175*80c94ecdSKeith M Wesolowski 			    (replyq_ptr->cyclic_indicator == 0) ? 1 : 0;
176*80c94ecdSKeith M Wesolowski 			replyq_ptr->replyq_headptr =
177*80c94ecdSKeith M Wesolowski 			    /* LINTED: alignment */
178*80c94ecdSKeith M Wesolowski 			    (uint32_t *)(replyq_ptr->replyq_start_addr);
179*80c94ecdSKeith M Wesolowski 		} else {
180*80c94ecdSKeith M Wesolowski 			replyq_ptr->replyq_headptr += 2;
181*80c94ecdSKeith M Wesolowski 		}
182*80c94ecdSKeith M Wesolowski 	}
183*80c94ecdSKeith M Wesolowski 	/* PERF */
184*80c94ecdSKeith M Wesolowski 
185*80c94ecdSKeith M Wesolowski 	return (CPQARY3_SUCCESS);
186*80c94ecdSKeith M Wesolowski }
187*80c94ecdSKeith M Wesolowski 
188*80c94ecdSKeith M Wesolowski 
189*80c94ecdSKeith M Wesolowski /*
190*80c94ecdSKeith M Wesolowski  * Function	:  cpqary3_poll_retrieve
191*80c94ecdSKeith M Wesolowski  * Description	:  This routine retrieves the completed command from the
192*80c94ecdSKeith M Wesolowski  *			controller reply queue in poll mode.
193*80c94ecdSKeith M Wesolowski  *			and processes the completed commands.
194*80c94ecdSKeith M Wesolowski  * Called By	:  cpqary3_poll
195*80c94ecdSKeith M Wesolowski  * Parameters	:  per-controller
196*80c94ecdSKeith M Wesolowski  * Calls	:  packet completion routines
197*80c94ecdSKeith M Wesolowski  * Return Values:  If the polled command is completed, send back a success.
198*80c94ecdSKeith M Wesolowski  *			If not return failure.
199*80c94ecdSKeith M Wesolowski  */
200*80c94ecdSKeith M Wesolowski uint8_t
cpqary3_poll_retrieve(cpqary3_t * cpqary3p,uint32_t poll_tag)201*80c94ecdSKeith M Wesolowski cpqary3_poll_retrieve(cpqary3_t *cpqary3p, uint32_t poll_tag)
202*80c94ecdSKeith M Wesolowski {
203*80c94ecdSKeith M Wesolowski 	uint32_t			tag;
204*80c94ecdSKeith M Wesolowski 	uint32_t			CmdsOutMax;
205*80c94ecdSKeith M Wesolowski 	cpqary3_cmdpvt_t		*cpqary3_cmdpvtp;
206*80c94ecdSKeith M Wesolowski 	cpqary3_drvr_replyq_t		*replyq_ptr;
207*80c94ecdSKeith M Wesolowski 	uint32_t			temp_tag;
208*80c94ecdSKeith M Wesolowski 	uint8_t				tag_flag = 0;
209*80c94ecdSKeith M Wesolowski 
210*80c94ecdSKeith M Wesolowski 	RETURN_FAILURE_IF_NULL(cpqary3p);
211*80c94ecdSKeith M Wesolowski 
212*80c94ecdSKeith M Wesolowski 	/* PERF */
213*80c94ecdSKeith M Wesolowski 	replyq_ptr = (cpqary3_drvr_replyq_t *)cpqary3p->drvr_replyq;
214*80c94ecdSKeith M Wesolowski 	CmdsOutMax = cpqary3p->cmdmemlistp->max_memcnt;
215*80c94ecdSKeith M Wesolowski 
216*80c94ecdSKeith M Wesolowski 	if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) {
217*80c94ecdSKeith M Wesolowski 		while ((tag = ddi_get32(cpqary3p->opq_handle,
218*80c94ecdSKeith M Wesolowski 		    (uint32_t *)cpqary3p->opq)) != 0xFFFFFFFF) {
219*80c94ecdSKeith M Wesolowski 			cpqary3_cmdpvtp = &cpqary3p->cmdmemlistp->pool[
220*80c94ecdSKeith M Wesolowski 			    tag >> CPQARY3_GET_MEM_TAG];
221*80c94ecdSKeith M Wesolowski 			cpqary3_cmdpvtp->cmdlist_memaddr->
222*80c94ecdSKeith M Wesolowski 			    Header.Tag.drvinfo_n_err = (tag & 0xF) >> 1;
223*80c94ecdSKeith M Wesolowski 			temp_tag = cpqary3_cmdpvtp->tag.tag_value;
224*80c94ecdSKeith M Wesolowski 
225*80c94ecdSKeith M Wesolowski 			if (temp_tag == poll_tag)
226*80c94ecdSKeith M Wesolowski 				tag_flag = 1;
227*80c94ecdSKeith M Wesolowski 			cpqary3_cmdpvtp->complete(cpqary3_cmdpvtp);
228*80c94ecdSKeith M Wesolowski 		}
229*80c94ecdSKeith M Wesolowski 	} else {
230*80c94ecdSKeith M Wesolowski 		while ((replyq_ptr->replyq_headptr[0] & 0x01) ==
231*80c94ecdSKeith M Wesolowski 		    replyq_ptr->cyclic_indicator) {
232*80c94ecdSKeith M Wesolowski 			/* command has completed */
233*80c94ecdSKeith M Wesolowski 			/* Get the tag */
234*80c94ecdSKeith M Wesolowski 			tag = replyq_ptr->replyq_headptr[0];
235*80c94ecdSKeith M Wesolowski 
236*80c94ecdSKeith M Wesolowski 			if ((tag >> CPQARY3_GET_MEM_TAG) >= (CmdsOutMax/3)*3) {
237*80c94ecdSKeith M Wesolowski 				cmn_err(CE_WARN,
238*80c94ecdSKeith M Wesolowski 				    "CPQary3 : HBA returned Spurious Tag");
239*80c94ecdSKeith M Wesolowski 				return (CPQARY3_FAILURE);
240*80c94ecdSKeith M Wesolowski 			}
241*80c94ecdSKeith M Wesolowski 
242*80c94ecdSKeith M Wesolowski 			cpqary3_cmdpvtp = &cpqary3p->cmdmemlistp->pool[
243*80c94ecdSKeith M Wesolowski 			    tag >> CPQARY3_GET_MEM_TAG];
244*80c94ecdSKeith M Wesolowski 			cpqary3_cmdpvtp->cmdlist_memaddr->
245*80c94ecdSKeith M Wesolowski 			    Header.Tag.drvinfo_n_err = (tag & 0xF) >> 1;
246*80c94ecdSKeith M Wesolowski 			temp_tag = cpqary3_cmdpvtp->tag.tag_value;
247*80c94ecdSKeith M Wesolowski 
248*80c94ecdSKeith M Wesolowski 			if (temp_tag == poll_tag)
249*80c94ecdSKeith M Wesolowski 				tag_flag = 1;
250*80c94ecdSKeith M Wesolowski 
251*80c94ecdSKeith M Wesolowski 			cpqary3_cmdpvtp->complete(cpqary3_cmdpvtp);
252*80c94ecdSKeith M Wesolowski 
253*80c94ecdSKeith M Wesolowski 			/* Traverse to the next command in reply queue */
254*80c94ecdSKeith M Wesolowski 			++replyq_ptr->index;
255*80c94ecdSKeith M Wesolowski 			if (replyq_ptr->index == replyq_ptr->max_index) {
256*80c94ecdSKeith M Wesolowski 				replyq_ptr->index = 0;
257*80c94ecdSKeith M Wesolowski 				/* Toggle at wraparound */
258*80c94ecdSKeith M Wesolowski 				replyq_ptr->cyclic_indicator =
259*80c94ecdSKeith M Wesolowski 				    (replyq_ptr->cyclic_indicator == 0) ? 1 : 0;
260*80c94ecdSKeith M Wesolowski 				replyq_ptr->replyq_headptr =
261*80c94ecdSKeith M Wesolowski 				    /* LINTED: alignment */
262*80c94ecdSKeith M Wesolowski 				    (uint32_t *)(replyq_ptr->replyq_start_addr);
263*80c94ecdSKeith M Wesolowski 			} else {
264*80c94ecdSKeith M Wesolowski 				replyq_ptr->replyq_headptr += 2;
265*80c94ecdSKeith M Wesolowski 			}
266*80c94ecdSKeith M Wesolowski 		}
267*80c94ecdSKeith M Wesolowski 	}
268*80c94ecdSKeith M Wesolowski 	/* PERF */
269*80c94ecdSKeith M Wesolowski 	if (tag_flag) {
270*80c94ecdSKeith M Wesolowski 		return (CPQARY3_SUCCESS);
271*80c94ecdSKeith M Wesolowski 	}
272*80c94ecdSKeith M Wesolowski 
273*80c94ecdSKeith M Wesolowski 	return (CPQARY3_FAILURE);
274*80c94ecdSKeith M Wesolowski }
275*80c94ecdSKeith M Wesolowski 
276*80c94ecdSKeith M Wesolowski /*
277*80c94ecdSKeith M Wesolowski  * Function	: 	cpqary3_submit
278*80c94ecdSKeith M Wesolowski  * Description	: 	This routine submits the command to the Inbound Post Q.
279*80c94ecdSKeith M Wesolowski  * Called By	: 	cpqary3_transport(), cpqary3_send_NOE_command(),
280*80c94ecdSKeith M Wesolowski  *			cpqary3_disable_NOE_command(),
281*80c94ecdSKeith M Wesolowski  *			cpqary3_handle_flag_nointr(),
282*80c94ecdSKeith M Wesolowski  *			cpqary3_tick_hdlr(), cpqary3_synccmd_send()
283*80c94ecdSKeith M Wesolowski  * Parameters	: 	per-controller, physical address
284*80c94ecdSKeith M Wesolowski  * Calls	: 	None
285*80c94ecdSKeith M Wesolowski  * Return Values: 	None
286*80c94ecdSKeith M Wesolowski  */
287*80c94ecdSKeith M Wesolowski int32_t
cpqary3_submit(cpqary3_t * cpqary3p,uint32_t cmd_phyaddr)288*80c94ecdSKeith M Wesolowski cpqary3_submit(cpqary3_t *cpqary3p, uint32_t cmd_phyaddr)
289*80c94ecdSKeith M Wesolowski {
290*80c94ecdSKeith M Wesolowski 	uint32_t		phys_addr = 0;
291*80c94ecdSKeith M Wesolowski 	uint8_t			retval  = 0;
292*80c94ecdSKeith M Wesolowski 
293*80c94ecdSKeith M Wesolowski 	/*
294*80c94ecdSKeith M Wesolowski 	 * Write the Physical Address of the command-to-be-submitted
295*80c94ecdSKeith M Wesolowski 	 * into the Controller's Inbound Post Q.
296*80c94ecdSKeith M Wesolowski 	 */
297*80c94ecdSKeith M Wesolowski 
298*80c94ecdSKeith M Wesolowski 	ASSERT(cpqary3p != NULL);
299*80c94ecdSKeith M Wesolowski 
300*80c94ecdSKeith M Wesolowski #ifdef AMD64_DEBUG
301*80c94ecdSKeith M Wesolowski 	{
302*80c94ecdSKeith M Wesolowski 	char		debug_char;
303*80c94ecdSKeith M Wesolowski 	uint32_t	tmp_cmd_phyaddr;
304*80c94ecdSKeith M Wesolowski 
305*80c94ecdSKeith M Wesolowski 	tmp_cmd_phyaddr = (uint32_t)(cmd_phyaddr & 0XFFFFFFFF);
306*80c94ecdSKeith M Wesolowski 
307*80c94ecdSKeith M Wesolowski 	cmn_err(CE_WARN, "CPQary3: cmd_phyaddr = %lX\n tmp_cmd_phyaddr = %lX",
308*80c94ecdSKeith M Wesolowski 	    cmd_phyaddr, tmp_cmd_phyaddr);
309*80c94ecdSKeith M Wesolowski 
310*80c94ecdSKeith M Wesolowski 	debug_enter(&debug_char);
311*80c94ecdSKeith M Wesolowski 	ddi_put32(cpqary3p->ipq_handle, (uint32_t *)cpqary3p->ipq, cmd_phyaddr);
312*80c94ecdSKeith M Wesolowski 	}
313*80c94ecdSKeith M Wesolowski #endif
314*80c94ecdSKeith M Wesolowski 
315*80c94ecdSKeith M Wesolowski 
316*80c94ecdSKeith M Wesolowski 	/* CONTROLLER_LOCKUP */
317*80c94ecdSKeith M Wesolowski 	if (cpqary3p->controller_lockup == CPQARY3_TRUE) {
318*80c94ecdSKeith M Wesolowski 		retval = EIO;
319*80c94ecdSKeith M Wesolowski 		return (retval);
320*80c94ecdSKeith M Wesolowski 	}
321*80c94ecdSKeith M Wesolowski 	/* CONTROLLER_LOCKUP */
322*80c94ecdSKeith M Wesolowski 
323*80c94ecdSKeith M Wesolowski 	if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) {
324*80c94ecdSKeith M Wesolowski 		ddi_put32(cpqary3p->ipq_handle,
325*80c94ecdSKeith M Wesolowski 		    (uint32_t *)cpqary3p->ipq, cmd_phyaddr);
326*80c94ecdSKeith M Wesolowski 	} else {
327*80c94ecdSKeith M Wesolowski 		/* The driver always uses the 0th block fetch count always */
328*80c94ecdSKeith M Wesolowski 		phys_addr = cmd_phyaddr | 0 | 0x1;
329*80c94ecdSKeith M Wesolowski 		ddi_put32(cpqary3p->ipq_handle,
330*80c94ecdSKeith M Wesolowski 		    (uint32_t *)cpqary3p->ipq, phys_addr);
331*80c94ecdSKeith M Wesolowski 	}
332*80c94ecdSKeith M Wesolowski 
333*80c94ecdSKeith M Wesolowski 	/* PERF */
334*80c94ecdSKeith M Wesolowski 
335*80c94ecdSKeith M Wesolowski 	/*
336*80c94ecdSKeith M Wesolowski 	 * Command submission can NEVER FAIL since the number of commands that
337*80c94ecdSKeith M Wesolowski 	 * can reside in the controller at any time is 1024 and our memory
338*80c94ecdSKeith M Wesolowski 	 * allocation is for 225 commands ONLY. Thus, at any given time the
339*80c94ecdSKeith M Wesolowski 	 * maximum number of commands in the controller is 225.
340*80c94ecdSKeith M Wesolowski 	 */
341*80c94ecdSKeith M Wesolowski 
342*80c94ecdSKeith M Wesolowski 	/* CONTROLLER_LOCKUP */
343*80c94ecdSKeith M Wesolowski 	return (retval);
344*80c94ecdSKeith M Wesolowski 	/* CONTROLLER_LOCKUP */
345*80c94ecdSKeith M Wesolowski 
346*80c94ecdSKeith M Wesolowski }
347*80c94ecdSKeith M Wesolowski 
348*80c94ecdSKeith M Wesolowski 
349*80c94ecdSKeith M Wesolowski /*
350*80c94ecdSKeith M Wesolowski  * Function	: 	cpqary3_intr_onoff
351*80c94ecdSKeith M Wesolowski  * Description	: 	This routine enables/disables the HBA interrupt.
352*80c94ecdSKeith M Wesolowski  * Called By	: 	cpqary3_attach(), ry3_handle_flag_nointr(),
353*80c94ecdSKeith M Wesolowski  *			cpqary3_tick_hdlr(), cpqary3_init_ctlr_resource()
354*80c94ecdSKeith M Wesolowski  * Parameters	: 	per-controller, flag stating enable/disable
355*80c94ecdSKeith M Wesolowski  * Calls	: 	None
356*80c94ecdSKeith M Wesolowski  * Return Values: 	None
357*80c94ecdSKeith M Wesolowski  */
358*80c94ecdSKeith M Wesolowski void
cpqary3_intr_onoff(cpqary3_t * cpqary3p,uint8_t flag)359*80c94ecdSKeith M Wesolowski cpqary3_intr_onoff(cpqary3_t *cpqary3p, uint8_t flag)
360*80c94ecdSKeith M Wesolowski {
361*80c94ecdSKeith M Wesolowski 	uint32_t	intr = 0;
362*80c94ecdSKeith M Wesolowski 	uint32_t	intr_mask = 0;
363*80c94ecdSKeith M Wesolowski 
364*80c94ecdSKeith M Wesolowski 	/*
365*80c94ecdSKeith M Wesolowski 	 * Enable or disable the interrupt based on the flag
366*80c94ecdSKeith M Wesolowski 	 * Read the Interrupt Mask Register first and then update it
367*80c94ecdSKeith M Wesolowski 	 * accordingly
368*80c94ecdSKeith M Wesolowski 	 */
369*80c94ecdSKeith M Wesolowski 
370*80c94ecdSKeith M Wesolowski 	ASSERT(cpqary3p != NULL);
371*80c94ecdSKeith M Wesolowski 
372*80c94ecdSKeith M Wesolowski 	intr = ddi_get32(cpqary3p->imr_handle, (uint32_t *)cpqary3p->imr);
373*80c94ecdSKeith M Wesolowski 	intr_mask = cpqary3p->bddef->bd_intrmask;
374*80c94ecdSKeith M Wesolowski 
375*80c94ecdSKeith M Wesolowski 	if (flag == CPQARY3_INTR_ENABLE) {
376*80c94ecdSKeith M Wesolowski 		ddi_put32(cpqary3p->imr_handle,
377*80c94ecdSKeith M Wesolowski 		    (uint32_t *)cpqary3p->imr, intr & ~(intr_mask));
378*80c94ecdSKeith M Wesolowski 	} else {
379*80c94ecdSKeith M Wesolowski 		ddi_put32(cpqary3p->imr_handle,
380*80c94ecdSKeith M Wesolowski 		    (uint32_t *)cpqary3p->imr, (intr | intr_mask));
381*80c94ecdSKeith M Wesolowski 	}
382*80c94ecdSKeith M Wesolowski }
383*80c94ecdSKeith M Wesolowski 
384*80c94ecdSKeith M Wesolowski 
385*80c94ecdSKeith M Wesolowski /*
386*80c94ecdSKeith M Wesolowski  * Function	: 	cpqary3_lockup_intr_onoff
387*80c94ecdSKeith M Wesolowski  * Description	: 	This routine enables/disables the lockup interrupt.
388*80c94ecdSKeith M Wesolowski  * Called By	: 	cpqary3_attach(), cpqary3_handle_flag_nointr(),
389*80c94ecdSKeith M Wesolowski  *			cpqary3_tick_hdlr(), cpqary3_hw_isr,
390*80c94ecdSKeith M Wesolowski  *			cpqary3_init_ctlr_resource()
391*80c94ecdSKeith M Wesolowski  * Parameters	: 	per-controller, flag stating enable/disable
392*80c94ecdSKeith M Wesolowski  * Calls	: 	None
393*80c94ecdSKeith M Wesolowski  * Return Values: 	None
394*80c94ecdSKeith M Wesolowski  */
395*80c94ecdSKeith M Wesolowski void
cpqary3_lockup_intr_onoff(cpqary3_t * cpqary3p,uint8_t flag)396*80c94ecdSKeith M Wesolowski cpqary3_lockup_intr_onoff(cpqary3_t *cpqary3p, uint8_t flag)
397*80c94ecdSKeith M Wesolowski {
398*80c94ecdSKeith M Wesolowski 	uint32_t	intr = 0;
399*80c94ecdSKeith M Wesolowski 	uint32_t	intr_lockup_mask = 0;
400*80c94ecdSKeith M Wesolowski 
401*80c94ecdSKeith M Wesolowski 	/*
402*80c94ecdSKeith M Wesolowski 	 * Enable or disable the interrupt based on the flag
403*80c94ecdSKeith M Wesolowski 	 * Read the Interrupt Mask Register first and then update it
404*80c94ecdSKeith M Wesolowski 	 * accordingly
405*80c94ecdSKeith M Wesolowski 	 */
406*80c94ecdSKeith M Wesolowski 
407*80c94ecdSKeith M Wesolowski 	ASSERT(cpqary3p != NULL);
408*80c94ecdSKeith M Wesolowski 
409*80c94ecdSKeith M Wesolowski 	intr = ddi_get32(cpqary3p->imr_handle, (uint32_t *)cpqary3p->imr);
410*80c94ecdSKeith M Wesolowski 	intr_lockup_mask = cpqary3p->bddef->bd_lockup_intrmask;
411*80c94ecdSKeith M Wesolowski 
412*80c94ecdSKeith M Wesolowski 	if (flag == CPQARY3_INTR_ENABLE) {
413*80c94ecdSKeith M Wesolowski 		ddi_put32(cpqary3p->imr_handle,
414*80c94ecdSKeith M Wesolowski 		    (uint32_t *)cpqary3p->imr, intr & ~(intr_lockup_mask));
415*80c94ecdSKeith M Wesolowski 	} else {
416*80c94ecdSKeith M Wesolowski 		ddi_put32(cpqary3p->imr_handle,
417*80c94ecdSKeith M Wesolowski 		    (uint32_t *)cpqary3p->imr, (intr | intr_lockup_mask));
418*80c94ecdSKeith M Wesolowski 	}
419*80c94ecdSKeith M Wesolowski }
420*80c94ecdSKeith M Wesolowski 
421*80c94ecdSKeith M Wesolowski /*
422*80c94ecdSKeith M Wesolowski  * Function	: 	cpqary3_init_ctlr
423*80c94ecdSKeith M Wesolowski  * Description	: 	This routine initialises the HBA to Simple Transport
424*80c94ecdSKeith M Wesolowski  *			Method. Refer to CISS for more information.
425*80c94ecdSKeith M Wesolowski  *			It checks the readiness of the HBA.
426*80c94ecdSKeith M Wesolowski  * Called By	: 	cpqary3_init_ctlr_resource()
427*80c94ecdSKeith M Wesolowski  * Parameters	: 	per-controller(), physical address()
428*80c94ecdSKeith M Wesolowski  * Calls	: 	cpqary3_check_ctlr_init
429*80c94ecdSKeith M Wesolowski  * Return Values: 	SUCCESS / FAILURE
430*80c94ecdSKeith M Wesolowski  *			[Shall return failure if the initialization of the
431*80c94ecdSKeith M Wesolowski  *			controller to the Simple Transport Method fails]
432*80c94ecdSKeith M Wesolowski  */
433*80c94ecdSKeith M Wesolowski uint8_t
cpqary3_init_ctlr(cpqary3_t * cpqary3p)434*80c94ecdSKeith M Wesolowski cpqary3_init_ctlr(cpqary3_t *cpqary3p)
435*80c94ecdSKeith M Wesolowski {
436*80c94ecdSKeith M Wesolowski 	uint8_t				cntr;
437*80c94ecdSKeith M Wesolowski 	uint8_t				signature[4] = { 'C', 'I', 'S', 'S' };
438*80c94ecdSKeith M Wesolowski 	volatile CfgTable_t		*ctp;
439*80c94ecdSKeith M Wesolowski 	volatile CfgTrans_Perf_t	*perf_cfg;
440*80c94ecdSKeith M Wesolowski 	cpqary3_phyctg_t		*cpqary3_phyctgp;
441*80c94ecdSKeith M Wesolowski 	uint32_t			phy_addr;
442*80c94ecdSKeith M Wesolowski 	size_t				cmd_size;
443*80c94ecdSKeith M Wesolowski 	uint32_t			queue_depth;
444*80c94ecdSKeith M Wesolowski 	uint32_t			CmdsOutMax;
445*80c94ecdSKeith M Wesolowski 	uint32_t			BlockFetchCnt[8];
446*80c94ecdSKeith M Wesolowski 	caddr_t				replyq_start_addr = NULL;
447*80c94ecdSKeith M Wesolowski 	/* SG */
448*80c94ecdSKeith M Wesolowski 	uint32_t			max_blk_fetch_cnt = 0;
449*80c94ecdSKeith M Wesolowski 	uint32_t			max_sg_cnt = 0;
450*80c94ecdSKeith M Wesolowski 	uint32_t			optimal_sg = 0;
451*80c94ecdSKeith M Wesolowski 	uint32_t			optimal_sg_size = 0;
452*80c94ecdSKeith M Wesolowski 	/* Header + Request + Error */
453*80c94ecdSKeith M Wesolowski 	uint32_t			size_of_HRE = 0;
454*80c94ecdSKeith M Wesolowski 	uint32_t			size_of_cmdlist = 0;
455*80c94ecdSKeith M Wesolowski 	/* SG */
456*80c94ecdSKeith M Wesolowski 
457*80c94ecdSKeith M Wesolowski 	RETURN_FAILURE_IF_NULL(cpqary3p);
458*80c94ecdSKeith M Wesolowski 	ctp = (CfgTable_t *)cpqary3p->ct;
459*80c94ecdSKeith M Wesolowski 	perf_cfg = (CfgTrans_Perf_t *)cpqary3p->cp;
460*80c94ecdSKeith M Wesolowski 
461*80c94ecdSKeith M Wesolowski 	/* QUEUE CHANGES */
462*80c94ecdSKeith M Wesolowski 	cpqary3p->drvr_replyq =
463*80c94ecdSKeith M Wesolowski 	    (cpqary3_drvr_replyq_t *)MEM_ZALLOC(sizeof (cpqary3_drvr_replyq_t));
464*80c94ecdSKeith M Wesolowski 	/* QUEUE CHANGES */
465*80c94ecdSKeith M Wesolowski 
466*80c94ecdSKeith M Wesolowski 	if (!cpqary3_check_ctlr_init(cpqary3p))
467*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
468*80c94ecdSKeith M Wesolowski 
469*80c94ecdSKeith M Wesolowski 	DTRACE_PROBE1(ctlr_init_start, CfgTable_t *, ctp);
470*80c94ecdSKeith M Wesolowski 
471*80c94ecdSKeith M Wesolowski 	/*
472*80c94ecdSKeith M Wesolowski 	 * Validate the signature - should be "CISS"
473*80c94ecdSKeith M Wesolowski 	 * Use of cntr in the for loop does not suggest a counter - it just
474*80c94ecdSKeith M Wesolowski 	 * saves declaration of another variable.
475*80c94ecdSKeith M Wesolowski 	 */
476*80c94ecdSKeith M Wesolowski 
477*80c94ecdSKeith M Wesolowski 	for (cntr = 0; cntr < 4; cntr++) {
478*80c94ecdSKeith M Wesolowski 		if (DDI_GET8(cpqary3p, &ctp->Signature[cntr]) !=
479*80c94ecdSKeith M Wesolowski 		    signature[cntr]) {
480*80c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN, "CPQary3 : Controller NOT ready");
481*80c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN, "CPQary3 : _cpqary3_init_ctlr : "
482*80c94ecdSKeith M Wesolowski 			    "Signature not stamped");
483*80c94ecdSKeith M Wesolowski 			return (CPQARY3_FAILURE);
484*80c94ecdSKeith M Wesolowski 		}
485*80c94ecdSKeith M Wesolowski 	}
486*80c94ecdSKeith M Wesolowski 
487*80c94ecdSKeith M Wesolowski 
488*80c94ecdSKeith M Wesolowski 	if (!(cpqary3p->bddef->bd_flags & SA_BD_SAS)) {
489*80c94ecdSKeith M Wesolowski 		CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax);
490*80c94ecdSKeith M Wesolowski 
491*80c94ecdSKeith M Wesolowski 		if (CmdsOutMax == 0) {
492*80c94ecdSKeith M Wesolowski 			cmn_err(CE_CONT, "CPQary3 : HBA Maximum Outstanding "
493*80c94ecdSKeith M Wesolowski 			    "Commands set to Zero\n");
494*80c94ecdSKeith M Wesolowski 			cmn_err(CE_CONT, "CPQary3 : Cannot continue driver "
495*80c94ecdSKeith M Wesolowski 			    "initialization \n");
496*80c94ecdSKeith M Wesolowski 			return (CPQARY3_FAILURE);
497*80c94ecdSKeith M Wesolowski 		}
498*80c94ecdSKeith M Wesolowski 
499*80c94ecdSKeith M Wesolowski 		cpqary3p->ctlr_maxcmds = CmdsOutMax;
500*80c94ecdSKeith M Wesolowski 		cpqary3p->sg_cnt = CPQARY3_SG_CNT;
501*80c94ecdSKeith M Wesolowski 
502*80c94ecdSKeith M Wesolowski 		queue_depth = cpqary3p->ctlr_maxcmds;
503*80c94ecdSKeith M Wesolowski 		cmd_size = (8 * queue_depth);
504*80c94ecdSKeith M Wesolowski 		/* QUEUE CHANGES */
505*80c94ecdSKeith M Wesolowski 		cpqary3p->drvr_replyq->cyclic_indicator =
506*80c94ecdSKeith M Wesolowski 		    CPQARY3_REPLYQ_INIT_CYCLIC_IND;
507*80c94ecdSKeith M Wesolowski 		cpqary3p->drvr_replyq->simple_cyclic_indicator =
508*80c94ecdSKeith M Wesolowski 		    CPQARY3_REPLYQ_INIT_CYCLIC_IND;
509*80c94ecdSKeith M Wesolowski 		cpqary3p->drvr_replyq->max_index = cpqary3p->ctlr_maxcmds;
510*80c94ecdSKeith M Wesolowski 		cpqary3p->drvr_replyq->simple_index = 0;
511*80c94ecdSKeith M Wesolowski 		replyq_start_addr = MEM_ZALLOC(cmd_size);
512*80c94ecdSKeith M Wesolowski 		bzero(replyq_start_addr, cmd_size);
513*80c94ecdSKeith M Wesolowski 		cpqary3p->drvr_replyq->replyq_headptr =
514*80c94ecdSKeith M Wesolowski 		    /* LINTED: alignment */
515*80c94ecdSKeith M Wesolowski 		    (uint32_t *)replyq_start_addr;
516*80c94ecdSKeith M Wesolowski 		cpqary3p->drvr_replyq->replyq_simple_ptr =
517*80c94ecdSKeith M Wesolowski 		    /* LINTED: alignment */
518*80c94ecdSKeith M Wesolowski 		    (uint32_t *)replyq_start_addr;
519*80c94ecdSKeith M Wesolowski 		cpqary3p->drvr_replyq->replyq_start_addr = replyq_start_addr;
520*80c94ecdSKeith M Wesolowski 
521*80c94ecdSKeith M Wesolowski 		/* PERF */
522*80c94ecdSKeith M Wesolowski 
523*80c94ecdSKeith M Wesolowski 		/*
524*80c94ecdSKeith M Wesolowski 		 * Check for support of SIMPLE Transport Method
525*80c94ecdSKeith M Wesolowski 		 */
526*80c94ecdSKeith M Wesolowski 		if (!(DDI_GET32(cpqary3p, &ctp->TransportSupport) &
527*80c94ecdSKeith M Wesolowski 		    CFGTBL_XPORT_SIMPLE)) {
528*80c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN, "CPQary3 : Controller "
529*80c94ecdSKeith M Wesolowski 			    "NOT YET INITIALIZED");
530*80c94ecdSKeith M Wesolowski 			cmn_err(CE_CONT, "CPQary3 : For Hot Plug Operations, "
531*80c94ecdSKeith M Wesolowski 			    "try again later \n");
532*80c94ecdSKeith M Wesolowski 			return (CPQARY3_FAILURE);
533*80c94ecdSKeith M Wesolowski 		}
534*80c94ecdSKeith M Wesolowski 
535*80c94ecdSKeith M Wesolowski 		/*
536*80c94ecdSKeith M Wesolowski 		 * Configuration Table Initialization
537*80c94ecdSKeith M Wesolowski 		 * Set bit 0 of InBound Door Bell Reg to inform the controller
538*80c94ecdSKeith M Wesolowski 		 * about the changes related to the Configuration table
539*80c94ecdSKeith M Wesolowski 		 */
540*80c94ecdSKeith M Wesolowski 		DTRACE_PROBE(cfgtable_init_start);
541*80c94ecdSKeith M Wesolowski 
542*80c94ecdSKeith M Wesolowski 		DDI_PUT32(cpqary3p, &ctp->HostWrite.TransportRequest,
543*80c94ecdSKeith M Wesolowski 		    CFGTBL_XPORT_SIMPLE);
544*80c94ecdSKeith M Wesolowski 		ddi_put32(cpqary3p->idr_handle, (uint32_t *)cpqary3p->idr,
545*80c94ecdSKeith M Wesolowski 		    ddi_get32(cpqary3p->idr_handle, (uint32_t *)cpqary3p->idr) |
546*80c94ecdSKeith M Wesolowski 		    CFGTBL_CHANGE_REQ);
547*80c94ecdSKeith M Wesolowski 
548*80c94ecdSKeith M Wesolowski 		/*
549*80c94ecdSKeith M Wesolowski 		 * Check whether the controller is  ready
550*80c94ecdSKeith M Wesolowski 		 */
551*80c94ecdSKeith M Wesolowski 
552*80c94ecdSKeith M Wesolowski 		cntr = 0;
553*80c94ecdSKeith M Wesolowski 		while (ddi_get32(cpqary3p->idr_handle,
554*80c94ecdSKeith M Wesolowski 		    (uint32_t *)cpqary3p->idr) & CFGTBL_ACC_CMDS) {
555*80c94ecdSKeith M Wesolowski 			drv_usecwait(1000000); /* Wait for 1 Sec. */
556*80c94ecdSKeith M Wesolowski 			cntr++;
557*80c94ecdSKeith M Wesolowski 
558*80c94ecdSKeith M Wesolowski 			/*
559*80c94ecdSKeith M Wesolowski 			 * Wait for a maximum of 90 seconds. No f/w should take
560*80c94ecdSKeith M Wesolowski 			 * more than 90 secs to initialize. If the controller
561*80c94ecdSKeith M Wesolowski 			 * is not ready even after 90 secs, it suggests that
562*80c94ecdSKeith M Wesolowski 			 * something is wrong
563*80c94ecdSKeith M Wesolowski 			 * (wrt the controller, what else) !!!
564*80c94ecdSKeith M Wesolowski 			 */
565*80c94ecdSKeith M Wesolowski 
566*80c94ecdSKeith M Wesolowski 			if (cntr > CISS_INIT_TIME) /* 1.30 Mins */ {
567*80c94ecdSKeith M Wesolowski 				cmn_err(CE_CONT, "CPQary3 : Controller "
568*80c94ecdSKeith M Wesolowski 				    "Initialization Failed \n");
569*80c94ecdSKeith M Wesolowski 				return (CPQARY3_FAILURE);
570*80c94ecdSKeith M Wesolowski 			}
571*80c94ecdSKeith M Wesolowski 		}
572*80c94ecdSKeith M Wesolowski 
573*80c94ecdSKeith M Wesolowski 		DTRACE_PROBE(cfgtable_init_done);
574*80c94ecdSKeith M Wesolowski 
575*80c94ecdSKeith M Wesolowski 		/*
576*80c94ecdSKeith M Wesolowski 		 * Check whether controller accepts the requested method of
577*80c94ecdSKeith M Wesolowski 		 * transport
578*80c94ecdSKeith M Wesolowski 		 */
579*80c94ecdSKeith M Wesolowski 		if (!(DDI_GET32(cpqary3p, &ctp->TransportActive) &
580*80c94ecdSKeith M Wesolowski 		    CFGTBL_XPORT_SIMPLE)) {
581*80c94ecdSKeith M Wesolowski 			cmn_err(CE_CONT, "CPQary3 : Failed to Initialize "
582*80c94ecdSKeith M Wesolowski 			    "Controller \n");
583*80c94ecdSKeith M Wesolowski 			cmn_err(CE_CONT, "CPQary3 : For Hot Plug Operations, "
584*80c94ecdSKeith M Wesolowski 			    "try again later\n");
585*80c94ecdSKeith M Wesolowski 			return (CPQARY3_FAILURE);
586*80c94ecdSKeith M Wesolowski 		}
587*80c94ecdSKeith M Wesolowski 
588*80c94ecdSKeith M Wesolowski 		DTRACE_PROBE(ctlr_init_simple);
589*80c94ecdSKeith M Wesolowski 
590*80c94ecdSKeith M Wesolowski 		/*
591*80c94ecdSKeith M Wesolowski 		 * Check if Controller is ready to accept Commands
592*80c94ecdSKeith M Wesolowski 		 */
593*80c94ecdSKeith M Wesolowski 
594*80c94ecdSKeith M Wesolowski 		if (!(DDI_GET32(cpqary3p, &ctp->TransportActive) &
595*80c94ecdSKeith M Wesolowski 		    CFGTBL_ACC_CMDS)) {
596*80c94ecdSKeith M Wesolowski 			cmn_err(CE_CONT, "CPQary3: Controller NOT ready to "
597*80c94ecdSKeith M Wesolowski 			    "accept Commands \n");
598*80c94ecdSKeith M Wesolowski 			return (CPQARY3_FAILURE);
599*80c94ecdSKeith M Wesolowski 		}
600*80c94ecdSKeith M Wesolowski 
601*80c94ecdSKeith M Wesolowski 		DTRACE_PROBE(ctlr_init_ready);
602*80c94ecdSKeith M Wesolowski 
603*80c94ecdSKeith M Wesolowski 		/*
604*80c94ecdSKeith M Wesolowski 		 * Check if the maximum number of oustanding commands for the
605*80c94ecdSKeith M Wesolowski 		 * initialized controller is something greater than Zero.
606*80c94ecdSKeith M Wesolowski 		 */
607*80c94ecdSKeith M Wesolowski 
608*80c94ecdSKeith M Wesolowski 		CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax);
609*80c94ecdSKeith M Wesolowski 
610*80c94ecdSKeith M Wesolowski 		if (CmdsOutMax == 0) {
611*80c94ecdSKeith M Wesolowski 			cmn_err(CE_CONT, "CPQary3 : HBA Maximum Outstanding "
612*80c94ecdSKeith M Wesolowski 			    "Commands set to Zero\n");
613*80c94ecdSKeith M Wesolowski 			cmn_err(CE_CONT, "CPQary3 : Cannot continue driver "
614*80c94ecdSKeith M Wesolowski 			    "initialization \n");
615*80c94ecdSKeith M Wesolowski 			return (CPQARY3_FAILURE);
616*80c94ecdSKeith M Wesolowski 		}
617*80c94ecdSKeith M Wesolowski 		cpqary3p->ctlr_maxcmds = CmdsOutMax;
618*80c94ecdSKeith M Wesolowski 
619*80c94ecdSKeith M Wesolowski 		/*
620*80c94ecdSKeith M Wesolowski 		 * Zero the Upper 32 Address in the Controller
621*80c94ecdSKeith M Wesolowski 		 */
622*80c94ecdSKeith M Wesolowski 
623*80c94ecdSKeith M Wesolowski 		DDI_PUT32(cpqary3p, &ctp->HostWrite.Upper32Addr, 0x00000000);
624*80c94ecdSKeith M Wesolowski 		cpqary3p->heartbeat = DDI_GET32(cpqary3p, &ctp->HeartBeat);
625*80c94ecdSKeith M Wesolowski 
626*80c94ecdSKeith M Wesolowski 		/* Set the controller interrupt check routine */
627*80c94ecdSKeith M Wesolowski 		cpqary3p->check_ctlr_intr = cpqary3_check_simple_ctlr_intr;
628*80c94ecdSKeith M Wesolowski 
629*80c94ecdSKeith M Wesolowski 		cpqary3p->host_support =
630*80c94ecdSKeith M Wesolowski 		    DDI_GET32(cpqary3p, &ctp->HostDrvrSupport);
631*80c94ecdSKeith M Wesolowski 		DDI_PUT32(cpqary3p, &ctp->HostDrvrSupport,
632*80c94ecdSKeith M Wesolowski 		    (cpqary3p->host_support | 0x4));
633*80c94ecdSKeith M Wesolowski 		cpqary3p->host_support =
634*80c94ecdSKeith M Wesolowski 		    DDI_GET32(cpqary3p, &ctp->HostDrvrSupport);
635*80c94ecdSKeith M Wesolowski 
636*80c94ecdSKeith M Wesolowski 		cpqary3p->lockup_logged = CPQARY3_FALSE;
637*80c94ecdSKeith M Wesolowski 	} else {
638*80c94ecdSKeith M Wesolowski 	/* PERF */
639*80c94ecdSKeith M Wesolowski 
640*80c94ecdSKeith M Wesolowski 		/*
641*80c94ecdSKeith M Wesolowski 		 * Check for support of PERF Transport Method
642*80c94ecdSKeith M Wesolowski 		 */
643*80c94ecdSKeith M Wesolowski 		if (!(DDI_GET32(cpqary3p, &ctp->TransportSupport)
644*80c94ecdSKeith M Wesolowski 		    & CFGTBL_XPORT_PERFORMANT)) {
645*80c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN, "CPQary3 : Controller "
646*80c94ecdSKeith M Wesolowski 			    "NOT YET INITIALIZED");
647*80c94ecdSKeith M Wesolowski 			cmn_err(CE_CONT, "CPQary3 : For Hot Plug Operations, "
648*80c94ecdSKeith M Wesolowski 			    "try again later \n");
649*80c94ecdSKeith M Wesolowski 			return (CPQARY3_FAILURE);
650*80c94ecdSKeith M Wesolowski 		}
651*80c94ecdSKeith M Wesolowski 
652*80c94ecdSKeith M Wesolowski 		CmdsOutMax = DDI_GET32(cpqary3p, &ctp->MaxPerfModeCmdsOutMax);
653*80c94ecdSKeith M Wesolowski 		if (CmdsOutMax == 0)
654*80c94ecdSKeith M Wesolowski 			CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax);
655*80c94ecdSKeith M Wesolowski 		if (CmdsOutMax == 0) {
656*80c94ecdSKeith M Wesolowski 			cmn_err(CE_CONT, "CPQary3 : HBA Maximum Outstanding "
657*80c94ecdSKeith M Wesolowski 			    "Commands set to Zero\n");
658*80c94ecdSKeith M Wesolowski 			cmn_err(CE_CONT, "CPQary3 : Cannot continue driver "
659*80c94ecdSKeith M Wesolowski 			    "initialization \n");
660*80c94ecdSKeith M Wesolowski 			return (CPQARY3_FAILURE);
661*80c94ecdSKeith M Wesolowski 		}
662*80c94ecdSKeith M Wesolowski 
663*80c94ecdSKeith M Wesolowski 		cpqary3p->ctlr_maxcmds = CmdsOutMax;
664*80c94ecdSKeith M Wesolowski 
665*80c94ecdSKeith M Wesolowski 
666*80c94ecdSKeith M Wesolowski 		/* Initialize the Performant Method Transport Method Table */
667*80c94ecdSKeith M Wesolowski 
668*80c94ecdSKeith M Wesolowski 		queue_depth = cpqary3p->ctlr_maxcmds;
669*80c94ecdSKeith M Wesolowski 
670*80c94ecdSKeith M Wesolowski 		DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQSize, queue_depth);
671*80c94ecdSKeith M Wesolowski 		DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQCount, 1);
672*80c94ecdSKeith M Wesolowski 		DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQCntrAddrLow32, 0);
673*80c94ecdSKeith M Wesolowski 		DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQCntrAddrHigh32, 0);
674*80c94ecdSKeith M Wesolowski 
675*80c94ecdSKeith M Wesolowski 		cpqary3_phyctgp =
676*80c94ecdSKeith M Wesolowski 		    (cpqary3_phyctg_t *)MEM_ZALLOC(sizeof (cpqary3_phyctg_t));
677*80c94ecdSKeith M Wesolowski 
678*80c94ecdSKeith M Wesolowski 		if (!cpqary3_phyctgp) {
679*80c94ecdSKeith M Wesolowski 			cmn_err(CE_NOTE,
680*80c94ecdSKeith M Wesolowski 			    "CPQary3: Initial mem zalloc failed");
681*80c94ecdSKeith M Wesolowski 			return (CPQARY3_FAILURE);
682*80c94ecdSKeith M Wesolowski 		}
683*80c94ecdSKeith M Wesolowski 		cmd_size = (8 * queue_depth);
684*80c94ecdSKeith M Wesolowski 		phy_addr = 0;
685*80c94ecdSKeith M Wesolowski 		replyq_start_addr = cpqary3_alloc_phyctgs_mem(cpqary3p,
686*80c94ecdSKeith M Wesolowski 		    cmd_size, &phy_addr, cpqary3_phyctgp);
687*80c94ecdSKeith M Wesolowski 
688*80c94ecdSKeith M Wesolowski 		if (!replyq_start_addr) {
689*80c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN, "MEMALLOC returned failure");
690*80c94ecdSKeith M Wesolowski 			return (CPQARY3_FAILURE);
691*80c94ecdSKeith M Wesolowski 		}
692*80c94ecdSKeith M Wesolowski 
693*80c94ecdSKeith M Wesolowski 		bzero(replyq_start_addr, cmd_size);
694*80c94ecdSKeith M Wesolowski 		cpqary3p->drvr_replyq->replyq_headptr =
695*80c94ecdSKeith M Wesolowski 		    /* LINTED: alignment */
696*80c94ecdSKeith M Wesolowski 		    (uint32_t *)replyq_start_addr;
697*80c94ecdSKeith M Wesolowski 		cpqary3p->drvr_replyq->index = 0;
698*80c94ecdSKeith M Wesolowski 		cpqary3p->drvr_replyq->max_index = queue_depth;
699*80c94ecdSKeith M Wesolowski 		cpqary3p->drvr_replyq->replyq_start_addr = replyq_start_addr;
700*80c94ecdSKeith M Wesolowski 		cpqary3p->drvr_replyq->cyclic_indicator =
701*80c94ecdSKeith M Wesolowski 		    CPQARY3_REPLYQ_INIT_CYCLIC_IND;
702*80c94ecdSKeith M Wesolowski 		cpqary3p->drvr_replyq->replyq_start_paddr = phy_addr;
703*80c94ecdSKeith M Wesolowski 
704*80c94ecdSKeith M Wesolowski 		DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQAddr0Low32, phy_addr);
705*80c94ecdSKeith M Wesolowski 		DDI_PUT32_CP(cpqary3p, &perf_cfg->ReplyQAddr0High32, 0);
706*80c94ecdSKeith M Wesolowski 
707*80c94ecdSKeith M Wesolowski 		max_blk_fetch_cnt =
708*80c94ecdSKeith M Wesolowski 		    DDI_GET32(cpqary3p, &ctp->MaxBlockFetchCount);
709*80c94ecdSKeith M Wesolowski 
710*80c94ecdSKeith M Wesolowski 		/*
711*80c94ecdSKeith M Wesolowski 		 * For non-proton FW controllers, max_blk_fetch_count is not
712*80c94ecdSKeith M Wesolowski 		 * implemented in the firmware
713*80c94ecdSKeith M Wesolowski 		 */
714*80c94ecdSKeith M Wesolowski 
715*80c94ecdSKeith M Wesolowski 		/*
716*80c94ecdSKeith M Wesolowski 		 * When blk fetch count is 0, FW auto fetches 564 bytes
717*80c94ecdSKeith M Wesolowski 		 * corresponding to an optimal S/G of 31
718*80c94ecdSKeith M Wesolowski 		 */
719*80c94ecdSKeith M Wesolowski 		if (max_blk_fetch_cnt == 0) {
720*80c94ecdSKeith M Wesolowski 			BlockFetchCnt[0] = 35;
721*80c94ecdSKeith M Wesolowski 		} else {
722*80c94ecdSKeith M Wesolowski 			/*
723*80c94ecdSKeith M Wesolowski 			 * With MAX_PERF_SG_CNT set to 64, block fetch count
724*80c94ecdSKeith M Wesolowski 			 * is got by:(sizeof (CommandList_t) + 15)/16
725*80c94ecdSKeith M Wesolowski 			 */
726*80c94ecdSKeith M Wesolowski 			if (max_blk_fetch_cnt > 68)
727*80c94ecdSKeith M Wesolowski 				BlockFetchCnt[0] = 68;
728*80c94ecdSKeith M Wesolowski 			else
729*80c94ecdSKeith M Wesolowski 				BlockFetchCnt[0] = max_blk_fetch_cnt;
730*80c94ecdSKeith M Wesolowski 		}
731*80c94ecdSKeith M Wesolowski 
732*80c94ecdSKeith M Wesolowski 		DDI_PUT32_CP(cpqary3p, &perf_cfg->BlockFetchCnt[0],
733*80c94ecdSKeith M Wesolowski 		    BlockFetchCnt[0]);
734*80c94ecdSKeith M Wesolowski 		DDI_PUT32(cpqary3p, &ctp->HostWrite.TransportRequest,
735*80c94ecdSKeith M Wesolowski 		    CFGTBL_XPORT_PERFORMANT);
736*80c94ecdSKeith M Wesolowski 		ddi_put32(cpqary3p->idr_handle, (uint32_t *)cpqary3p->idr,
737*80c94ecdSKeith M Wesolowski 		    ddi_get32(cpqary3p->idr_handle, (uint32_t *)cpqary3p->idr) |
738*80c94ecdSKeith M Wesolowski 		    CFGTBL_CHANGE_REQ);
739*80c94ecdSKeith M Wesolowski 
740*80c94ecdSKeith M Wesolowski 		/*
741*80c94ecdSKeith M Wesolowski 		 * Check whether the controller is  ready
742*80c94ecdSKeith M Wesolowski 		 */
743*80c94ecdSKeith M Wesolowski 
744*80c94ecdSKeith M Wesolowski 		cntr = 0;
745*80c94ecdSKeith M Wesolowski 		while (ddi_get32(cpqary3p->idr_handle,
746*80c94ecdSKeith M Wesolowski 		    (uint32_t *)cpqary3p->idr) & CFGTBL_ACC_CMDS) {
747*80c94ecdSKeith M Wesolowski 			drv_usecwait(1000000); /* Wait for 1 Sec. */
748*80c94ecdSKeith M Wesolowski 			cntr++;
749*80c94ecdSKeith M Wesolowski 
750*80c94ecdSKeith M Wesolowski 
751*80c94ecdSKeith M Wesolowski 			/*
752*80c94ecdSKeith M Wesolowski 			 * Wait for a maximum of 90 seconds. No f/w should take
753*80c94ecdSKeith M Wesolowski 			 * more than 90 secs to initialize. If the controller
754*80c94ecdSKeith M Wesolowski 			 * is not ready even after 90 secs, it suggests that
755*80c94ecdSKeith M Wesolowski 			 * something is wrong
756*80c94ecdSKeith M Wesolowski 			 * (wrt the controller, what else) !!!
757*80c94ecdSKeith M Wesolowski 			 */
758*80c94ecdSKeith M Wesolowski 
759*80c94ecdSKeith M Wesolowski 			if (cntr > CISS_INIT_TIME) /* 1.30 Mins */ {
760*80c94ecdSKeith M Wesolowski 				cmn_err(CE_CONT, "CPQary3 : Controller "
761*80c94ecdSKeith M Wesolowski 				    "Initialization Failed \n");
762*80c94ecdSKeith M Wesolowski 				return (CPQARY3_FAILURE);
763*80c94ecdSKeith M Wesolowski 			}
764*80c94ecdSKeith M Wesolowski 		}
765*80c94ecdSKeith M Wesolowski 
766*80c94ecdSKeith M Wesolowski 		/*
767*80c94ecdSKeith M Wesolowski 		 * Check whether controller accepts the requested method of
768*80c94ecdSKeith M Wesolowski 		 * transport
769*80c94ecdSKeith M Wesolowski 		 */
770*80c94ecdSKeith M Wesolowski 
771*80c94ecdSKeith M Wesolowski 		if (!(DDI_GET32(cpqary3p, &ctp->TransportActive) &
772*80c94ecdSKeith M Wesolowski 		    CFGTBL_XPORT_PERFORMANT)) {
773*80c94ecdSKeith M Wesolowski 			cmn_err(CE_NOTE, "CPQary3 : Failed to Initialize "
774*80c94ecdSKeith M Wesolowski 			    "Controller");
775*80c94ecdSKeith M Wesolowski 			cmn_err(CE_CONT, "CPQary3 : For Hot Plug Operations, "
776*80c94ecdSKeith M Wesolowski 			    "try again later\n");
777*80c94ecdSKeith M Wesolowski 			DTRACE_PROBE1(ctlr_init_perf_fail, CfgTable_t *, ctp);
778*80c94ecdSKeith M Wesolowski 			return (CPQARY3_FAILURE);
779*80c94ecdSKeith M Wesolowski 		}
780*80c94ecdSKeith M Wesolowski 
781*80c94ecdSKeith M Wesolowski 		DTRACE_PROBE(ctlr_init_simple);
782*80c94ecdSKeith M Wesolowski 
783*80c94ecdSKeith M Wesolowski 		/*
784*80c94ecdSKeith M Wesolowski 		 * Check if Controller is ready to accept Commands
785*80c94ecdSKeith M Wesolowski 		 */
786*80c94ecdSKeith M Wesolowski 
787*80c94ecdSKeith M Wesolowski 		if (!(DDI_GET32(cpqary3p, &ctp->TransportActive) &
788*80c94ecdSKeith M Wesolowski 		    CFGTBL_ACC_CMDS)) {
789*80c94ecdSKeith M Wesolowski 			cmn_err(CE_NOTE, "CPQary3: Controller NOT ready to "
790*80c94ecdSKeith M Wesolowski 			    "accept Commands");
791*80c94ecdSKeith M Wesolowski 			return (CPQARY3_FAILURE);
792*80c94ecdSKeith M Wesolowski 		}
793*80c94ecdSKeith M Wesolowski 
794*80c94ecdSKeith M Wesolowski 		/*
795*80c94ecdSKeith M Wesolowski 		 * Check if the maximum number of oustanding commands for the
796*80c94ecdSKeith M Wesolowski 		 * initialized controller is something greater than Zero.
797*80c94ecdSKeith M Wesolowski 		 */
798*80c94ecdSKeith M Wesolowski 
799*80c94ecdSKeith M Wesolowski 		CmdsOutMax = DDI_GET32(cpqary3p, &ctp->MaxPerfModeCmdsOutMax);
800*80c94ecdSKeith M Wesolowski 		if (CmdsOutMax == 0)
801*80c94ecdSKeith M Wesolowski 			CmdsOutMax = DDI_GET32(cpqary3p, &ctp->CmdsOutMax);
802*80c94ecdSKeith M Wesolowski 
803*80c94ecdSKeith M Wesolowski 		if (CmdsOutMax == 0) {
804*80c94ecdSKeith M Wesolowski 			cmn_err(CE_NOTE, "CPQary3 : HBA Maximum Outstanding "
805*80c94ecdSKeith M Wesolowski 			    "Commands set to Zero");
806*80c94ecdSKeith M Wesolowski 			cmn_err(CE_NOTE, "CPQary3 : Cannot continue driver "
807*80c94ecdSKeith M Wesolowski 			    "initialization");
808*80c94ecdSKeith M Wesolowski 			return (CPQARY3_FAILURE);
809*80c94ecdSKeith M Wesolowski 		}
810*80c94ecdSKeith M Wesolowski 
811*80c94ecdSKeith M Wesolowski 		cpqary3p->ctlr_maxcmds = CmdsOutMax;
812*80c94ecdSKeith M Wesolowski 
813*80c94ecdSKeith M Wesolowski 		/* SG */
814*80c94ecdSKeith M Wesolowski 		max_sg_cnt = DDI_GET32(cpqary3p, &ctp->MaxSGElements);
815*80c94ecdSKeith M Wesolowski 		max_blk_fetch_cnt =
816*80c94ecdSKeith M Wesolowski 		    DDI_GET32(cpqary3p, &ctp->MaxBlockFetchCount);
817*80c94ecdSKeith M Wesolowski 
818*80c94ecdSKeith M Wesolowski 		/* 32 byte aligned - size_of_cmdlist */
819*80c94ecdSKeith M Wesolowski 		size_of_cmdlist = ((sizeof (CommandList_t) + 31) / 32) * 32;
820*80c94ecdSKeith M Wesolowski 		size_of_HRE  = size_of_cmdlist -
821*80c94ecdSKeith M Wesolowski 		    (sizeof (SGDescriptor_t) * CISS_MAXSGENTRIES);
822*80c94ecdSKeith M Wesolowski 
823*80c94ecdSKeith M Wesolowski 		if ((max_blk_fetch_cnt == 0) || (max_sg_cnt == 0) ||
824*80c94ecdSKeith M Wesolowski 		    ((max_blk_fetch_cnt * 16) <= size_of_HRE)) {
825*80c94ecdSKeith M Wesolowski 			cpqary3p->sg_cnt = CPQARY3_PERF_SG_CNT;
826*80c94ecdSKeith M Wesolowski 		} else {
827*80c94ecdSKeith M Wesolowski 			/*
828*80c94ecdSKeith M Wesolowski 			 * Get the optimal_sg - no of the SG's that will fit
829*80c94ecdSKeith M Wesolowski 			 * into the max_blk_fetch_cnt
830*80c94ecdSKeith M Wesolowski 			 */
831*80c94ecdSKeith M Wesolowski 
832*80c94ecdSKeith M Wesolowski 			optimal_sg_size =
833*80c94ecdSKeith M Wesolowski 			    (max_blk_fetch_cnt * 16) - size_of_HRE;
834*80c94ecdSKeith M Wesolowski 
835*80c94ecdSKeith M Wesolowski 			if (optimal_sg_size < sizeof (SGDescriptor_t)) {
836*80c94ecdSKeith M Wesolowski 				optimal_sg = CPQARY3_PERF_SG_CNT;
837*80c94ecdSKeith M Wesolowski 			} else {
838*80c94ecdSKeith M Wesolowski 				optimal_sg =
839*80c94ecdSKeith M Wesolowski 				    optimal_sg_size / sizeof (SGDescriptor_t);
840*80c94ecdSKeith M Wesolowski 			}
841*80c94ecdSKeith M Wesolowski 
842*80c94ecdSKeith M Wesolowski 			cpqary3p->sg_cnt = MIN(max_sg_cnt, optimal_sg);
843*80c94ecdSKeith M Wesolowski 
844*80c94ecdSKeith M Wesolowski 			if (cpqary3p->sg_cnt > MAX_PERF_SG_CNT)
845*80c94ecdSKeith M Wesolowski 				cpqary3p->sg_cnt = MAX_PERF_SG_CNT;
846*80c94ecdSKeith M Wesolowski 		}
847*80c94ecdSKeith M Wesolowski 
848*80c94ecdSKeith M Wesolowski 		/* SG */
849*80c94ecdSKeith M Wesolowski 
850*80c94ecdSKeith M Wesolowski 		/*
851*80c94ecdSKeith M Wesolowski 		 * Zero the Upper 32 Address in the Controller
852*80c94ecdSKeith M Wesolowski 		 */
853*80c94ecdSKeith M Wesolowski 
854*80c94ecdSKeith M Wesolowski 		DDI_PUT32(cpqary3p, &ctp->HostWrite.Upper32Addr, 0x00000000);
855*80c94ecdSKeith M Wesolowski 		cpqary3p->heartbeat = DDI_GET32(cpqary3p, &ctp->HeartBeat);
856*80c94ecdSKeith M Wesolowski 
857*80c94ecdSKeith M Wesolowski 		/* Set the controller interrupt check routine */
858*80c94ecdSKeith M Wesolowski 
859*80c94ecdSKeith M Wesolowski 		if (cpqary3p->bddef->bd_is_e200) {
860*80c94ecdSKeith M Wesolowski 			cpqary3p->check_ctlr_intr =
861*80c94ecdSKeith M Wesolowski 			    cpqary3_check_perf_e200_intr;
862*80c94ecdSKeith M Wesolowski 		} else {
863*80c94ecdSKeith M Wesolowski 			cpqary3p->check_ctlr_intr =
864*80c94ecdSKeith M Wesolowski 			    cpqary3_check_perf_ctlr_intr;
865*80c94ecdSKeith M Wesolowski 		}
866*80c94ecdSKeith M Wesolowski 
867*80c94ecdSKeith M Wesolowski 		if ((!cpqary3p->bddef->bd_is_e200) &&
868*80c94ecdSKeith M Wesolowski 		    (!cpqary3p->bddef->bd_is_ssll)) {
869*80c94ecdSKeith M Wesolowski 			cpqary3p->host_support =
870*80c94ecdSKeith M Wesolowski 			    DDI_GET32(cpqary3p, &ctp->HostDrvrSupport);
871*80c94ecdSKeith M Wesolowski 			DDI_PUT32(cpqary3p, &ctp->HostDrvrSupport,
872*80c94ecdSKeith M Wesolowski 			    (cpqary3p->host_support | 0x4));
873*80c94ecdSKeith M Wesolowski 		}
874*80c94ecdSKeith M Wesolowski 		cpqary3p->host_support =
875*80c94ecdSKeith M Wesolowski 		    DDI_GET32(cpqary3p, &ctp->HostDrvrSupport);
876*80c94ecdSKeith M Wesolowski 		cpqary3p->lockup_logged = CPQARY3_FALSE;
877*80c94ecdSKeith M Wesolowski 	}
878*80c94ecdSKeith M Wesolowski 
879*80c94ecdSKeith M Wesolowski 	return (CPQARY3_SUCCESS);
880*80c94ecdSKeith M Wesolowski }
881*80c94ecdSKeith M Wesolowski 
882*80c94ecdSKeith M Wesolowski /*
883*80c94ecdSKeith M Wesolowski  * Function	: 	cpqary3_check_ctlr_init
884*80c94ecdSKeith M Wesolowski  * Description	: 	This routine checks to see if the HBA is initialized.
885*80c94ecdSKeith M Wesolowski  * Called By	: 	cpqary3_init_ctlr()
886*80c94ecdSKeith M Wesolowski  * Parameters	: 	per-controller
887*80c94ecdSKeith M Wesolowski  * Calls	: 	None
888*80c94ecdSKeith M Wesolowski  * Return Values: 	SUCCESS / FAILURE
889*80c94ecdSKeith M Wesolowski  */
890*80c94ecdSKeith M Wesolowski uint8_t
cpqary3_check_ctlr_init(cpqary3_t * cpqary3p)891*80c94ecdSKeith M Wesolowski cpqary3_check_ctlr_init(cpqary3_t *cpqary3p)
892*80c94ecdSKeith M Wesolowski {
893*80c94ecdSKeith M Wesolowski 	int8_t				retvalue;
894*80c94ecdSKeith M Wesolowski 	uint16_t			i;
895*80c94ecdSKeith M Wesolowski 	uint32_t			*ctlr_init;
896*80c94ecdSKeith M Wesolowski 	ddi_acc_handle_t		ctlr_init_handle;
897*80c94ecdSKeith M Wesolowski 	extern ddi_device_acc_attr_t	cpqary3_dev_attributes;
898*80c94ecdSKeith M Wesolowski 
899*80c94ecdSKeith M Wesolowski 	RETURN_FAILURE_IF_NULL(cpqary3p);
900*80c94ecdSKeith M Wesolowski 
901*80c94ecdSKeith M Wesolowski 	/*
902*80c94ecdSKeith M Wesolowski 	 * Set up the mapping for a Register at offset 0xB0 from I2O Bar
903*80c94ecdSKeith M Wesolowski 	 * The value 0xB0 taken from the CONFIGM utility.
904*80c94ecdSKeith M Wesolowski 	 * It should read 0xffff0000 if the controller is initialized.
905*80c94ecdSKeith M Wesolowski 	 * if not yet initialized, read it every second for 300 secs.
906*80c94ecdSKeith M Wesolowski 	 * If not set even after 300 secs, return FAILURE.
907*80c94ecdSKeith M Wesolowski 	 * If set, free the mapping and continue
908*80c94ecdSKeith M Wesolowski 	 */
909*80c94ecdSKeith M Wesolowski 	retvalue = ddi_regs_map_setup(cpqary3p->dip, INDEX_PCI_BASE0,
910*80c94ecdSKeith M Wesolowski 	    (caddr_t *)&ctlr_init, (offset_t)I2O_CTLR_INIT, 4,
911*80c94ecdSKeith M Wesolowski 	    &cpqary3_dev_attributes, &ctlr_init_handle);
912*80c94ecdSKeith M Wesolowski 
913*80c94ecdSKeith M Wesolowski 	if (retvalue != DDI_SUCCESS) {
914*80c94ecdSKeith M Wesolowski 		if (DDI_REGS_ACC_CONFLICT == retvalue)
915*80c94ecdSKeith M Wesolowski 			cmn_err(CE_WARN,
916*80c94ecdSKeith M Wesolowski 			    "CPQary3 : HBA Init Register Mapping Conflict");
917*80c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN,
918*80c94ecdSKeith M Wesolowski 		    "CPQary3 : HBA Init Regsiter Mapping Failed");
919*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
920*80c94ecdSKeith M Wesolowski 	}
921*80c94ecdSKeith M Wesolowski 
922*80c94ecdSKeith M Wesolowski 	for (i = 0; i < 300; i++) {	/* loop for 300 seconds */
923*80c94ecdSKeith M Wesolowski 		if (CISS_CTLR_INIT == ddi_get32(ctlr_init_handle, ctlr_init)) {
924*80c94ecdSKeith M Wesolowski 			DTRACE_PROBE(ctlr_init_check_ready);
925*80c94ecdSKeith M Wesolowski 			ddi_regs_map_free(&ctlr_init_handle);
926*80c94ecdSKeith M Wesolowski 			break;
927*80c94ecdSKeith M Wesolowski 		} else {
928*80c94ecdSKeith M Wesolowski 			DTRACE_PROBE(ctlr_init_check_notready);
929*80c94ecdSKeith M Wesolowski 			delay(drv_usectohz(1000000));
930*80c94ecdSKeith M Wesolowski 		}
931*80c94ecdSKeith M Wesolowski 	}
932*80c94ecdSKeith M Wesolowski 
933*80c94ecdSKeith M Wesolowski 	if (i >= 300) {	/* HBA not initialized even after 300 seconds !!! */
934*80c94ecdSKeith M Wesolowski 		ddi_regs_map_free(&ctlr_init_handle);
935*80c94ecdSKeith M Wesolowski 		cmn_err(CE_WARN, "CPQary3 : %s NOT initialized !!! HBA may not "
936*80c94ecdSKeith M Wesolowski 		    "function properly. Please replace the hardware or check "
937*80c94ecdSKeith M Wesolowski 		    "the connections", cpqary3p->hba_name);
938*80c94ecdSKeith M Wesolowski 		return (CPQARY3_FAILURE);
939*80c94ecdSKeith M Wesolowski 	}
940*80c94ecdSKeith M Wesolowski 
941*80c94ecdSKeith M Wesolowski 	return (CPQARY3_SUCCESS);
942*80c94ecdSKeith M Wesolowski }
943