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