xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas_init.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 #pragma pack()
76 /*
77  * private header files.
78  */
79 #include <sys/scsi/adapters/mpt_sas/mptsas_var.h>
80 
81 static int mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var,
82 	ddi_acc_handle_t accessp);
83 static int mptsas_ioc_do_get_facts_reply(mptsas_t *mpt, caddr_t memp, int var,
84 	ddi_acc_handle_t accessp);
85 static int mptsas_ioc_do_get_port_facts(mptsas_t *mpt, caddr_t memp, int var,
86 	ddi_acc_handle_t accessp);
87 static int mptsas_ioc_do_get_port_facts_reply(mptsas_t *mpt, caddr_t memp,
88     int var, ddi_acc_handle_t accessp);
89 static int mptsas_ioc_do_enable_port(mptsas_t *mpt, caddr_t memp, int var,
90 	ddi_acc_handle_t accessp);
91 static int mptsas_ioc_do_enable_port_reply(mptsas_t *mpt, caddr_t memp, int var,
92 	ddi_acc_handle_t accessp);
93 static int mptsas_ioc_do_enable_event_notification(mptsas_t *mpt, caddr_t memp,
94 	int var, ddi_acc_handle_t accessp);
95 static int mptsas_ioc_do_enable_event_notification_reply(mptsas_t *mpt,
96     caddr_t memp, int var, ddi_acc_handle_t accessp);
97 static int mptsas_do_ioc_init(mptsas_t *mpt, caddr_t memp, int var,
98 	ddi_acc_handle_t accessp);
99 static int mptsas_do_ioc_init_reply(mptsas_t *mpt, caddr_t memp, int var,
100 	ddi_acc_handle_t accessp);
101 
102 static const char *
103 mptsas_product_type_string(mptsas_t *mpt)
104 {
105 	switch (mpt->m_productid & MPI2_FW_HEADER_PID_PROD_MASK) {
106 
107 	case MPI2_FW_HEADER_PID_PROD_A:
108 		return ("A");
109 	default:
110 		return ("?");
111 	}
112 }
113 
114 int
115 mptsas_ioc_get_facts(mptsas_t *mpt)
116 {
117 	/*
118 	 * Send get facts messages
119 	 */
120 	if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_FACTS_REQUEST), NULL,
121 	    mptsas_ioc_do_get_facts)) {
122 		return (DDI_FAILURE);
123 	}
124 
125 	/*
126 	 * Get facts reply messages
127 	 */
128 	if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_FACTS_REPLY), NULL,
129 	    mptsas_ioc_do_get_facts_reply)) {
130 		return (DDI_FAILURE);
131 	}
132 
133 	return (DDI_SUCCESS);
134 }
135 
136 static int
137 mptsas_ioc_do_get_facts(mptsas_t *mpt, caddr_t memp, int var,
138 		ddi_acc_handle_t accessp)
139 {
140 #ifndef __lock_lint
141 	_NOTE(ARGUNUSED(var))
142 #endif
143 	pMpi2IOCFactsRequest_t	facts;
144 	int			numbytes;
145 
146 	bzero(memp, sizeof (*facts));
147 	facts = (void *)memp;
148 	ddi_put8(accessp, &facts->Function, MPI2_FUNCTION_IOC_FACTS);
149 	numbytes = sizeof (*facts);
150 
151 	/*
152 	 * Post message via handshake
153 	 */
154 	if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
155 		return (DDI_FAILURE);
156 	}
157 
158 	return (DDI_SUCCESS);
159 }
160 
161 static int
162 mptsas_ioc_do_get_facts_reply(mptsas_t *mpt, caddr_t memp, int var,
163 		ddi_acc_handle_t accessp)
164 {
165 #ifndef __lock_lint
166 	_NOTE(ARGUNUSED(var))
167 #endif
168 
169 	pMpi2IOCFactsReply_t	factsreply;
170 	int			numbytes;
171 	uint_t			iocstatus;
172 	char			buf[32];
173 	uint16_t		numReplyFrames;
174 	uint16_t		queueSize, queueDiff;
175 	int			simple_sge_main;
176 	int			simple_sge_next;
177 
178 	bzero(memp, sizeof (*factsreply));
179 	factsreply = (void *)memp;
180 	numbytes = sizeof (*factsreply);
181 
182 	/*
183 	 * get ioc facts reply message
184 	 */
185 	if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
186 		return (DDI_FAILURE);
187 	}
188 
189 	if (iocstatus = ddi_get16(accessp, &factsreply->IOCStatus)) {
190 		mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_get_facts_reply: "
191 		    "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
192 		    ddi_get32(accessp, &factsreply->IOCLogInfo));
193 		return (DDI_FAILURE);
194 	}
195 
196 	/*
197 	 * store key values from reply to mpt structure
198 	 */
199 	mpt->m_fwversion = ddi_get32(accessp, &factsreply->FWVersion.Word);
200 	mpt->m_productid = ddi_get16(accessp, &factsreply->ProductID);
201 
202 
203 	(void) sprintf(buf, "%u.%u.%u.%u",
204 	    ddi_get8(accessp, &factsreply->FWVersion.Struct.Major),
205 	    ddi_get8(accessp, &factsreply->FWVersion.Struct.Minor),
206 	    ddi_get8(accessp, &factsreply->FWVersion.Struct.Unit),
207 	    ddi_get8(accessp, &factsreply->FWVersion.Struct.Dev));
208 	mptsas_log(mpt, CE_NOTE, "?mpt%d Firmware version v%s (%s)\n",
209 	    mpt->m_instance, buf, mptsas_product_type_string(mpt));
210 	(void) ddi_prop_update_string(DDI_DEV_T_NONE, mpt->m_dip,
211 	    "firmware-version", buf);
212 
213 	/*
214 	 * Set up request info.
215 	 */
216 	mpt->m_max_requests = ddi_get16(accessp,
217 	    &factsreply->RequestCredit) - 1;
218 	mpt->m_req_frame_size = ddi_get16(accessp,
219 	    &factsreply->IOCRequestFrameSize) * 4;
220 
221 	/*
222 	 * Size of reply free queue should be the number of requests
223 	 * plus some additional for events (32).  Make sure number of
224 	 * reply frames is not a multiple of 16 so that the queue sizes
225 	 * are calculated correctly later to be a multiple of 16.
226 	 */
227 	mpt->m_reply_frame_size = ddi_get8(accessp,
228 	    &factsreply->ReplyFrameSize) * 4;
229 	numReplyFrames = mpt->m_max_requests + 32;
230 	if (!(numReplyFrames % 16)) {
231 		numReplyFrames--;
232 	}
233 	mpt->m_max_replies = numReplyFrames;
234 	queueSize = numReplyFrames;
235 	queueSize += 16 - (queueSize % 16);
236 	mpt->m_free_queue_depth = queueSize;
237 
238 	/*
239 	 * Size of reply descriptor post queue should be the number of
240 	 * request frames + the number of reply frames + 1 and needs to
241 	 * be a multiple of 16.  This size can be no larger than
242 	 * MaxReplyDescriptorPostQueueDepth from IOCFacts.  If the
243 	 * calculated queue size is larger than allowed, subtract a
244 	 * multiple of 16 from m_max_requests, m_max_replies, and
245 	 * m_reply_free_depth.
246 	 */
247 	queueSize = mpt->m_max_requests + numReplyFrames + 1;
248 	if (queueSize % 16) {
249 		queueSize += 16 - (queueSize % 16);
250 	}
251 	mpt->m_post_queue_depth = ddi_get16(accessp,
252 	    &factsreply->MaxReplyDescriptorPostQueueDepth);
253 	if (queueSize > mpt->m_post_queue_depth) {
254 		queueDiff = queueSize - mpt->m_post_queue_depth;
255 		if (queueDiff % 16) {
256 			queueDiff += 16 - (queueDiff % 16);
257 		}
258 		mpt->m_max_requests -= queueDiff;
259 		mpt->m_max_replies -= queueDiff;
260 		mpt->m_free_queue_depth -= queueDiff;
261 		queueSize -= queueDiff;
262 	}
263 	mpt->m_post_queue_depth = queueSize;
264 
265 	/*
266 	 * Set up other stuff.
267 	 */
268 	mpt->m_max_chain_depth = ddi_get8(accessp,
269 	    &factsreply->MaxChainDepth);
270 
271 	/*
272 	 * Calculate max frames per request based on DMA S/G length.
273 	 */
274 
275 	simple_sge_main = MPTSAS_MAX_FRAME_SGES64(mpt) - 1;
276 	simple_sge_next = mpt->m_req_frame_size /
277 	    sizeof (MPI2_SGE_SIMPLE64) - 1;
278 
279 	mpt->m_max_request_frames = (MPTSAS_MAX_DMA_SEGS -
280 	    simple_sge_main) / simple_sge_next + 1;
281 	if (((MPTSAS_MAX_DMA_SEGS - simple_sge_main) %
282 	    simple_sge_next) > 1) {
283 		mpt->m_max_request_frames++;
284 	}
285 
286 	return (DDI_SUCCESS);
287 }
288 
289 int
290 mptsas_ioc_get_port_facts(mptsas_t *mpt, int port)
291 {
292 	/*
293 	 * Send get port facts message
294 	 */
295 	if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_FACTS_REQUEST), port,
296 	    mptsas_ioc_do_get_port_facts)) {
297 		return (DDI_FAILURE);
298 	}
299 
300 	/*
301 	 * Get port facts reply message
302 	 */
303 	if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_FACTS_REPLY), port,
304 	    mptsas_ioc_do_get_port_facts_reply)) {
305 		return (DDI_FAILURE);
306 	}
307 
308 	return (DDI_SUCCESS);
309 }
310 
311 static int
312 mptsas_ioc_do_get_port_facts(mptsas_t *mpt, caddr_t memp, int var,
313 			ddi_acc_handle_t accessp)
314 {
315 	pMpi2PortFactsRequest_t	facts;
316 	int			numbytes;
317 
318 	bzero(memp, sizeof (*facts));
319 	facts = (void *)memp;
320 	ddi_put8(accessp, &facts->Function, MPI2_FUNCTION_PORT_FACTS);
321 	ddi_put8(accessp, &facts->PortNumber, var);
322 	numbytes = sizeof (*facts);
323 
324 	/*
325 	 * Send port facts message via handshake
326 	 */
327 	if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
328 		return (DDI_FAILURE);
329 	}
330 
331 	return (DDI_SUCCESS);
332 }
333 
334 static int
335 mptsas_ioc_do_get_port_facts_reply(mptsas_t *mpt, caddr_t memp, int var,
336 				ddi_acc_handle_t accessp)
337 {
338 #ifndef __lock_lint
339 	_NOTE(ARGUNUSED(var))
340 #endif
341 	pMpi2PortFactsReply_t	factsreply;
342 	int			numbytes;
343 	uint_t			iocstatus;
344 
345 	bzero(memp, sizeof (*factsreply));
346 	factsreply = (void *)memp;
347 	numbytes = sizeof (*factsreply);
348 
349 	/*
350 	 * Get port facts reply message via handshake
351 	 */
352 	if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
353 		return (DDI_FAILURE);
354 	}
355 
356 	if (iocstatus = ddi_get16(accessp, &factsreply->IOCStatus)) {
357 		mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_get_port_facts_reply: "
358 		    "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
359 		    ddi_get32(accessp, &factsreply->IOCLogInfo));
360 		return (DDI_FAILURE);
361 	}
362 
363 	return (DDI_SUCCESS);
364 }
365 
366 int
367 mptsas_ioc_enable_port(mptsas_t *mpt)
368 {
369 	/*
370 	 * Send enable port message
371 	 */
372 	if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_ENABLE_REQUEST), 0,
373 	    mptsas_ioc_do_enable_port)) {
374 		return (DDI_FAILURE);
375 	}
376 
377 	/*
378 	 * Get enable port reply message
379 	 */
380 	if (mptsas_do_dma(mpt, sizeof (MPI2_PORT_ENABLE_REPLY), 0,
381 	    mptsas_ioc_do_enable_port_reply)) {
382 		return (DDI_FAILURE);
383 	}
384 
385 	return (DDI_SUCCESS);
386 }
387 
388 static int
389 mptsas_ioc_do_enable_port(mptsas_t *mpt, caddr_t memp, int var,
390 	ddi_acc_handle_t accessp)
391 {
392 #ifndef __lock_lint
393 	_NOTE(ARGUNUSED(var))
394 #endif
395 	pMpi2PortEnableRequest_t	enable;
396 	int				numbytes;
397 
398 	bzero(memp, sizeof (*enable));
399 	enable = (void *)memp;
400 	ddi_put8(accessp, &enable->Function, MPI2_FUNCTION_PORT_ENABLE);
401 	numbytes = sizeof (*enable);
402 
403 	/*
404 	 * Send message via handshake
405 	 */
406 	if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
407 		return (DDI_FAILURE);
408 	}
409 
410 	return (DDI_SUCCESS);
411 }
412 
413 static int
414 mptsas_ioc_do_enable_port_reply(mptsas_t *mpt, caddr_t memp, int var,
415 	ddi_acc_handle_t accessp)
416 {
417 #ifndef __lock_lint
418 	_NOTE(ARGUNUSED(var))
419 #endif
420 
421 	int			numbytes;
422 	uint_t			iocstatus;
423 	pMpi2PortEnableReply_t	portreply;
424 
425 	numbytes = sizeof (MPI2_PORT_ENABLE_REPLY);
426 	bzero(memp, numbytes);
427 	portreply = (void *)memp;
428 
429 	/*
430 	 * Get message via handshake
431 	 */
432 	if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
433 		return (DDI_FAILURE);
434 	}
435 
436 	if (iocstatus = ddi_get16(accessp, &portreply->IOCStatus)) {
437 		mptsas_log(mpt, CE_WARN, "mptsas_ioc_do_enable_port_reply: "
438 		    "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
439 		    ddi_get32(accessp, &portreply->IOCLogInfo));
440 		return (DDI_FAILURE);
441 	}
442 
443 	return (DDI_SUCCESS);
444 }
445 
446 int
447 mptsas_ioc_enable_event_notification(mptsas_t *mpt)
448 {
449 	ASSERT(mutex_owned(&mpt->m_mutex));
450 
451 	/*
452 	 * Send enable event notification message
453 	 */
454 	if (mptsas_do_dma(mpt, sizeof (MPI2_EVENT_NOTIFICATION_REQUEST), NULL,
455 	    mptsas_ioc_do_enable_event_notification)) {
456 		return (DDI_FAILURE);
457 	}
458 
459 	/*
460 	 * Get enable event reply message
461 	 */
462 	if (mptsas_do_dma(mpt, sizeof (MPI2_EVENT_NOTIFICATION_REPLY), NULL,
463 	    mptsas_ioc_do_enable_event_notification_reply)) {
464 		return (DDI_FAILURE);
465 	}
466 
467 	return (DDI_SUCCESS);
468 }
469 
470 static int
471 mptsas_ioc_do_enable_event_notification(mptsas_t *mpt, caddr_t memp, int var,
472 	ddi_acc_handle_t accessp)
473 {
474 #ifndef __lock_lint
475 	_NOTE(ARGUNUSED(var))
476 #endif
477 
478 	pMpi2EventNotificationRequest_t	event;
479 	int				numbytes;
480 
481 	bzero(memp, sizeof (*event));
482 	event = (void *)memp;
483 	ddi_put8(accessp, &event->Function, MPI2_FUNCTION_EVENT_NOTIFICATION);
484 	numbytes = sizeof (*event);
485 
486 	/*
487 	 * Send message via handshake
488 	 */
489 	if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
490 		return (DDI_FAILURE);
491 	}
492 
493 	return (DDI_SUCCESS);
494 }
495 
496 static int
497 mptsas_ioc_do_enable_event_notification_reply(mptsas_t *mpt, caddr_t memp,
498     int var, ddi_acc_handle_t accessp)
499 {
500 #ifndef __lock_lint
501 	_NOTE(ARGUNUSED(var))
502 #endif
503 	int				numbytes;
504 	uint_t				iocstatus;
505 	pMpi2EventNotificationReply_t	eventsreply;
506 
507 	numbytes = sizeof (MPI2_EVENT_NOTIFICATION_REPLY);
508 	bzero(memp, numbytes);
509 	eventsreply = (void *)memp;
510 
511 	/*
512 	 * Get message via handshake
513 	 */
514 	if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
515 		return (DDI_FAILURE);
516 	}
517 
518 	if (iocstatus = ddi_get16(accessp, &eventsreply->IOCStatus)) {
519 		mptsas_log(mpt, CE_WARN,
520 		    "mptsas_ioc_do_enable_event_notification_reply: "
521 		    "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
522 		    ddi_get32(accessp, &eventsreply->IOCLogInfo));
523 		return (DDI_FAILURE);
524 	}
525 
526 	return (DDI_SUCCESS);
527 }
528 
529 int
530 mptsas_ioc_init(mptsas_t *mpt)
531 {
532 	/*
533 	 * Send ioc init message
534 	 */
535 	if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_INIT_REQUEST), NULL,
536 	    mptsas_do_ioc_init)) {
537 		return (DDI_FAILURE);
538 	}
539 
540 	/*
541 	 * Get ioc init reply message
542 	 */
543 	if (mptsas_do_dma(mpt, sizeof (MPI2_IOC_INIT_REPLY), NULL,
544 	    mptsas_do_ioc_init_reply)) {
545 		return (DDI_FAILURE);
546 	}
547 
548 	return (DDI_SUCCESS);
549 }
550 
551 static int
552 mptsas_do_ioc_init(mptsas_t *mpt, caddr_t memp, int var,
553     ddi_acc_handle_t accessp)
554 {
555 #ifndef __lock_lint
556 	_NOTE(ARGUNUSED(var))
557 #endif
558 
559 	pMpi2IOCInitRequest_t	init;
560 	int			numbytes;
561 
562 	bzero(memp, sizeof (*init));
563 	init = (void *)memp;
564 	ddi_put8(accessp, &init->Function, MPI2_FUNCTION_IOC_INIT);
565 	ddi_put8(accessp, &init->WhoInit, MPI2_WHOINIT_HOST_DRIVER);
566 	ddi_put16(accessp, &init->MsgVersion, MPI2_VERSION);
567 	ddi_put16(accessp, &init->HeaderVersion, MPI2_HEADER_VERSION);
568 	ddi_put16(accessp, &init->SystemRequestFrameSize,
569 	    mpt->m_req_frame_size / 4);
570 	ddi_put16(accessp, &init->ReplyDescriptorPostQueueDepth,
571 	    mpt->m_post_queue_depth);
572 	ddi_put16(accessp, &init->ReplyFreeQueueDepth,
573 	    mpt->m_free_queue_depth);
574 
575 	/*
576 	 * These addresses are set using the DMA cookie addresses from when the
577 	 * memory was allocated.  Sense buffer hi address should be 0.
578 	 */
579 	ddi_put32(accessp, &init->SenseBufferAddressHigh, 0);
580 	ddi_put32(accessp, &init->SystemReplyAddressHigh,
581 	    (uint32_t)(mpt->m_reply_frame_dma_addr >> 32));
582 	ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.High,
583 	    (uint32_t)(mpt->m_req_frame_dma_addr >> 32));
584 	ddi_put32(accessp, &init->SystemRequestFrameBaseAddress.Low,
585 	    (uint32_t)mpt->m_req_frame_dma_addr);
586 	ddi_put32(accessp, &init->ReplyDescriptorPostQueueAddress.High,
587 	    (uint32_t)(mpt->m_post_queue_dma_addr >> 32));
588 	ddi_put32(accessp, &init->ReplyDescriptorPostQueueAddress.Low,
589 	    (uint32_t)mpt->m_post_queue_dma_addr);
590 	ddi_put32(accessp, &init->ReplyFreeQueueAddress.High,
591 	    (uint32_t)(mpt->m_free_queue_dma_addr >> 32));
592 	ddi_put32(accessp, &init->ReplyFreeQueueAddress.Low,
593 	    (uint32_t)mpt->m_free_queue_dma_addr);
594 
595 	numbytes = sizeof (*init);
596 
597 	/*
598 	 * Post message via handshake
599 	 */
600 	if (mptsas_send_handshake_msg(mpt, memp, numbytes, accessp)) {
601 		return (DDI_FAILURE);
602 	}
603 
604 	return (DDI_SUCCESS);
605 }
606 
607 static int
608 mptsas_do_ioc_init_reply(mptsas_t *mpt, caddr_t memp, int var,
609 		ddi_acc_handle_t accessp)
610 {
611 #ifndef __lock_lint
612 	_NOTE(ARGUNUSED(var))
613 #endif
614 
615 	pMpi2IOCInitReply_t	initreply;
616 	int			numbytes;
617 	uint_t			iocstatus;
618 
619 	numbytes = sizeof (MPI2_IOC_INIT_REPLY);
620 	bzero(memp, numbytes);
621 	initreply = (void *)memp;
622 
623 	/*
624 	 * Get reply message via handshake
625 	 */
626 	if (mptsas_get_handshake_msg(mpt, memp, numbytes, accessp)) {
627 		return (DDI_FAILURE);
628 	}
629 
630 	if (iocstatus = ddi_get16(accessp, &initreply->IOCStatus)) {
631 		mptsas_log(mpt, CE_WARN, "mptsas_do_ioc_init_reply: "
632 		    "IOCStatus=0x%x, IOCLogInfo=0x%x", iocstatus,
633 		    ddi_get32(accessp, &initreply->IOCLogInfo));
634 		return (DDI_FAILURE);
635 	}
636 
637 	if ((ddi_get32(mpt->m_datap, &mpt->m_reg->Doorbell)) &
638 	    MPI2_IOC_STATE_OPERATIONAL) {
639 		mptsas_log(mpt, CE_NOTE,
640 		    "?mpt%d: IOC Operational.\n", mpt->m_instance);
641 	} else {
642 		return (DDI_FAILURE);
643 	}
644 
645 	return (DDI_SUCCESS);
646 }
647