xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_init.c (revision cde3e94d79d833480d2f3ba69f901b918878fd65)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  * Copyright (c) 2014, Tegile Systems Inc. All rights reserved.
26  * Copyright (c) 2017, Joyent, Inc.
27  * Copyright 2023 Racktop Systems, Inc.
28  */
29 
30 /*
31  * Copyright (c) 2000 to 2009, LSI Corporation.
32  * All rights reserved.
33  *
34  * Redistribution and use in source and binary forms of all code within
35  * this file that is exclusively owned by LSI, with or without
36  * modification, is permitted provided that, in addition to the CDDL 1.0
37  * License requirements, the following conditions are met:
38  *
39  *    Neither the name of the author nor the names of its contributors may be
40  *    used to endorse or promote products derived from this software without
41  *    specific prior written permission.
42  *
43  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
46  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
47  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
48  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
49  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
50  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
51  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
52  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
53  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
54  * DAMAGE.
55  */
56 
57 /*
58  * mptsas_init - This file contains all the functions used to initialize
59  * MPT2.0 based hardware.
60  */
61 
62 #if defined(lint) || defined(DEBUG)
63 #define	MPTSAS_DEBUG
64 #endif
65 
66 /*
67  * standard header files
68  */
69 #include <sys/note.h>
70 #include <sys/scsi/scsi.h>
71 
72 #pragma pack(1)
73 #include <sys/scsi/adapters/mpi/mpi2_type.h>
74 #include <sys/scsi/adapters/mpi/mpi2.h>
75 #include <sys/scsi/adapters/mpi/mpi2_cnfg.h>
76 #include <sys/scsi/adapters/mpi/mpi2_init.h>
77 #include <sys/scsi/adapters/mpi/mpi2_ioc.h>
78 #include <sys/scsi/adapters/mpi/mpi2_tool.h>
79 #pragma pack()
80 /*
81  * private header files.
82  */
83 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
84 
85 static int mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var,
86 	ddi_acc_handle_t accessp);
87 static int mptsas_ioc_do_get_facts_reply(mptsas_t *mpt, caddr_t memp, int var,
88 	ddi_acc_handle_t accessp);
89 static int mptsas_ioc_do_get_port_facts(mptsas_t *mpt, caddr_t memp, int var,
90 	ddi_acc_handle_t accessp);
91 static int mptsas_ioc_do_get_port_facts_reply(mptsas_t *mpt, caddr_t memp,
92     int var, ddi_acc_handle_t accessp);
93 static int mptsas_ioc_do_enable_port(mptsas_t *mpt, caddr_t memp, int var,
94 	ddi_acc_handle_t accessp);
95 static int mptsas_ioc_do_enable_port_reply(mptsas_t *mpt, caddr_t memp, int var,
96 	ddi_acc_handle_t accessp);
97 static int mptsas_ioc_do_enable_event_notification(mptsas_t *mpt, caddr_t memp,
98 	int var, ddi_acc_handle_t accessp);
99 static int mptsas_ioc_do_enable_event_notification_reply(mptsas_t *mpt,
100     caddr_t memp, int var, ddi_acc_handle_t accessp);
101 static int mptsas_do_ioc_init(mptsas_t *mpt, caddr_t memp, int var,
102 	ddi_acc_handle_t accessp);
103 static int mptsas_do_ioc_init_reply(mptsas_t *mpt, caddr_t memp, int var,
104 	ddi_acc_handle_t accessp);
105 
106 static const char *
mptsas_devid_type_string(mptsas_t * mpt)107 mptsas_devid_type_string(mptsas_t *mpt)
108 {
109 	switch (mpt->m_devid) {
110 	case MPI2_MFGPAGE_DEVID_SAS2008:
111 		return ("SAS2008");
112 	case MPI2_MFGPAGE_DEVID_SAS2004:
113 		return ("SAS2004");
114 	case MPI2_MFGPAGE_DEVID_SAS2108_1:
115 	case MPI2_MFGPAGE_DEVID_SAS2108_2:
116 	case MPI2_MFGPAGE_DEVID_SAS2108_3:
117 		return ("SAS2108");
118 	case MPI2_MFGPAGE_DEVID_SAS2116_1:
119 	case MPI2_MFGPAGE_DEVID_SAS2116_2:
120 		return ("SAS2116");
121 	case MPI2_MFGPAGE_DEVID_SAS2208_1:
122 	case MPI2_MFGPAGE_DEVID_SAS2208_2:
123 	case MPI2_MFGPAGE_DEVID_SAS2208_3:
124 	case MPI2_MFGPAGE_DEVID_SAS2208_4:
125 	case MPI2_MFGPAGE_DEVID_SAS2208_5:
126 	case MPI2_MFGPAGE_DEVID_SAS2208_6:
127 		return ("SAS2208");
128 	case MPI2_MFGPAGE_DEVID_SAS2308_1:
129 	case MPI2_MFGPAGE_DEVID_SAS2308_2:
130 	case MPI2_MFGPAGE_DEVID_SAS2308_3:
131 		return ("SAS2308");
132 	case MPI25_MFGPAGE_DEVID_SAS3004:
133 		return ("SAS3004");
134 	case MPI25_MFGPAGE_DEVID_SAS3008:
135 		return ("SAS3008");
136 	case MPI25_MFGPAGE_DEVID_SAS3108_1:
137 	case MPI25_MFGPAGE_DEVID_SAS3108_2:
138 	case MPI25_MFGPAGE_DEVID_SAS3108_5:
139 	case MPI25_MFGPAGE_DEVID_SAS3108_6:
140 		return ("SAS3108");
141 	case MPI26_MFGPAGE_DEVID_SAS3216:
142 	case MPI26_MFGPAGE_DEVID_SAS3316_1:
143 	case MPI26_MFGPAGE_DEVID_SAS3316_2:
144 	case MPI26_MFGPAGE_DEVID_SAS3316_3:
145 	case MPI26_MFGPAGE_DEVID_SAS3316_4:
146 		return ("SAS3216");
147 	case MPI26_MFGPAGE_DEVID_SAS3224:
148 	case MPI26_MFGPAGE_DEVID_SAS3324_1:
149 	case MPI26_MFGPAGE_DEVID_SAS3324_2:
150 	case MPI26_MFGPAGE_DEVID_SAS3324_3:
151 	case MPI26_MFGPAGE_DEVID_SAS3324_4:
152 		return ("SAS3224");
153 	case MPI26_MFGPAGE_DEVID_SAS3408:
154 		return ("SAS3408");
155 	case MPI26_MFGPAGE_DEVID_SAS3416:
156 		return ("SAS3416");
157 	case MPI26_MFGPAGE_DEVID_SAS3508:
158 	case MPI26_MFGPAGE_DEVID_SAS3508_1:
159 		return ("SAS3508");
160 	case MPI26_MFGPAGE_DEVID_SAS3516:
161 	case MPI26_MFGPAGE_DEVID_SAS3516_1:
162 		return ("SAS3516");
163 	case MPI26_MFGPAGE_DEVID_SAS3616:
164 		return ("SAS3616");
165 	case MPI26_MFGPAGE_DEVID_SAS3708:
166 		return ("SAS3708");
167 	case MPI26_MFGPAGE_DEVID_SAS3716:
168 		return ("SAS3716");
169 	case MPI26_MFGPAGE_DEVID_SAS3816:
170 	case MPI26_MFGPAGE_DEVID_SAS3816_1:
171 		return ("SAS3816");
172 	case MPI26_MFGPAGE_DEVID_SAS4008:
173 		return ("SAS4008");
174 	default:
175 		return ("?");
176 	}
177 }
178 
179 int
mptsas_ioc_get_facts(mptsas_t * mpt)180 mptsas_ioc_get_facts(mptsas_t *mpt)
181 {
182 	/*
183 	 * Send get facts messages
184 	 */
185 	if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_FACTS_REQUEST), 0,
186 	    mptsas_ioc_do_get_facts)) {
187 		return (DDI_FAILURE);
188 	}
189 
190 	/*
191 	 * Get facts reply messages
192 	 */
193 	if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_FACTS_REPLY), 0,
194 	    mptsas_ioc_do_get_facts_reply)) {
195 		return (DDI_FAILURE);
196 	}
197 
198 	return (DDI_SUCCESS);
199 }
200 
201 static int
mptsas_ioc_do_get_facts(mptsas_t * mpt,caddr_t memp,int var,ddi_acc_handle_t accessp)202 mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var,
203     ddi_acc_handle_t accessp)
204 {
205 #ifndef __lock_lint
206 	_NOTE(ARGUNUSED(var))
207 #endif
208 	pMpi2IOCFactsRequest_t	facts;
209 	int			numbytes;
210 
211 	bzero(memp, sizeof (*facts));
212 	facts = (void *)memp;
213 	ddi_put8(accessp, &facts->Function, MPI2_FUNCTION_IOC_FACTS);
214 	numbytes = sizeof (*facts);
215 
216 	/*
217 	 * Post message via handshake
218 	 */
219 	if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
220 		return (DDI_FAILURE);
221 	}
222 
223 	return (DDI_SUCCESS);
224 }
225 
226 static int
mptsas_ioc_do_get_facts_reply(mptsas_t * mpt,caddr_t memp,int var,ddi_acc_handle_t accessp)227 mptsas_ioc_do_get_facts_reply(mptsas_t *mpt, caddr_t memp, int var,
228     ddi_acc_handle_t accessp)
229 {
230 #ifndef __lock_lint
231 	_NOTE(ARGUNUSED(var))
232 #endif
233 
234 	pMpi2IOCFactsReply_t	factsreply;
235 	int			numbytes;
236 	uint_t			iocstatus;
237 	char			buf[32];
238 	uint16_t		numReplyFrames;
239 	uint16_t		queueSize, queueDiff;
240 	int			simple_sge_main;
241 	int			simple_sge_next;
242 	uint32_t		capabilities;
243 	uint16_t		msgversion;
244 
245 	bzero(memp, sizeof (*factsreply));
246 	factsreply = (void *)memp;
247 	numbytes = sizeof (*factsreply);
248 
249 	/*
250 	 * get ioc facts reply message
251 	 */
252 	if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
253 		return (DDI_FAILURE);
254 	}
255 
256 	if ((iocstatus = ddi_get16(accessp, &factsreply->IOCStatus)) != 0) {
257 		mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_get_facts_reply: "
258 		    "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
259 		    ddi_get32(accessp, &factsreply->IOCLogInfo));
260 		return (DDI_FAILURE);
261 	}
262 
263 	/*
264 	 * store key values from reply to mpt structure
265 	 */
266 	mpt->m_fwversion = ddi_get32(accessp, &factsreply->FWVersion.Word);
267 	mpt->m_productid = ddi_get16(accessp, &factsreply->ProductID);
268 
269 
270 	(void) sprintf(buf, "%u.%u.%u.%u",
271 	    ddi_get8(accessp, &factsreply->FWVersion.Struct.Major),
272 	    ddi_get8(accessp, &factsreply->FWVersion.Struct.Minor),
273 	    ddi_get8(accessp, &factsreply->FWVersion.Struct.Unit),
274 	    ddi_get8(accessp, &factsreply->FWVersion.Struct.Dev));
275 	mptsas_log(mpt, CE_NOTE, "?MPT Firmware version v%s (%s)\n",
276 	    buf, mptsas_devid_type_string(mpt));
277 	(void) ddi_prop_update_string(DDI_DEV_T_NONE, mpt->m_dip,
278 	    "firmware-version", buf);
279 
280 	/*
281 	 * Set up request info.
282 	 */
283 	mpt->m_max_requests = ddi_get16(accessp,
284 	    &factsreply->RequestCredit) - 1;
285 	mpt->m_req_frame_size = ddi_get16(accessp,
286 	    &factsreply->IOCRequestFrameSize) * 4;
287 
288 	/*
289 	 * Size of reply free queue should be the number of requests
290 	 * plus some additional for events (32).  Make sure number of
291 	 * reply frames is not a multiple of 16 so that the queue sizes
292 	 * are calculated correctly later to be a multiple of 16.
293 	 */
294 	mpt->m_reply_frame_size = ddi_get8(accessp,
295 	    &factsreply->ReplyFrameSize) * 4;
296 	numReplyFrames = mpt->m_max_requests + 32;
297 	if (!(numReplyFrames % 16)) {
298 		numReplyFrames--;
299 	}
300 	mpt->m_max_replies = numReplyFrames;
301 	queueSize = numReplyFrames;
302 	queueSize += 16 - (queueSize % 16);
303 	mpt->m_free_queue_depth = queueSize;
304 
305 	/*
306 	 * Size of reply descriptor post queue should be the number of
307 	 * request frames + the number of reply frames + 1 and needs to
308 	 * be a multiple of 16.  This size can be no larger than
309 	 * MaxReplyDescriptorPostQueueDepth from IOCFacts.  If the
310 	 * calculated queue size is larger than allowed, subtract a
311 	 * multiple of 16 from m_max_requests, m_max_replies, and
312 	 * m_reply_free_depth.
313 	 */
314 	queueSize = mpt->m_max_requests + numReplyFrames + 1;
315 	if (queueSize % 16) {
316 		queueSize += 16 - (queueSize % 16);
317 	}
318 	mpt->m_post_queue_depth = ddi_get16(accessp,
319 	    &factsreply->MaxReplyDescriptorPostQueueDepth);
320 	if (queueSize > mpt->m_post_queue_depth) {
321 		queueDiff = queueSize - mpt->m_post_queue_depth;
322 		if (queueDiff % 16) {
323 			queueDiff += 16 - (queueDiff % 16);
324 		}
325 		mpt->m_max_requests -= queueDiff;
326 		mpt->m_max_replies -= queueDiff;
327 		mpt->m_free_queue_depth -= queueDiff;
328 		queueSize -= queueDiff;
329 	}
330 	mpt->m_post_queue_depth = queueSize;
331 
332 	/*
333 	 * Set up max chain depth.
334 	 */
335 	mpt->m_max_chain_depth = ddi_get8(accessp,
336 	    &factsreply->MaxChainDepth);
337 	mpt->m_ioc_capabilities = ddi_get32(accessp,
338 	    &factsreply->IOCCapabilities);
339 
340 	/*
341 	 * Set flag to check for SAS3 support.
342 	 */
343 	msgversion = ddi_get16(accessp, &factsreply->MsgVersion);
344 	if (msgversion >= MPI2_VERSION_02_05) {
345 		mptsas_log(mpt, CE_NOTE, "?mpt_sas%d SAS 3 Supported\n",
346 		    mpt->m_instance);
347 		mpt->m_MPI25 = TRUE;
348 	} else {
349 		mptsas_log(mpt, CE_NOTE, "?mpt_sas%d MPI Version 0x%x\n",
350 		    mpt->m_instance, msgversion);
351 	}
352 
353 	/*
354 	 * Calculate max frames per request based on DMA S/G length.
355 	 */
356 	simple_sge_main = MPTSAS_MAX_FRAME_SGES64(mpt) - 1;
357 	simple_sge_next = mpt->m_req_frame_size / MPTSAS_SGE_SIZE(mpt) - 1;
358 
359 	mpt->m_max_request_frames = (MPTSAS_MAX_DMA_SEGS -
360 	    simple_sge_main) / simple_sge_next + 1;
361 	if (((MPTSAS_MAX_DMA_SEGS - simple_sge_main) %
362 	    simple_sge_next) > 1) {
363 		mpt->m_max_request_frames++;
364 	}
365 
366 	/*
367 	 * Check if controller supports FW diag buffers and set flag to enable
368 	 * each type.
369 	 */
370 	capabilities = ddi_get32(accessp, &factsreply->IOCCapabilities);
371 	if (capabilities & MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) {
372 		mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_TRACE].enabled =
373 		    TRUE;
374 	}
375 	if (capabilities & MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) {
376 		mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_SNAPSHOT].
377 		    enabled = TRUE;
378 	}
379 	if (capabilities & MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) {
380 		mpt->m_fw_diag_buffer_list[MPI2_DIAG_BUF_TYPE_EXTENDED].
381 		    enabled = TRUE;
382 	}
383 
384 	/*
385 	 * Check if controller supports replaying events when issuing Message
386 	 * Unit Reset and set flag to enable MUR.
387 	 */
388 	if (capabilities & MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY) {
389 		mpt->m_event_replay = TRUE;
390 	}
391 
392 	/*
393 	 * Check if controller supports IR.
394 	 */
395 	if (capabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
396 		mpt->m_ir_capable = TRUE;
397 	}
398 
399 	return (DDI_SUCCESS);
400 }
401 
402 int
mptsas_ioc_get_port_facts(mptsas_t * mpt,int port)403 mptsas_ioc_get_port_facts(mptsas_t *mpt, int port)
404 {
405 	/*
406 	 * Send get port facts message
407 	 */
408 	if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_FACTS_REQUEST), port,
409 	    mptsas_ioc_do_get_port_facts)) {
410 		return (DDI_FAILURE);
411 	}
412 
413 	/*
414 	 * Get port facts reply message
415 	 */
416 	if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_FACTS_REPLY), port,
417 	    mptsas_ioc_do_get_port_facts_reply)) {
418 		return (DDI_FAILURE);
419 	}
420 
421 	return (DDI_SUCCESS);
422 }
423 
424 static int
mptsas_ioc_do_get_port_facts(mptsas_t * mpt,caddr_t memp,int var,ddi_acc_handle_t accessp)425 mptsas_ioc_do_get_port_facts(mptsas_t *mpt, caddr_t memp, int var,
426     ddi_acc_handle_t accessp)
427 {
428 	pMpi2PortFactsRequest_t	facts;
429 	int			numbytes;
430 
431 	bzero(memp, sizeof (*facts));
432 	facts = (void *)memp;
433 	ddi_put8(accessp, &facts->Function, MPI2_FUNCTION_PORT_FACTS);
434 	ddi_put8(accessp, &facts->PortNumber, var);
435 	numbytes = sizeof (*facts);
436 
437 	/*
438 	 * Send port facts message via handshake
439 	 */
440 	if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
441 		return (DDI_FAILURE);
442 	}
443 
444 	return (DDI_SUCCESS);
445 }
446 
447 static int
mptsas_ioc_do_get_port_facts_reply(mptsas_t * mpt,caddr_t memp,int var,ddi_acc_handle_t accessp)448 mptsas_ioc_do_get_port_facts_reply(mptsas_t *mpt, caddr_t memp, int var,
449     ddi_acc_handle_t accessp)
450 {
451 #ifndef __lock_lint
452 	_NOTE(ARGUNUSED(var))
453 #endif
454 	pMpi2PortFactsReply_t	factsreply;
455 	int			numbytes;
456 	uint_t			iocstatus;
457 
458 	bzero(memp, sizeof (*factsreply));
459 	factsreply = (void *)memp;
460 	numbytes = sizeof (*factsreply);
461 
462 	/*
463 	 * Get port facts reply message via handshake
464 	 */
465 	if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
466 		return (DDI_FAILURE);
467 	}
468 
469 	if ((iocstatus = ddi_get16(accessp, &factsreply->IOCStatus)) != 0) {
470 		mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_get_port_facts_reply: "
471 		    "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
472 		    ddi_get32(accessp, &factsreply->IOCLogInfo));
473 		return (DDI_FAILURE);
474 	}
475 
476 	return (DDI_SUCCESS);
477 }
478 
479 int
mptsas_ioc_enable_port(mptsas_t * mpt)480 mptsas_ioc_enable_port(mptsas_t *mpt)
481 {
482 	/*
483 	 * Send enable port message
484 	 */
485 	if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_ENABLE_REQUEST), 0,
486 	    mptsas_ioc_do_enable_port)) {
487 		return (DDI_FAILURE);
488 	}
489 
490 	/*
491 	 * Get enable port reply message
492 	 */
493 	if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_ENABLE_REPLY), 0,
494 	    mptsas_ioc_do_enable_port_reply)) {
495 		return (DDI_FAILURE);
496 	}
497 
498 	return (DDI_SUCCESS);
499 }
500 
501 static int
mptsas_ioc_do_enable_port(mptsas_t * mpt,caddr_t memp,int var,ddi_acc_handle_t accessp)502 mptsas_ioc_do_enable_port(mptsas_t *mpt, caddr_t memp, int var,
503     ddi_acc_handle_t accessp)
504 {
505 #ifndef __lock_lint
506 	_NOTE(ARGUNUSED(var))
507 #endif
508 	pMpi2PortEnableRequest_t	enable;
509 	int				numbytes;
510 
511 	bzero(memp, sizeof (*enable));
512 	enable = (void *)memp;
513 	ddi_put8(accessp, &enable->Function, MPI2_FUNCTION_PORT_ENABLE);
514 	numbytes = sizeof (*enable);
515 
516 	/*
517 	 * Send message via handshake
518 	 */
519 	if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
520 		return (DDI_FAILURE);
521 	}
522 
523 	return (DDI_SUCCESS);
524 }
525 
526 static int
mptsas_ioc_do_enable_port_reply(mptsas_t * mpt,caddr_t memp,int var,ddi_acc_handle_t accessp)527 mptsas_ioc_do_enable_port_reply(mptsas_t *mpt, caddr_t memp, int var,
528     ddi_acc_handle_t accessp)
529 {
530 #ifndef __lock_lint
531 	_NOTE(ARGUNUSED(var))
532 #endif
533 
534 	int			numbytes;
535 	uint_t			iocstatus;
536 	pMpi2PortEnableReply_t	portreply;
537 
538 	numbytes = sizeof (MPI2_PORT_ENABLE_REPLY);
539 	bzero(memp, numbytes);
540 	portreply = (void *)memp;
541 
542 	/*
543 	 * Get message via handshake
544 	 */
545 	if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
546 		return (DDI_FAILURE);
547 	}
548 
549 	if ((iocstatus = ddi_get16(accessp, &portreply->IOCStatus)) != 0) {
550 		mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_enable_port_reply: "
551 		    "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
552 		    ddi_get32(accessp, &portreply->IOCLogInfo));
553 		return (DDI_FAILURE);
554 	}
555 
556 	return (DDI_SUCCESS);
557 }
558 
559 int
mptsas_ioc_enable_event_notification(mptsas_t * mpt)560 mptsas_ioc_enable_event_notification(mptsas_t *mpt)
561 {
562 	ASSERT(mutex_owned(&mpt->m_mutex));
563 
564 	/*
565 	 * Send enable event notification message
566 	 */
567 	if (mptsas_do_dma(mpt, sizeof (MPI2_EVENT_NOTIFICATION_REQUEST), 0,
568 	    mptsas_ioc_do_enable_event_notification)) {
569 		return (DDI_FAILURE);
570 	}
571 
572 	/*
573 	 * Get enable event reply message
574 	 */
575 	if (mptsas_do_dma(mpt, sizeof (MPI2_EVENT_NOTIFICATION_REPLY), 0,
576 	    mptsas_ioc_do_enable_event_notification_reply)) {
577 		return (DDI_FAILURE);
578 	}
579 
580 	return (DDI_SUCCESS);
581 }
582 
583 static int
mptsas_ioc_do_enable_event_notification(mptsas_t * mpt,caddr_t memp,int var,ddi_acc_handle_t accessp)584 mptsas_ioc_do_enable_event_notification(mptsas_t *mpt, caddr_t memp, int var,
585     ddi_acc_handle_t accessp)
586 {
587 #ifndef __lock_lint
588 	_NOTE(ARGUNUSED(var))
589 #endif
590 
591 	pMpi2EventNotificationRequest_t	event;
592 	int				numbytes;
593 
594 	bzero(memp, sizeof (*event));
595 	event = (void *)memp;
596 	ddi_put8(accessp, &event->Function, MPI2_FUNCTION_EVENT_NOTIFICATION);
597 	numbytes = sizeof (*event);
598 
599 	/*
600 	 * Send message via handshake
601 	 */
602 	if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
603 		return (DDI_FAILURE);
604 	}
605 
606 	return (DDI_SUCCESS);
607 }
608 
609 static int
mptsas_ioc_do_enable_event_notification_reply(mptsas_t * mpt,caddr_t memp,int var,ddi_acc_handle_t accessp)610 mptsas_ioc_do_enable_event_notification_reply(mptsas_t *mpt, caddr_t memp,
611     int var, ddi_acc_handle_t accessp)
612 {
613 #ifndef __lock_lint
614 	_NOTE(ARGUNUSED(var))
615 #endif
616 	int				numbytes;
617 	uint_t				iocstatus;
618 	pMpi2EventNotificationReply_t	eventsreply;
619 
620 	numbytes = sizeof (MPI2_EVENT_NOTIFICATION_REPLY);
621 	bzero(memp, numbytes);
622 	eventsreply = (void *)memp;
623 
624 	/*
625 	 * Get message via handshake
626 	 */
627 	if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
628 		return (DDI_FAILURE);
629 	}
630 
631 	if ((iocstatus = ddi_get16(accessp, &eventsreply->IOCStatus)) != 0) {
632 		mptsas_log(mpt, CE_WARN,
633 		    "mptsas_ioc_do_enable_event_notification_reply: "
634 		    "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
635 		    ddi_get32(accessp, &eventsreply->IOCLogInfo));
636 		return (DDI_FAILURE);
637 	}
638 
639 	return (DDI_SUCCESS);
640 }
641 
642 int
mptsas_ioc_init(mptsas_t * mpt)643 mptsas_ioc_init(mptsas_t *mpt)
644 {
645 	/*
646 	 * Send ioc init message
647 	 */
648 	if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_INIT_REQUEST), 0,
649 	    mptsas_do_ioc_init)) {
650 		return (DDI_FAILURE);
651 	}
652 
653 	/*
654 	 * Get ioc init reply message
655 	 */
656 	if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_INIT_REPLY), 0,
657 	    mptsas_do_ioc_init_reply)) {
658 		return (DDI_FAILURE);
659 	}
660 
661 	return (DDI_SUCCESS);
662 }
663 
664 static int
mptsas_do_ioc_init(mptsas_t * mpt,caddr_t memp,int var,ddi_acc_handle_t accessp)665 mptsas_do_ioc_init(mptsas_t *mpt, caddr_t memp, int var,
666     ddi_acc_handle_t accessp)
667 {
668 #ifndef __lock_lint
669 	_NOTE(ARGUNUSED(var))
670 #endif
671 
672 	pMpi2IOCInitRequest_t	init;
673 	int			numbytes;
674 	timespec_t		time;
675 	uint64_t		mSec;
676 
677 	bzero(memp, sizeof (*init));
678 	init = (void *)memp;
679 	ddi_put8(accessp, &init->Function, MPI2_FUNCTION_IOC_INIT);
680 	ddi_put8(accessp, &init->WhoInit, MPI2_WHOINIT_HOST_DRIVER);
681 	ddi_put16(accessp, &init->MsgVersion, MPI2_VERSION);
682 	ddi_put16(accessp, &init->HeaderVersion, MPI2_HEADER_VERSION);
683 	ddi_put16(accessp, &init->SystemRequestFrameSize,
684 	    mpt->m_req_frame_size / 4);
685 	ddi_put16(accessp, &init->ReplyDescriptorPostQueueDepth,
686 	    mpt->m_post_queue_depth);
687 	ddi_put16(accessp, &init->ReplyFreeQueueDepth,
688 	    mpt->m_free_queue_depth);
689 
690 	/*
691 	 * These addresses are set using the DMA cookie addresses from when the
692 	 * memory was allocated.  Sense buffer hi address should be 0.
693 	 */
694 	ddi_put32(accessp, &init->SenseBufferAddressHigh,
695 	    (uint32_t)(mpt->m_req_sense_dma_addr >> 32));
696 	ddi_put32(accessp, &init->SystemReplyAddressHigh,
697 	    (uint32_t)(mpt->m_reply_frame_dma_addr >> 32));
698 	ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.High,
699 	    (uint32_t)(mpt->m_req_frame_dma_addr >> 32));
700 	ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.Low,
701 	    (uint32_t)mpt->m_req_frame_dma_addr);
702 	ddi_put32(accessp, &init->ReplyDescriptorPostQueueAddress.High,
703 	    (uint32_t)(mpt->m_post_queue_dma_addr >> 32));
704 	ddi_put32(accessp, &init->ReplyDescriptorPostQueueAddress.Low,
705 	    (uint32_t)mpt->m_post_queue_dma_addr);
706 	ddi_put32(accessp, &init->ReplyFreeQueueAddress.High,
707 	    (uint32_t)(mpt->m_free_queue_dma_addr >> 32));
708 	ddi_put32(accessp, &init->ReplyFreeQueueAddress.Low,
709 	    (uint32_t)mpt->m_free_queue_dma_addr);
710 
711 	/*
712 	 * Fill in the timestamp with the number of milliseconds since midnight
713 	 * of January 1, 1970 UT (Greenwich Mean Time).  Time is returned in
714 	 * seconds and nanoseconds.  Translate both to milliseconds and add
715 	 * them together to get total milliseconds.
716 	 */
717 	gethrestime(&time);
718 	mSec = time.tv_sec * MILLISEC;
719 	mSec += (time.tv_nsec / MICROSEC);
720 	ddi_put32(accessp, &init->TimeStamp.High, (uint32_t)(mSec >> 32));
721 	ddi_put32(accessp, &init->TimeStamp.Low, (uint32_t)mSec);
722 
723 	numbytes = sizeof (*init);
724 
725 	/*
726 	 * Post message via handshake
727 	 */
728 	if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
729 		return (DDI_FAILURE);
730 	}
731 
732 	return (DDI_SUCCESS);
733 }
734 
735 static int
mptsas_do_ioc_init_reply(mptsas_t * mpt,caddr_t memp,int var,ddi_acc_handle_t accessp)736 mptsas_do_ioc_init_reply(mptsas_t *mpt, caddr_t memp, int var,
737     ddi_acc_handle_t accessp)
738 {
739 #ifndef __lock_lint
740 	_NOTE(ARGUNUSED(var))
741 #endif
742 
743 	pMpi2IOCInitReply_t	initreply;
744 	int			numbytes;
745 	uint_t			iocstatus;
746 
747 	numbytes = sizeof (MPI2_IOC_INIT_REPLY);
748 	bzero(memp, numbytes);
749 	initreply = (void *)memp;
750 
751 	/*
752 	 * Get reply message via handshake
753 	 */
754 	if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
755 		return (DDI_FAILURE);
756 	}
757 
758 	if ((iocstatus = ddi_get16(accessp, &initreply->IOCStatus)) != 0) {
759 		mptsas_log(mpt, CE_WARN, "mptsas_do_ioc_init_reply: "
760 		    "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
761 		    ddi_get32(accessp, &initreply->IOCLogInfo));
762 		return (DDI_FAILURE);
763 	}
764 
765 	if ((mptsas_hirrd(mpt, &mpt->m_reg->Doorbell)) &
766 	    MPI2_IOC_STATE_OPERATIONAL) {
767 		mptsas_log(mpt, CE_NOTE,
768 		    "?mpt%d: IOC Operational.\n", mpt->m_instance);
769 	} else {
770 		return (DDI_FAILURE);
771 	}
772 
773 	return (DDI_SUCCESS);
774 }
775