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