1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte  * CDDL HEADER START
3fcf3ce44SJohn Forte  *
4fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte  *
8*8f23e9faSHans Rosenfeld  * You can obtain a copy of the license at
9*8f23e9faSHans Rosenfeld  * http://www.opensource.org/licenses/cddl1.txt.
10fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte  * and limitations under the License.
12fcf3ce44SJohn Forte  *
13fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte  *
19fcf3ce44SJohn Forte  * CDDL HEADER END
20fcf3ce44SJohn Forte  */
21fcf3ce44SJohn Forte 
22fcf3ce44SJohn Forte /*
23*8f23e9faSHans Rosenfeld  * Copyright (c) 2004-2012 Emulex. All rights reserved.
2482527734SSukumar Swaminathan  * Use is subject to license terms.
25fcf3ce44SJohn Forte  */
26fcf3ce44SJohn Forte 
27291a2b48SSukumar Swaminathan #include <emlxs.h>
28fcf3ce44SJohn Forte 
29fcf3ce44SJohn Forte 
30fcf3ce44SJohn Forte /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31fcf3ce44SJohn Forte EMLXS_MSG_DEF(EMLXS_DIAG_C);
32fcf3ce44SJohn Forte 
33291a2b48SSukumar Swaminathan uint32_t emlxs_diag_pattern[256] = {
34fcf3ce44SJohn Forte 	/* Walking ones */
35fcf3ce44SJohn Forte 	0x80000000, 0x40000000, 0x20000000, 0x10000000,
36fcf3ce44SJohn Forte 	0x08000000, 0x04000000, 0x02000000, 0x01000000,
37fcf3ce44SJohn Forte 	0x00800000, 0x00400000, 0x00200000, 0x00100000,
38fcf3ce44SJohn Forte 	0x00080000, 0x00040000, 0x00020000, 0x00010000,
39fcf3ce44SJohn Forte 	0x00008000, 0x00004000, 0x00002000, 0x00001000,
40fcf3ce44SJohn Forte 	0x00000800, 0x00000400, 0x00000200, 0x00000100,
41fcf3ce44SJohn Forte 	0x00000080, 0x00000040, 0x00000020, 0x00000010,
42fcf3ce44SJohn Forte 	0x00000008, 0x00000004, 0x00000002, 0x00000001,
43fcf3ce44SJohn Forte 
44fcf3ce44SJohn Forte 	/* Walking zeros */
45fcf3ce44SJohn Forte 	0x7fffffff, 0xbfffffff, 0xdfffffff, 0xefffffff,
46fcf3ce44SJohn Forte 	0xf7ffffff, 0xfbffffff, 0xfdffffff, 0xfeffffff,
47fcf3ce44SJohn Forte 	0xff7fffff, 0xffbfffff, 0xffdfffff, 0xffefffff,
48fcf3ce44SJohn Forte 	0xfff7ffff, 0xfffbffff, 0xfffdffff, 0xfffeffff,
49fcf3ce44SJohn Forte 	0xffff7fff, 0xffffbfff, 0xffffdfff, 0xffffefff,
50fcf3ce44SJohn Forte 	0xfffff7ff, 0xfffffbff, 0xfffffdff, 0xfffffeff,
51fcf3ce44SJohn Forte 	0xffffff7f, 0xffffffbf, 0xffffffdf, 0xffffffef,
52fcf3ce44SJohn Forte 	0xfffffff7, 0xfffffffb, 0xfffffffd, 0xfffffffe,
53fcf3ce44SJohn Forte 
54fcf3ce44SJohn Forte 	/* all zeros */
55fcf3ce44SJohn Forte 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
56fcf3ce44SJohn Forte 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
57fcf3ce44SJohn Forte 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
58fcf3ce44SJohn Forte 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
59fcf3ce44SJohn Forte 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
60fcf3ce44SJohn Forte 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
61fcf3ce44SJohn Forte 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
62fcf3ce44SJohn Forte 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
63fcf3ce44SJohn Forte 
64fcf3ce44SJohn Forte 	/* all ones */
65fcf3ce44SJohn Forte 	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
66fcf3ce44SJohn Forte 	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
67fcf3ce44SJohn Forte 	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
68fcf3ce44SJohn Forte 	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
69fcf3ce44SJohn Forte 	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
70fcf3ce44SJohn Forte 	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
71fcf3ce44SJohn Forte 	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
72fcf3ce44SJohn Forte 	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
73fcf3ce44SJohn Forte 
74fcf3ce44SJohn Forte 	/* all 5's */
75fcf3ce44SJohn Forte 	0x55555555, 0x55555555, 0x55555555, 0x55555555,
76fcf3ce44SJohn Forte 	0x55555555, 0x55555555, 0x55555555, 0x55555555,
77fcf3ce44SJohn Forte 	0x55555555, 0x55555555, 0x55555555, 0x55555555,
78fcf3ce44SJohn Forte 	0x55555555, 0x55555555, 0x55555555, 0x55555555,
79fcf3ce44SJohn Forte 	0x55555555, 0x55555555, 0x55555555, 0x55555555,
80fcf3ce44SJohn Forte 	0x55555555, 0x55555555, 0x55555555, 0x55555555,
81fcf3ce44SJohn Forte 	0x55555555, 0x55555555, 0x55555555, 0x55555555,
82fcf3ce44SJohn Forte 	0x55555555, 0x55555555, 0x55555555, 0x55555555,
83fcf3ce44SJohn Forte 
84fcf3ce44SJohn Forte 	/* all a's */
85fcf3ce44SJohn Forte 	0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
86fcf3ce44SJohn Forte 	0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
87fcf3ce44SJohn Forte 	0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
88fcf3ce44SJohn Forte 	0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
89fcf3ce44SJohn Forte 	0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
90fcf3ce44SJohn Forte 	0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
91fcf3ce44SJohn Forte 	0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
92fcf3ce44SJohn Forte 	0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa,
93fcf3ce44SJohn Forte 
94fcf3ce44SJohn Forte 	/* all 5a's */
95fcf3ce44SJohn Forte 	0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
96fcf3ce44SJohn Forte 	0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
97fcf3ce44SJohn Forte 	0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
98fcf3ce44SJohn Forte 	0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
99fcf3ce44SJohn Forte 	0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
100fcf3ce44SJohn Forte 	0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
101fcf3ce44SJohn Forte 	0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
102fcf3ce44SJohn Forte 	0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a, 0x5a5a5a5a,
103fcf3ce44SJohn Forte 
104fcf3ce44SJohn Forte 	/* all a5's */
105fcf3ce44SJohn Forte 	0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
106fcf3ce44SJohn Forte 	0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
107fcf3ce44SJohn Forte 	0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
108fcf3ce44SJohn Forte 	0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
109fcf3ce44SJohn Forte 	0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
110fcf3ce44SJohn Forte 	0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
111fcf3ce44SJohn Forte 	0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5,
112fcf3ce44SJohn Forte 	0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5, 0xa5a5a5a5
113fcf3ce44SJohn Forte };
114fcf3ce44SJohn Forte 
115fcf3ce44SJohn Forte 
116fcf3ce44SJohn Forte /* Default pkt callback routine */
117fcf3ce44SJohn Forte static void
emlxs_diag_pkt_callback(fc_packet_t * pkt)118fcf3ce44SJohn Forte emlxs_diag_pkt_callback(fc_packet_t *pkt)
119fcf3ce44SJohn Forte {
120fcf3ce44SJohn Forte 	emlxs_port_t *port = (emlxs_port_t *)pkt->pkt_ulp_private;
121fcf3ce44SJohn Forte 
122fcf3ce44SJohn Forte 	/* Set the completed flag and wake up sleeping threads */
123fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PKT_LOCK);
124fcf3ce44SJohn Forte 	pkt->pkt_tran_flags |= FC_TRAN_COMPLETED;
125fcf3ce44SJohn Forte 	cv_broadcast(&EMLXS_PKT_CV);
126fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PKT_LOCK);
127fcf3ce44SJohn Forte 
128fcf3ce44SJohn Forte 	return;
129fcf3ce44SJohn Forte 
13082527734SSukumar Swaminathan } /* emlxs_diag_pkt_callback() */
131fcf3ce44SJohn Forte 
132fcf3ce44SJohn Forte 
133fcf3ce44SJohn Forte extern uint32_t
emlxs_diag_echo_run(emlxs_port_t * port,uint32_t did,uint32_t pattern)134fcf3ce44SJohn Forte emlxs_diag_echo_run(emlxs_port_t *port, uint32_t did, uint32_t pattern)
135fcf3ce44SJohn Forte {
136fcf3ce44SJohn Forte 	emlxs_hba_t *hba = HBA;
137fcf3ce44SJohn Forte 	uint32_t i = 0;
138fcf3ce44SJohn Forte 	uint32_t rval = FC_SUCCESS;
139fcf3ce44SJohn Forte 	int32_t pkt_ret;
140fcf3ce44SJohn Forte 	fc_packet_t *pkt;
141fcf3ce44SJohn Forte 	ELS_PKT *els;
142fcf3ce44SJohn Forte 	clock_t timeout;
143fcf3ce44SJohn Forte 	uint8_t *pkt_resp;
144fcf3ce44SJohn Forte 	char *pattern_buffer;
145fcf3ce44SJohn Forte 	uint32_t length;
146fcf3ce44SJohn Forte 	uint32_t *lptr;
147fcf3ce44SJohn Forte 	NODELIST *ndlp;
148fcf3ce44SJohn Forte 	uint8_t *pat;
149fcf3ce44SJohn Forte 
150fcf3ce44SJohn Forte 	/* Check did */
151fcf3ce44SJohn Forte 	if (did == 0) {
152fcf3ce44SJohn Forte 		did = port->did;
153fcf3ce44SJohn Forte 	}
154291a2b48SSukumar Swaminathan 
155fcf3ce44SJohn Forte 	/* Check if device is ready */
156fcf3ce44SJohn Forte 	if ((hba->state < FC_LINK_UP) || (port->did == 0)) {
157fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
158fcf3ce44SJohn Forte 		    "ECHO: HBA not ready.");
159fcf3ce44SJohn Forte 
160fcf3ce44SJohn Forte 		return (FC_TRAN_BUSY);
161fcf3ce44SJohn Forte 	}
162291a2b48SSukumar Swaminathan 
163fcf3ce44SJohn Forte 	/* Check for the host node */
164*8f23e9faSHans Rosenfeld 	ndlp = emlxs_node_find_did(port, port->did, 1);
165fcf3ce44SJohn Forte 
166fcf3ce44SJohn Forte 	if (!ndlp || !ndlp->nlp_active) {
167fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
168fcf3ce44SJohn Forte 		    "ECHO: HBA not ready.");
169fcf3ce44SJohn Forte 
170fcf3ce44SJohn Forte 		return (FC_TRAN_BUSY);
171fcf3ce44SJohn Forte 	}
172291a2b48SSukumar Swaminathan 
173fcf3ce44SJohn Forte 	length = 124;
174fcf3ce44SJohn Forte 
175fcf3ce44SJohn Forte 	/* Prepare ECHO pkt */
176fcf3ce44SJohn Forte 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (uint32_t) + length,
177fcf3ce44SJohn Forte 	    sizeof (uint32_t) + length, 0, KM_NOSLEEP))) {
178fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
179fcf3ce44SJohn Forte 		    "ECHO: Unable to allocate packet. size=%x",
180fcf3ce44SJohn Forte 		    sizeof (uint32_t) + length);
181fcf3ce44SJohn Forte 
182fcf3ce44SJohn Forte 		return (FC_NOMEM);
183fcf3ce44SJohn Forte 	}
184291a2b48SSukumar Swaminathan 
185fcf3ce44SJohn Forte 	/* pkt initialization */
186fcf3ce44SJohn Forte 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
187fcf3ce44SJohn Forte 	pkt->pkt_timeout = 60;
188fcf3ce44SJohn Forte 
189fcf3ce44SJohn Forte 	/* Build the fc header */
190fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.d_id = did;
191fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_EXTENDED_SVC | R_CTL_UNSOL_CONTROL;
192fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.s_id = port->did;
193fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
194291a2b48SSukumar Swaminathan 	pkt->pkt_cmd_fhdr.f_ctl =
195291a2b48SSukumar Swaminathan 	    F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE | F_CTL_END_SEQ;
196fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_id = 0;
197fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.df_ctl = 0;
198fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
199fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
200fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.rx_id = 0xffff;
201fcf3ce44SJohn Forte 	pkt->pkt_cmd_fhdr.ro = 0;
202fcf3ce44SJohn Forte 	pkt->pkt_comp = emlxs_diag_pkt_callback;
203fcf3ce44SJohn Forte 
204fcf3ce44SJohn Forte 	/* Build the command */
205291a2b48SSukumar Swaminathan 	els = (ELS_PKT *) pkt->pkt_cmd;
206fcf3ce44SJohn Forte 	els->elsCode = 0x10;
207fcf3ce44SJohn Forte 	pattern_buffer = (char *)els->un.pad;
208fcf3ce44SJohn Forte 
209fcf3ce44SJohn Forte 	if (pattern) {
210fcf3ce44SJohn Forte 		/* Fill the transmit buffer with the pattern */
211fcf3ce44SJohn Forte 		lptr = (uint32_t *)pattern_buffer;
212fcf3ce44SJohn Forte 
213fcf3ce44SJohn Forte 		for (i = 0; i < length; i += 4) {
214fcf3ce44SJohn Forte 			*lptr++ = pattern;
215fcf3ce44SJohn Forte 		}
216fcf3ce44SJohn Forte 	} else {
217fcf3ce44SJohn Forte 		/* Program the default echo pattern */
218fcf3ce44SJohn Forte 		bzero(pattern_buffer, length);
219*8f23e9faSHans Rosenfeld 		(void) snprintf(pattern_buffer, length,
220291a2b48SSukumar Swaminathan 		    "Emulex. We network storage. Emulex. We network storage. "
221*8f23e9faSHans Rosenfeld 		    "Emulex. We network storage. Emulex. We network storage.");
222fcf3ce44SJohn Forte 	}
223fcf3ce44SJohn Forte 
224fcf3ce44SJohn Forte 	/* Send ECHO pkt */
225fcf3ce44SJohn Forte 	if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) {
226fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
227fcf3ce44SJohn Forte 		    "ECHO: Packet send failed.");
228fcf3ce44SJohn Forte 
229fcf3ce44SJohn Forte 		goto done;
230fcf3ce44SJohn Forte 	}
231291a2b48SSukumar Swaminathan 
232fcf3ce44SJohn Forte 	/* Wait for ECHO completion */
233fcf3ce44SJohn Forte 	mutex_enter(&EMLXS_PKT_LOCK);
234fcf3ce44SJohn Forte 	timeout = emlxs_timeout(hba, (pkt->pkt_timeout + 15));
235fcf3ce44SJohn Forte 	pkt_ret = 0;
236fcf3ce44SJohn Forte 	while ((pkt_ret != -1) && !(pkt->pkt_tran_flags & FC_TRAN_COMPLETED)) {
237291a2b48SSukumar Swaminathan 		pkt_ret =
238291a2b48SSukumar Swaminathan 		    cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK, timeout);
239fcf3ce44SJohn Forte 
240fcf3ce44SJohn Forte 	}
241fcf3ce44SJohn Forte 	mutex_exit(&EMLXS_PKT_LOCK);
242fcf3ce44SJohn Forte 
243fcf3ce44SJohn Forte 	if (pkt_ret == -1) {
244fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_echo_failed_msg,
245fcf3ce44SJohn Forte 		    "Packet timed out.");
246fcf3ce44SJohn Forte 
247fcf3ce44SJohn Forte 		return (FC_ABORTED);
248fcf3ce44SJohn Forte 	}
249291a2b48SSukumar Swaminathan 
250fcf3ce44SJohn Forte 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
251fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_echo_failed_msg,
252fcf3ce44SJohn Forte 		    "Transport error.");
253fcf3ce44SJohn Forte 
254fcf3ce44SJohn Forte 		rval = FC_TRANSPORT_ERROR;
255fcf3ce44SJohn Forte 		goto done;
256fcf3ce44SJohn Forte 	}
257291a2b48SSukumar Swaminathan 
258fcf3ce44SJohn Forte 	/* Check response payload */
259fcf3ce44SJohn Forte 	pkt_resp = (uint8_t *)pkt->pkt_resp + 4;
260fcf3ce44SJohn Forte 	pat = (uint8_t *)pattern_buffer;
261fcf3ce44SJohn Forte 	rval = FC_SUCCESS;
262fcf3ce44SJohn Forte 
263fcf3ce44SJohn Forte 	for (i = 0; i < length; i++, pkt_resp++, pat++) {
264fcf3ce44SJohn Forte 		if (*pkt_resp != *pat) {
265fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_echo_failed_msg,
266fcf3ce44SJohn Forte 			    "Data miscompare. did=%06x length=%d. Offset %d "
267291a2b48SSukumar Swaminathan 			    "value %02x should be %02x.", did, length, i,
268291a2b48SSukumar Swaminathan 			    *pkt_resp, *pat);
269fcf3ce44SJohn Forte 
270fcf3ce44SJohn Forte 			rval = EMLXS_TEST_FAILED;
271fcf3ce44SJohn Forte 
272fcf3ce44SJohn Forte 			break;
273fcf3ce44SJohn Forte 		}
274fcf3ce44SJohn Forte 	}
275fcf3ce44SJohn Forte 
276fcf3ce44SJohn Forte 	if (rval == FC_SUCCESS) {
277fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_echo_complete_msg,
278fcf3ce44SJohn Forte 		    "did=%06x  length=%d  pattern=%02x,%02x,%02x,%02x...",
279fcf3ce44SJohn Forte 		    did, length, pattern_buffer[0] & 0xff,
280fcf3ce44SJohn Forte 		    pattern_buffer[1] & 0xff, pattern_buffer[2] & 0xff,
281fcf3ce44SJohn Forte 		    pattern_buffer[3] & 0xff);
282fcf3ce44SJohn Forte 	}
283291a2b48SSukumar Swaminathan 
284fcf3ce44SJohn Forte done:
285fcf3ce44SJohn Forte 
286fcf3ce44SJohn Forte 	/* Free the echo pkt */
287fcf3ce44SJohn Forte 	emlxs_pkt_free(pkt);
288fcf3ce44SJohn Forte 
289fcf3ce44SJohn Forte 	return (rval);
290fcf3ce44SJohn Forte 
29182527734SSukumar Swaminathan } /* emlxs_diag_echo_run() */
292fcf3ce44SJohn Forte 
293fcf3ce44SJohn Forte 
294fcf3ce44SJohn Forte extern uint32_t
emlxs_diag_biu_run(emlxs_hba_t * hba,uint32_t pattern)295fcf3ce44SJohn Forte emlxs_diag_biu_run(emlxs_hba_t *hba, uint32_t pattern)
296fcf3ce44SJohn Forte {
297fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
298*8f23e9faSHans Rosenfeld 	MAILBOXQ *mbq = NULL;
299*8f23e9faSHans Rosenfeld 	MATCHMAP *mp = NULL;
300*8f23e9faSHans Rosenfeld 	MATCHMAP *mp1 = NULL;
301fcf3ce44SJohn Forte 	uint32_t i;
302fcf3ce44SJohn Forte 	uint8_t *inptr;
303fcf3ce44SJohn Forte 	uint8_t *outptr;
304fcf3ce44SJohn Forte 	int32_t rval = FC_SUCCESS;
305fcf3ce44SJohn Forte 	uint32_t *lptr;
306fcf3ce44SJohn Forte 
307fcf3ce44SJohn Forte 	/* Check if device is ready */
308fcf3ce44SJohn Forte 	if (hba->state < FC_LINK_DOWN) {
309fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
310fcf3ce44SJohn Forte 		    "BIU: HBA not ready.");
311fcf3ce44SJohn Forte 
312fcf3ce44SJohn Forte 		return (FC_TRAN_BUSY);
313fcf3ce44SJohn Forte 	}
314291a2b48SSukumar Swaminathan 
315fcf3ce44SJohn Forte 	/*
316fcf3ce44SJohn Forte 	 * Get a buffer which will be used for the mailbox command
317fcf3ce44SJohn Forte 	 */
318*8f23e9faSHans Rosenfeld 	if ((mbq = (MAILBOXQ *) emlxs_mem_get(hba, MEM_MBOX)) == 0) {
319fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
320fcf3ce44SJohn Forte 		    "BIU: Mailbox allocation failed.");
321fcf3ce44SJohn Forte 
322fcf3ce44SJohn Forte 		rval = FC_NOMEM;
323fcf3ce44SJohn Forte 		goto done;
324fcf3ce44SJohn Forte 	}
325291a2b48SSukumar Swaminathan 
326fcf3ce44SJohn Forte 	/*
327fcf3ce44SJohn Forte 	 * Setup and issue mailbox RUN BIU DIAG command Setup test buffers
328fcf3ce44SJohn Forte 	 */
329*8f23e9faSHans Rosenfeld 	if (((mp = (MATCHMAP *) emlxs_mem_get(hba, MEM_BUF)) == 0) ||
330*8f23e9faSHans Rosenfeld 	    ((mp1 = (MATCHMAP *) emlxs_mem_get(hba, MEM_BUF)) == 0)) {
331fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
332fcf3ce44SJohn Forte 		    "BIU: Buffer allocation failed.");
333fcf3ce44SJohn Forte 
334fcf3ce44SJohn Forte 		rval = FC_NOMEM;
335fcf3ce44SJohn Forte 		goto done;
336fcf3ce44SJohn Forte 	}
337291a2b48SSukumar Swaminathan 
338fcf3ce44SJohn Forte 	if (pattern) {
339fcf3ce44SJohn Forte 		/* Fill the transmit buffer with the pattern */
340fcf3ce44SJohn Forte 		lptr = (uint32_t *)mp->virt;
341fcf3ce44SJohn Forte 
342fcf3ce44SJohn Forte 		for (i = 0; i < MEM_ELSBUF_SIZE; i += 4) {
343fcf3ce44SJohn Forte 			*lptr++ = pattern;
344fcf3ce44SJohn Forte 		}
345fcf3ce44SJohn Forte 	} else {
346fcf3ce44SJohn Forte 		/* Copy the default pattern into the trasmit buffer */
347fcf3ce44SJohn Forte 		bcopy((caddr_t)&emlxs_diag_pattern[0], (caddr_t)mp->virt,
348fcf3ce44SJohn Forte 		    MEM_ELSBUF_SIZE);
349fcf3ce44SJohn Forte 	}
35082527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(mp->dma_handle, 0, MEM_ELSBUF_SIZE,
351fcf3ce44SJohn Forte 	    DDI_DMA_SYNC_FORDEV);
352fcf3ce44SJohn Forte 
353fcf3ce44SJohn Forte 	bzero(mp1->virt, MEM_ELSBUF_SIZE);
35482527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE,
355fcf3ce44SJohn Forte 	    DDI_DMA_SYNC_FORDEV);
356fcf3ce44SJohn Forte 
357fcf3ce44SJohn Forte 	/* Create the biu diag request */
35882527734SSukumar Swaminathan 	(void) emlxs_mb_run_biu_diag(hba, mbq, mp->phys, mp1->phys);
359fcf3ce44SJohn Forte 
36082527734SSukumar Swaminathan 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 60);
361fcf3ce44SJohn Forte 
362fcf3ce44SJohn Forte 	if (rval == MBX_TIMEOUT) {
363fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_biu_failed_msg,
364fcf3ce44SJohn Forte 		    "BUI diagnostic timed out.");
365fcf3ce44SJohn Forte 
366fcf3ce44SJohn Forte 		rval = EMLXS_TEST_FAILED;
367fcf3ce44SJohn Forte 		goto done;
368fcf3ce44SJohn Forte 	}
369291a2b48SSukumar Swaminathan 
37082527734SSukumar Swaminathan 	EMLXS_MPDATA_SYNC(mp1->dma_handle, 0, MEM_ELSBUF_SIZE,
371fcf3ce44SJohn Forte 	    DDI_DMA_SYNC_FORKERNEL);
372fcf3ce44SJohn Forte 
373fcf3ce44SJohn Forte 	outptr = mp->virt;
374fcf3ce44SJohn Forte 	inptr = mp1->virt;
375fcf3ce44SJohn Forte 
376fcf3ce44SJohn Forte 	for (i = 0; i < MEM_ELSBUF_SIZE; i++, outptr++, inptr++) {
377fcf3ce44SJohn Forte 		if (*outptr != *inptr) {
378fcf3ce44SJohn Forte 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_biu_failed_msg,
379291a2b48SSukumar Swaminathan 			    "Data miscompare. Offset %d value %02x should "
380291a2b48SSukumar Swaminathan 			    "be %02x.", i, *inptr, *outptr);
381fcf3ce44SJohn Forte 
382fcf3ce44SJohn Forte 			rval = EMLXS_TEST_FAILED;
383fcf3ce44SJohn Forte 			goto done;
384fcf3ce44SJohn Forte 		}
385fcf3ce44SJohn Forte 	}
386fcf3ce44SJohn Forte 
387fcf3ce44SJohn Forte 	/* Wait half second before returning */
388fcf3ce44SJohn Forte 	delay(drv_usectohz(500000));
389fcf3ce44SJohn Forte 	rval = FC_SUCCESS;
390fcf3ce44SJohn Forte 
391fcf3ce44SJohn Forte 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_biu_complete_msg, "Status Good.");
392fcf3ce44SJohn Forte 
393fcf3ce44SJohn Forte done:
394fcf3ce44SJohn Forte 
395291a2b48SSukumar Swaminathan 	if (mp) {
396b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
397b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, mp->dma_handle)
398b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
399b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
400b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
401*8f23e9faSHans Rosenfeld 			    "diag_biu_run: hdl=%p",
402b3660a96SSukumar Swaminathan 			    mp->dma_handle);
403b3660a96SSukumar Swaminathan 			rval = EMLXS_TEST_FAILED;
404b3660a96SSukumar Swaminathan 		}
405b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
406a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_BUF, (void *)mp);
407291a2b48SSukumar Swaminathan 	}
408291a2b48SSukumar Swaminathan 	if (mp1) {
409b3660a96SSukumar Swaminathan #ifdef FMA_SUPPORT
410b3660a96SSukumar Swaminathan 		if (emlxs_fm_check_dma_handle(hba, mp1->dma_handle)
411b3660a96SSukumar Swaminathan 		    != DDI_FM_OK) {
412b3660a96SSukumar Swaminathan 			EMLXS_MSGF(EMLXS_CONTEXT,
413b3660a96SSukumar Swaminathan 			    &emlxs_invalid_dma_handle_msg,
414*8f23e9faSHans Rosenfeld 			    "diag_biu_run: hdl=%p",
415b3660a96SSukumar Swaminathan 			    mp1->dma_handle);
416b3660a96SSukumar Swaminathan 			rval = EMLXS_TEST_FAILED;
417b3660a96SSukumar Swaminathan 		}
418b3660a96SSukumar Swaminathan #endif  /* FMA_SUPPORT */
419a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_BUF, (void *)mp1);
420291a2b48SSukumar Swaminathan 	}
42182527734SSukumar Swaminathan 	if (mbq) {
422a9800bebSGarrett D'Amore 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
423291a2b48SSukumar Swaminathan 	}
424fcf3ce44SJohn Forte 
425fcf3ce44SJohn Forte 	return (rval);
426fcf3ce44SJohn Forte 
42782527734SSukumar Swaminathan } /* emlxs_diag_biu_run() */
428fcf3ce44SJohn Forte 
429fcf3ce44SJohn Forte 
430fcf3ce44SJohn Forte extern uint32_t
emlxs_diag_post_run(emlxs_hba_t * hba)431fcf3ce44SJohn Forte emlxs_diag_post_run(emlxs_hba_t *hba)
432fcf3ce44SJohn Forte {
433fcf3ce44SJohn Forte 	emlxs_port_t *port = &PPORT;
434fcf3ce44SJohn Forte 	uint32_t rval = FC_SUCCESS;
435fcf3ce44SJohn Forte 
436fcf3ce44SJohn Forte 	if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) {
437fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
438fcf3ce44SJohn Forte 		    "POST: HBA shutdown.");
439fcf3ce44SJohn Forte 
440fcf3ce44SJohn Forte 		return (FC_TRAN_BUSY);
441fcf3ce44SJohn Forte 	}
442291a2b48SSukumar Swaminathan 
443fcf3ce44SJohn Forte 	/* Take board offline */
444*8f23e9faSHans Rosenfeld 	if ((rval = emlxs_offline(hba, 0))) {
445fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_post_failed_msg,
446fcf3ce44SJohn Forte 		    "Unable to take adapter offline.");
447fcf3ce44SJohn Forte 
448fcf3ce44SJohn Forte 		rval = FC_RESETFAIL;
449fcf3ce44SJohn Forte 	}
450291a2b48SSukumar Swaminathan 
451fcf3ce44SJohn Forte 	/* Restart the adapter */
45282527734SSukumar Swaminathan 	rval = EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
453fcf3ce44SJohn Forte 
454fcf3ce44SJohn Forte 	switch (rval) {
455fcf3ce44SJohn Forte 	case 0:
456fcf3ce44SJohn Forte 
457fcf3ce44SJohn Forte 		(void) emlxs_online(hba);
458fcf3ce44SJohn Forte 
459fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_post_complete_msg,
460fcf3ce44SJohn Forte 		    "Status good.");
461fcf3ce44SJohn Forte 
462fcf3ce44SJohn Forte 		rval = FC_SUCCESS;
463fcf3ce44SJohn Forte 
464fcf3ce44SJohn Forte 		break;
465fcf3ce44SJohn Forte 
466fcf3ce44SJohn Forte 	case 1:	/* failed */
467fcf3ce44SJohn Forte 
468fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_post_failed_msg,
469fcf3ce44SJohn Forte 		    "HBA reset failed.");
470fcf3ce44SJohn Forte 
471fcf3ce44SJohn Forte 		rval = FC_RESETFAIL;
472fcf3ce44SJohn Forte 
473fcf3ce44SJohn Forte 		break;
474fcf3ce44SJohn Forte 
475fcf3ce44SJohn Forte 
476fcf3ce44SJohn Forte 	case 2:	/* failed */
477fcf3ce44SJohn Forte 
478fcf3ce44SJohn Forte 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_diag_error_msg,
479fcf3ce44SJohn Forte 		    "HBA busy. Quiece and retry.");
480fcf3ce44SJohn Forte 
481fcf3ce44SJohn Forte 		rval = FC_STATEC_BUSY;
482fcf3ce44SJohn Forte 
483fcf3ce44SJohn Forte 		break;
484fcf3ce44SJohn Forte 
485fcf3ce44SJohn Forte 	}
486fcf3ce44SJohn Forte 
487fcf3ce44SJohn Forte 	return (rval);
488fcf3ce44SJohn Forte 
48982527734SSukumar Swaminathan } /* emlxs_diag_post_run() */