1 /* $NetBSD: mpt.c,v 1.21 2019/09/23 16:19:33 skrll Exp $ */
2
3 /*
4 * Copyright (c) 2000, 2001 by Greg Ansley
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice immediately at the beginning of the file, without modification,
11 * this list of conditions, and the following disclaimer.
12 * 2. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27 /*
28 * Additional Copyright (c) 2002 by Matthew Jacob under same license.
29 */
30 /*-
31 * Copyright (c) 2002, 2006 by Matthew Jacob
32 * All rights reserved.
33 *
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions are
36 * met:
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
40 * substantially similar to the "NO WARRANTY" disclaimer below
41 * ("Disclaimer") and any redistribution must be conditioned upon including
42 * a substantially similar Disclaimer requirement for further binary
43 * redistribution.
44 * 3. Neither the names of the above listed copyright holders nor the names
45 * of any contributors may be used to endorse or promote products derived
46 * from this software without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
49 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
52 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
58 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 *
60 * Support from Chris Ellsworth in order to make SAS adapters work
61 * is gratefully acknowledged.
62 *
63 *
64 * Support from LSI-Logic has also gone a great deal toward making this a
65 * workable subsystem and is gratefully acknowledged.
66 */
67 /*-
68 * Copyright (c) 2004, Avid Technology, Inc. and its contributors.
69 * Copyright (c) 2005, WHEEL Sp. z o.o.
70 * Copyright (c) 2004, 2005 Justin T. Gibbs
71 * All rights reserved.
72 *
73 * Redistribution and use in source and binary forms, with or without
74 * modification, are permitted provided that the following conditions are
75 * met:
76 * 1. Redistributions of source code must retain the above copyright
77 * notice, this list of conditions and the following disclaimer.
78 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
79 * substantially similar to the "NO WARRANTY" disclaimer below
80 * ("Disclaimer") and any redistribution must be conditioned upon including
81 * a substantially similar Disclaimer requirement for further binary
82 * redistribution.
83 * 3. Neither the names of the above listed copyright holders nor the names
84 * of any contributors may be used to endorse or promote products derived
85 * from this software without specific prior written permission.
86 *
87 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
88 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
89 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
90 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
91 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
92 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
93 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
94 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
95 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
96 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
97 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
98 */
99
100
101 /*
102 * mpt.c:
103 *
104 * Generic routines for LSI Fusion adapters.
105 *
106 * Adapted from the FreeBSD "mpt" driver by Jason R. Thorpe for
107 * Wasabi Systems, Inc.
108 *
109 * Additional contributions by Garrett D'Amore on behalf of TELES AG.
110 */
111
112 #include <sys/cdefs.h>
113 __KERNEL_RCSID(0, "$NetBSD: mpt.c,v 1.21 2019/09/23 16:19:33 skrll Exp $");
114
115 #include <dev/ic/mpt.h>
116
117 #define MPT_MAX_TRYS 3
118 #define MPT_MAX_WAIT 300000
119
120 static int maxwait_ack = 0;
121 static int maxwait_int = 0;
122 static int maxwait_state = 0;
123
124 static inline u_int32_t
mpt_rd_db(mpt_softc_t * mpt)125 mpt_rd_db(mpt_softc_t *mpt)
126 {
127 return mpt_read(mpt, MPT_OFFSET_DOORBELL);
128 }
129
130 static inline u_int32_t
mpt_rd_intr(mpt_softc_t * mpt)131 mpt_rd_intr(mpt_softc_t *mpt)
132 {
133 return mpt_read(mpt, MPT_OFFSET_INTR_STATUS);
134 }
135
136 /* Busy wait for a door bell to be read by IOC */
137 static int
mpt_wait_db_ack(mpt_softc_t * mpt)138 mpt_wait_db_ack(mpt_softc_t *mpt)
139 {
140 int i;
141 for (i=0; i < MPT_MAX_WAIT; i++) {
142 if (!MPT_DB_IS_BUSY(mpt_rd_intr(mpt))) {
143 maxwait_ack = i > maxwait_ack ? i : maxwait_ack;
144 return MPT_OK;
145 }
146
147 DELAY(100);
148 }
149 return MPT_FAIL;
150 }
151
152 /* Busy wait for a door bell interrupt */
153 static int
mpt_wait_db_int(mpt_softc_t * mpt)154 mpt_wait_db_int(mpt_softc_t *mpt)
155 {
156 int i;
157 for (i=0; i < MPT_MAX_WAIT; i++) {
158 if (MPT_DB_INTR(mpt_rd_intr(mpt))) {
159 maxwait_int = i > maxwait_int ? i : maxwait_int;
160 return MPT_OK;
161 }
162 DELAY(100);
163 }
164 return MPT_FAIL;
165 }
166
167 /* Wait for IOC to transition to a give state */
168 void
mpt_check_doorbell(mpt_softc_t * mpt)169 mpt_check_doorbell(mpt_softc_t *mpt)
170 {
171 u_int32_t db = mpt_rd_db(mpt);
172 if (MPT_STATE(db) != MPT_DB_STATE_RUNNING) {
173 mpt_prt(mpt, "Device not running");
174 mpt_print_db(db);
175 }
176 }
177
178 /* Wait for IOC to transition to a give state */
179 static int
mpt_wait_state(mpt_softc_t * mpt,enum DB_STATE_BITS state)180 mpt_wait_state(mpt_softc_t *mpt, enum DB_STATE_BITS state)
181 {
182 int i;
183
184 for (i = 0; i < MPT_MAX_WAIT; i++) {
185 u_int32_t db = mpt_rd_db(mpt);
186 if (MPT_STATE(db) == state) {
187 maxwait_state = i > maxwait_state ? i : maxwait_state;
188 return (MPT_OK);
189 }
190 DELAY(100);
191 }
192 return (MPT_FAIL);
193 }
194
195
196 /* Issue the reset COMMAND to the IOC */
197 int
mpt_soft_reset(mpt_softc_t * mpt)198 mpt_soft_reset(mpt_softc_t *mpt)
199 {
200 if (mpt->verbose) {
201 mpt_prt(mpt, "soft reset");
202 }
203
204 /* Have to use hard reset if we are not in Running state */
205 if (MPT_STATE(mpt_rd_db(mpt)) != MPT_DB_STATE_RUNNING) {
206 mpt_prt(mpt, "soft reset failed: device not running");
207 return MPT_FAIL;
208 }
209
210 /* If door bell is in use we don't have a chance of getting
211 * a word in since the IOC probably crashed in message
212 * processing. So don't waste our time.
213 */
214 if (MPT_DB_IS_IN_USE(mpt_rd_db(mpt))) {
215 mpt_prt(mpt, "soft reset failed: doorbell wedged");
216 return MPT_FAIL;
217 }
218
219 /* Send the reset request to the IOC */
220 mpt_write(mpt, MPT_OFFSET_DOORBELL,
221 MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET << MPI_DOORBELL_FUNCTION_SHIFT);
222 if (mpt_wait_db_ack(mpt) != MPT_OK) {
223 mpt_prt(mpt, "soft reset failed: ack timeout");
224 return MPT_FAIL;
225 }
226
227 /* Wait for the IOC to reload and come out of reset state */
228 if (mpt_wait_state(mpt, MPT_DB_STATE_READY) != MPT_OK) {
229 mpt_prt(mpt, "soft reset failed: device did not start running");
230 return MPT_FAIL;
231 }
232
233 return MPT_OK;
234 }
235
236 /* This is a magic diagnostic reset that resets all the ARM
237 * processors in the chip.
238 */
239 void
mpt_hard_reset(mpt_softc_t * mpt)240 mpt_hard_reset(mpt_softc_t *mpt)
241 {
242 if (mpt->verbose) {
243 mpt_prt(mpt, "hard reset");
244 }
245 mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xff);
246
247 /* Enable diagnostic registers */
248 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_1);
249 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_2);
250 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_3);
251 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_4);
252 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_5);
253
254 /* Diag. port is now active so we can now hit the reset bit */
255 mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, MPT_DIAG_RESET_IOC);
256
257 DELAY(10000);
258
259 /* Disable Diagnostic Register */
260 mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFF);
261 }
262
263 /*
264 * Reset the IOC when needed. Try software command first then if needed
265 * poke at the magic diagnostic reset. Note that a hard reset resets
266 * *both* IOCs on dual function chips (FC929 && LSI1030) as well as
267 * fouls up the PCI configuration registers.
268 */
269 int
mpt_reset(mpt_softc_t * mpt)270 mpt_reset(mpt_softc_t *mpt)
271 {
272 int ret;
273
274 /* Try a soft reset */
275 if ((ret = mpt_soft_reset(mpt)) != MPT_OK) {
276 /* Failed; do a hard reset */
277 mpt_hard_reset(mpt);
278
279 /* Wait for the IOC to reload and come out of reset state */
280 ret = mpt_wait_state(mpt, MPT_DB_STATE_READY);
281 if (ret != MPT_OK) {
282 mpt_prt(mpt, "failed to reset device");
283 }
284 }
285
286 return ret;
287 }
288
289 /* Return a command buffer to the free queue */
290 void
mpt_free_request(mpt_softc_t * mpt,request_t * req)291 mpt_free_request(mpt_softc_t *mpt, request_t *req)
292 {
293 if (req == NULL || req != &mpt->request_pool[req->index]) {
294 panic("mpt_free_request bad req ptr\n");
295 return;
296 }
297 req->sequence = 0;
298 req->xfer = NULL;
299 req->debug = REQ_FREE;
300 SLIST_INSERT_HEAD(&mpt->request_free_list, req, link);
301 }
302
303 /* Get a command buffer from the free queue */
304 request_t *
mpt_get_request(mpt_softc_t * mpt)305 mpt_get_request(mpt_softc_t *mpt)
306 {
307 request_t *req;
308 req = SLIST_FIRST(&mpt->request_free_list);
309 if (req != NULL) {
310 if (req != &mpt->request_pool[req->index]) {
311 panic("mpt_get_request: corrupted request free list\n");
312 }
313 if (req->xfer != NULL) {
314 panic("mpt_get_request: corrupted request free list (xfer)\n");
315 }
316 SLIST_REMOVE_HEAD(&mpt->request_free_list, link);
317 req->debug = REQ_IN_PROGRESS;
318 }
319 return req;
320 }
321
322 /* Pass the command to the IOC */
323 void
mpt_send_cmd(mpt_softc_t * mpt,request_t * req)324 mpt_send_cmd(mpt_softc_t *mpt, request_t *req)
325 {
326 req->sequence = mpt->sequence++;
327 if (mpt->verbose > 1) {
328 u_int32_t *pReq;
329 pReq = req->req_vbuf;
330 mpt_prt(mpt, "Send Request %d (%#" PRIxBUSADDR "):",
331 req->index, req->req_pbuf);
332 mpt_prt(mpt, "%08x %08x %08x %08x",
333 pReq[0], pReq[1], pReq[2], pReq[3]);
334 mpt_prt(mpt, "%08x %08x %08x %08x",
335 pReq[4], pReq[5], pReq[6], pReq[7]);
336 mpt_prt(mpt, "%08x %08x %08x %08x",
337 pReq[8], pReq[9], pReq[10], pReq[11]);
338 mpt_prt(mpt, "%08x %08x %08x %08x",
339 pReq[12], pReq[13], pReq[14], pReq[15]);
340 }
341 MPT_SYNC_REQ(mpt, req, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
342 req->debug = REQ_ON_CHIP;
343 mpt_write(mpt, MPT_OFFSET_REQUEST_Q, (u_int32_t) req->req_pbuf);
344 }
345
346 /*
347 * Give the reply buffer back to the IOC after we have
348 * finished processing it.
349 */
350 void
mpt_free_reply(mpt_softc_t * mpt,u_int32_t ptr)351 mpt_free_reply(mpt_softc_t *mpt, u_int32_t ptr)
352 {
353 mpt_write(mpt, MPT_OFFSET_REPLY_Q, ptr);
354 }
355
356 /* Get a reply from the IOC */
357 u_int32_t
mpt_pop_reply_queue(mpt_softc_t * mpt)358 mpt_pop_reply_queue(mpt_softc_t *mpt)
359 {
360 return mpt_read(mpt, MPT_OFFSET_REPLY_Q);
361 }
362
363 /*
364 * Send a command to the IOC via the handshake register.
365 *
366 * Only done at initialization time and for certain unusual
367 * commands such as device/bus reset as specified by LSI.
368 */
369 int
mpt_send_handshake_cmd(mpt_softc_t * mpt,size_t len,void * cmd)370 mpt_send_handshake_cmd(mpt_softc_t *mpt, size_t len, void *cmd)
371 {
372 int i;
373 u_int32_t data, *data32;
374
375 /* Check condition of the IOC */
376 data = mpt_rd_db(mpt);
377 if (((MPT_STATE(data) != MPT_DB_STATE_READY) &&
378 (MPT_STATE(data) != MPT_DB_STATE_RUNNING) &&
379 (MPT_STATE(data) != MPT_DB_STATE_FAULT)) ||
380 ( MPT_DB_IS_IN_USE(data) )) {
381 mpt_prt(mpt, "handshake aborted due to invalid doorbell state");
382 mpt_print_db(data);
383 return(EBUSY);
384 }
385
386 /* We move things in 32 bit chunks */
387 len = (len + 3) >> 2;
388 data32 = cmd;
389
390 /* Clear any left over pending doorbell interrupts */
391 if (MPT_DB_INTR(mpt_rd_intr(mpt)))
392 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
393
394 /*
395 * Tell the handshake reg. we are going to send a command
396 * and how long it is going to be.
397 */
398 data = (MPI_FUNCTION_HANDSHAKE << MPI_DOORBELL_FUNCTION_SHIFT) |
399 (len << MPI_DOORBELL_ADD_DWORDS_SHIFT);
400 mpt_write(mpt, MPT_OFFSET_DOORBELL, data);
401
402 /* Wait for the chip to notice */
403 if (mpt_wait_db_int(mpt) != MPT_OK) {
404 mpt_prt(mpt, "mpt_send_handshake_cmd timeout1");
405 return ETIMEDOUT;
406 }
407
408 /* Clear the interrupt */
409 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
410
411 if (mpt_wait_db_ack(mpt) != MPT_OK) {
412 mpt_prt(mpt, "mpt_send_handshake_cmd timeout2");
413 return ETIMEDOUT;
414 }
415
416 /* Send the command */
417 for (i = 0; i < len; i++) {
418 mpt_write(mpt, MPT_OFFSET_DOORBELL, htole32(*data32++));
419 if (mpt_wait_db_ack(mpt) != MPT_OK) {
420 mpt_prt(mpt,
421 "mpt_send_handshake_cmd timeout! index = %d", i);
422 return ETIMEDOUT;
423 }
424 }
425 return MPT_OK;
426 }
427
428 /* Get the response from the handshake register */
429 int
mpt_recv_handshake_reply(mpt_softc_t * mpt,size_t reply_len,void * reply)430 mpt_recv_handshake_reply(mpt_softc_t *mpt, size_t reply_len, void *reply)
431 {
432 int left, reply_left;
433 u_int16_t *data16;
434 MSG_DEFAULT_REPLY *hdr;
435
436 /* We move things out in 16 bit chunks */
437 reply_len >>= 1;
438 data16 = (u_int16_t *)reply;
439
440 hdr = (MSG_DEFAULT_REPLY *)reply;
441
442 /* Get first word */
443 if (mpt_wait_db_int(mpt) != MPT_OK) {
444 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout1");
445 return ETIMEDOUT;
446 }
447 *data16++ = le16toh(mpt_read(mpt, MPT_OFFSET_DOORBELL) &
448 MPT_DB_DATA_MASK);
449 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
450
451 /* Get Second Word */
452 if (mpt_wait_db_int(mpt) != MPT_OK) {
453 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout2");
454 return ETIMEDOUT;
455 }
456 *data16++ = le16toh(mpt_read(mpt, MPT_OFFSET_DOORBELL) &
457 MPT_DB_DATA_MASK);
458 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
459
460 /* With the second word, we can now look at the length */
461 if (mpt->verbose > 1 && ((reply_len >> 1) != hdr->MsgLength)) {
462 mpt_prt(mpt, "reply length does not match message length: "
463 "got 0x%02x, expected %#02zx",
464 hdr->MsgLength << 2, reply_len << 1);
465 }
466
467 /* Get rest of the reply; but don't overflow the provided buffer */
468 left = (hdr->MsgLength << 1) - 2;
469 reply_left = reply_len - 2;
470 while (left--) {
471 u_int16_t datum;
472
473 if (mpt_wait_db_int(mpt) != MPT_OK) {
474 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout3");
475 return ETIMEDOUT;
476 }
477 datum = mpt_read(mpt, MPT_OFFSET_DOORBELL);
478
479 if (reply_left-- > 0)
480 *data16++ = le16toh(datum & MPT_DB_DATA_MASK);
481
482 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
483 }
484
485 /* One more wait & clear at the end */
486 if (mpt_wait_db_int(mpt) != MPT_OK) {
487 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout4");
488 return ETIMEDOUT;
489 }
490 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
491
492 if ((hdr->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
493 if (mpt->verbose > 1)
494 mpt_print_reply(hdr);
495 return (MPT_FAIL | hdr->IOCStatus);
496 }
497
498 return (0);
499 }
500
501 static int
mpt_get_iocfacts(mpt_softc_t * mpt,MSG_IOC_FACTS_REPLY * freplp)502 mpt_get_iocfacts(mpt_softc_t *mpt, MSG_IOC_FACTS_REPLY *freplp)
503 {
504 MSG_IOC_FACTS f_req;
505 int error;
506
507 memset(&f_req, 0, sizeof f_req);
508 f_req.Function = MPI_FUNCTION_IOC_FACTS;
509 f_req.MsgContext = htole32(0x12071942);
510 error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
511 if (error)
512 return(error);
513 error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
514 return (error);
515 }
516
517 static int
mpt_get_portfacts(mpt_softc_t * mpt,MSG_PORT_FACTS_REPLY * freplp)518 mpt_get_portfacts(mpt_softc_t *mpt, MSG_PORT_FACTS_REPLY *freplp)
519 {
520 MSG_PORT_FACTS f_req;
521 int error;
522
523 /* XXX: Only getting PORT FACTS for Port 0 */
524 memset(&f_req, 0, sizeof f_req);
525 f_req.Function = MPI_FUNCTION_PORT_FACTS;
526 f_req.MsgContext = htole32(0x12071943);
527 error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
528 if (error)
529 return(error);
530 error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
531 return (error);
532 }
533
534 /*
535 * Send the initialization request. This is where we specify how many
536 * SCSI busses and how many devices per bus we wish to emulate.
537 * This is also the command that specifies the max size of the reply
538 * frames from the IOC that we will be allocating.
539 */
540 static int
mpt_send_ioc_init(mpt_softc_t * mpt,u_int32_t who)541 mpt_send_ioc_init(mpt_softc_t *mpt, u_int32_t who)
542 {
543 int error = 0;
544 MSG_IOC_INIT init;
545 MSG_IOC_INIT_REPLY reply;
546
547 memset(&init, 0, sizeof init);
548 init.WhoInit = who;
549 init.Function = MPI_FUNCTION_IOC_INIT;
550 init.MaxDevices = mpt->mpt_max_devices;
551 init.MaxBuses = 1;
552 init.ReplyFrameSize = htole16(MPT_REPLY_SIZE);
553 init.MsgContext = htole32(0x12071941);
554
555 if ((error = mpt_send_handshake_cmd(mpt, sizeof init, &init)) != 0) {
556 return(error);
557 }
558
559 error = mpt_recv_handshake_reply(mpt, sizeof reply, &reply);
560 return (error);
561 }
562
563
564 /*
565 * Utiltity routine to read configuration headers and pages
566 */
567
568 int
mpt_read_cfg_header(mpt_softc_t * mpt,int PageType,int PageNumber,int PageAddress,fCONFIG_PAGE_HEADER * rslt)569 mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber,
570 int PageAddress, fCONFIG_PAGE_HEADER *rslt)
571 {
572 int count;
573 request_t *req;
574 MSG_CONFIG *cfgp;
575 MSG_CONFIG_REPLY *reply;
576
577 req = mpt_get_request(mpt);
578
579 cfgp = req->req_vbuf;
580 memset(cfgp, 0, sizeof *cfgp);
581
582 cfgp->Action = MPI_CONFIG_ACTION_PAGE_HEADER;
583 cfgp->Function = MPI_FUNCTION_CONFIG;
584 cfgp->Header.PageNumber = (U8) PageNumber;
585 cfgp->Header.PageType = (U8) PageType;
586 cfgp->PageAddress = htole32(PageAddress);
587 MPI_pSGE_SET_FLAGS(((SGE_SIMPLE32 *) &cfgp->PageBufferSGE),
588 (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
589 MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
590 cfgp->MsgContext = htole32(req->index | 0x80000000);
591
592 mpt_check_doorbell(mpt);
593 mpt_send_cmd(mpt, req);
594 count = 0;
595 do {
596 DELAY(500);
597 mpt_intr(mpt);
598 if (++count == 1000) {
599 mpt_prt(mpt, "read_cfg_header timed out");
600 return (-1);
601 }
602 } while (req->debug == REQ_ON_CHIP);
603
604 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
605 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
606 mpt_prt(mpt, "mpt_read_cfg_header: Config Info Status %x",
607 reply->IOCStatus);
608 mpt_free_reply(mpt, (req->sequence << 1));
609 return (-1);
610 }
611 memcpy(rslt, &reply->Header, sizeof (fCONFIG_PAGE_HEADER));
612 mpt_free_reply(mpt, (req->sequence << 1));
613 mpt_free_request(mpt, req);
614 return (0);
615 }
616
617 #define CFG_DATA_OFF 128
618
619 int
mpt_read_cfg_page(mpt_softc_t * mpt,int PageAddress,fCONFIG_PAGE_HEADER * hdr)620 mpt_read_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
621 {
622 int count;
623 request_t *req;
624 SGE_SIMPLE32 *se;
625 MSG_CONFIG *cfgp;
626 size_t amt;
627 MSG_CONFIG_REPLY *reply;
628
629 req = mpt_get_request(mpt);
630
631 cfgp = req->req_vbuf;
632 memset(cfgp, 0, MPT_REQUEST_AREA);
633 cfgp->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
634 cfgp->Function = MPI_FUNCTION_CONFIG;
635 cfgp->Header = *hdr;
636 amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
637 cfgp->Header.PageType &= MPI_CONFIG_PAGETYPE_MASK;
638 cfgp->PageAddress = htole32(PageAddress);
639 se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
640 se->Address = htole32(req->req_pbuf + CFG_DATA_OFF);
641 MPI_pSGE_SET_LENGTH(se, amt);
642 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
643 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
644 MPI_SGE_FLAGS_END_OF_LIST));
645 se->FlagsLength = htole32(se->FlagsLength);
646
647 cfgp->MsgContext = htole32(req->index | 0x80000000);
648
649 mpt_check_doorbell(mpt);
650 mpt_send_cmd(mpt, req);
651 count = 0;
652 do {
653 DELAY(500);
654 mpt_intr(mpt);
655 if (++count == 1000) {
656 mpt_prt(mpt, "read_cfg_page timed out");
657 return (-1);
658 }
659 } while (req->debug == REQ_ON_CHIP);
660
661 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
662 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
663 mpt_prt(mpt, "mpt_read_cfg_page: Config Info Status %x",
664 reply->IOCStatus);
665 mpt_free_reply(mpt, (req->sequence << 1));
666 return (-1);
667 }
668 mpt_free_reply(mpt, (req->sequence << 1));
669 #if 0 /* XXXJRT */
670 bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap,
671 BUS_DMASYNC_POSTREAD);
672 #endif
673 if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
674 cfgp->Header.PageNumber == 0) {
675 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
676 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
677 cfgp->Header.PageNumber == 1) {
678 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
679 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
680 cfgp->Header.PageNumber == 2) {
681 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
682 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
683 cfgp->Header.PageNumber == 0) {
684 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
685 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
686 cfgp->Header.PageNumber == 1) {
687 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
688 }
689 memcpy(hdr, (char *)req->req_vbuf + CFG_DATA_OFF, amt);
690 mpt_free_request(mpt, req);
691 return (0);
692 }
693
694 int
mpt_write_cfg_page(mpt_softc_t * mpt,int PageAddress,fCONFIG_PAGE_HEADER * hdr)695 mpt_write_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
696 {
697 int count, hdr_attr;
698 request_t *req;
699 SGE_SIMPLE32 *se;
700 MSG_CONFIG *cfgp;
701 size_t amt;
702 MSG_CONFIG_REPLY *reply;
703
704 req = mpt_get_request(mpt);
705
706 cfgp = req->req_vbuf;
707 memset(cfgp, 0, sizeof *cfgp);
708
709 hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK;
710 if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE &&
711 hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) {
712 mpt_prt(mpt, "page type 0x%x not changeable",
713 hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
714 return (-1);
715 }
716 hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK;
717
718 cfgp->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
719 cfgp->Function = MPI_FUNCTION_CONFIG;
720 cfgp->Header = *hdr;
721 amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
722 cfgp->PageAddress = htole32(PageAddress);
723
724 se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
725 se->Address = htole32(req->req_pbuf + CFG_DATA_OFF);
726 MPI_pSGE_SET_LENGTH(se, amt);
727 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
728 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
729 MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_HOST_TO_IOC));
730 se->FlagsLength = htole32(se->FlagsLength);
731
732 cfgp->MsgContext = htole32(req->index | 0x80000000);
733
734 if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
735 cfgp->Header.PageNumber == 0) {
736 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
737 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
738 cfgp->Header.PageNumber == 1) {
739 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
740 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
741 cfgp->Header.PageNumber == 2) {
742 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
743 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
744 cfgp->Header.PageNumber == 0) {
745 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
746 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
747 cfgp->Header.PageNumber == 1) {
748 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
749 }
750 memcpy((char *)req->req_vbuf + CFG_DATA_OFF, hdr, amt);
751 /* Restore stripped out attributes */
752 hdr->PageType |= hdr_attr;
753
754 mpt_check_doorbell(mpt);
755 mpt_send_cmd(mpt, req);
756 count = 0;
757 do {
758 DELAY(500);
759 mpt_intr(mpt);
760 if (++count == 1000) {
761 hdr->PageType |= hdr_attr;
762 mpt_prt(mpt, "mpt_write_cfg_page timed out");
763 return (-1);
764 }
765 } while (req->debug == REQ_ON_CHIP);
766
767 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
768 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
769 mpt_prt(mpt, "mpt_write_cfg_page: Config Info Status %x",
770 le16toh(reply->IOCStatus));
771 mpt_free_reply(mpt, (req->sequence << 1));
772 return (-1);
773 }
774 mpt_free_reply(mpt, (req->sequence << 1));
775
776 mpt_free_request(mpt, req);
777 return (0);
778 }
779
780 /*
781 * Read SCSI configuration information
782 */
783 static int
mpt_read_config_info_spi(mpt_softc_t * mpt)784 mpt_read_config_info_spi(mpt_softc_t *mpt)
785 {
786 int rv, i;
787
788 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0,
789 0, &mpt->mpt_port_page0.Header);
790 if (rv) {
791 return (-1);
792 }
793 if (mpt->verbose > 1) {
794 mpt_prt(mpt, "SPI Port Page 0 Header: %x %x %x %x",
795 mpt->mpt_port_page0.Header.PageVersion,
796 mpt->mpt_port_page0.Header.PageLength,
797 mpt->mpt_port_page0.Header.PageNumber,
798 mpt->mpt_port_page0.Header.PageType);
799 }
800
801 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1,
802 0, &mpt->mpt_port_page1.Header);
803 if (rv) {
804 return (-1);
805 }
806 if (mpt->verbose > 1) {
807 mpt_prt(mpt, "SPI Port Page 1 Header: %x %x %x %x",
808 mpt->mpt_port_page1.Header.PageVersion,
809 mpt->mpt_port_page1.Header.PageLength,
810 mpt->mpt_port_page1.Header.PageNumber,
811 mpt->mpt_port_page1.Header.PageType);
812 }
813
814 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2,
815 0, &mpt->mpt_port_page2.Header);
816 if (rv) {
817 return (-1);
818 }
819
820 if (mpt->verbose > 1) {
821 mpt_prt(mpt, "SPI Port Page 2 Header: %x %x %x %x",
822 mpt->mpt_port_page1.Header.PageVersion,
823 mpt->mpt_port_page1.Header.PageLength,
824 mpt->mpt_port_page1.Header.PageNumber,
825 mpt->mpt_port_page1.Header.PageType);
826 }
827
828 for (i = 0; i < 16; i++) {
829 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
830 0, i, &mpt->mpt_dev_page0[i].Header);
831 if (rv) {
832 return (-1);
833 }
834 if (mpt->verbose > 1) {
835 mpt_prt(mpt,
836 "SPI Target %d Device Page 0 Header: %x %x %x %x",
837 i, mpt->mpt_dev_page0[i].Header.PageVersion,
838 mpt->mpt_dev_page0[i].Header.PageLength,
839 mpt->mpt_dev_page0[i].Header.PageNumber,
840 mpt->mpt_dev_page0[i].Header.PageType);
841 }
842
843 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
844 1, i, &mpt->mpt_dev_page1[i].Header);
845 if (rv) {
846 return (-1);
847 }
848 if (mpt->verbose > 1) {
849 mpt_prt(mpt,
850 "SPI Target %d Device Page 1 Header: %x %x %x %x",
851 i, mpt->mpt_dev_page1[i].Header.PageVersion,
852 mpt->mpt_dev_page1[i].Header.PageLength,
853 mpt->mpt_dev_page1[i].Header.PageNumber,
854 mpt->mpt_dev_page1[i].Header.PageType);
855 }
856 }
857
858 /*
859 * At this point, we don't *have* to fail. As long as we have
860 * valid config header information, we can (barely) lurch
861 * along.
862 */
863
864 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page0.Header);
865 mpt2host_config_page_scsi_port_0(&mpt->mpt_port_page0);
866 if (rv) {
867 mpt_prt(mpt, "failed to read SPI Port Page 0");
868 } else if (mpt->verbose > 1) {
869 mpt_prt(mpt,
870 "SPI Port Page 0: Capabilities %x PhysicalInterface %x",
871 mpt->mpt_port_page0.Capabilities,
872 mpt->mpt_port_page0.PhysicalInterface);
873 }
874
875 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header);
876 mpt2host_config_page_scsi_port_1(&mpt->mpt_port_page1);
877 if (rv) {
878 mpt_prt(mpt, "failed to read SPI Port Page 1");
879 } else if (mpt->verbose > 1) {
880 mpt_prt(mpt,
881 "SPI Port Page 1: Configuration %x OnBusTimerValue %x",
882 mpt->mpt_port_page1.Configuration,
883 mpt->mpt_port_page1.OnBusTimerValue);
884 }
885
886 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header);
887 mpt2host_config_page_scsi_port_2(&mpt->mpt_port_page2);
888 if (rv) {
889 mpt_prt(mpt, "failed to read SPI Port Page 2");
890 } else if (mpt->verbose > 1) {
891 mpt_prt(mpt,
892 "SPI Port Page 2: Flags %x Settings %x",
893 mpt->mpt_port_page2.PortFlags,
894 mpt->mpt_port_page2.PortSettings);
895 for (i = 0; i < 1; i++) {
896 mpt_prt(mpt,
897 "SPI Port Page 2 Tgt %d: timo %x SF %x Flags %x",
898 i, mpt->mpt_port_page2.DeviceSettings[i].Timeout,
899 mpt->mpt_port_page2.DeviceSettings[i].SyncFactor,
900 mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags);
901 }
902 }
903
904 for (i = 0; i < 16; i++) {
905 rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page0[i].Header);
906 mpt2host_config_page_scsi_device_0(&mpt->mpt_dev_page0[i]);
907 if (rv) {
908 mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 0", i);
909 continue;
910 }
911 if (mpt->verbose > 1) {
912 mpt_prt(mpt,
913 "SPI Tgt %d Page 0: NParms %x Information %x",
914 i, mpt->mpt_dev_page0[i].NegotiatedParameters,
915 mpt->mpt_dev_page0[i].Information);
916 }
917 rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page1[i].Header);
918 mpt2host_config_page_scsi_device_1(&mpt->mpt_dev_page1[i]);
919 if (rv) {
920 mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 1", i);
921 continue;
922 }
923 if (mpt->verbose > 1) {
924 mpt_prt(mpt,
925 "SPI Tgt %d Page 1: RParms %x Configuration %x",
926 i, mpt->mpt_dev_page1[i].RequestedParameters,
927 mpt->mpt_dev_page1[i].Configuration);
928 }
929 }
930 return (0);
931 }
932
933 /*
934 * Validate SPI configuration information.
935 *
936 * In particular, validate SPI Port Page 1.
937 */
938 static int
mpt_set_initial_config_spi(mpt_softc_t * mpt)939 mpt_set_initial_config_spi(mpt_softc_t *mpt)
940 {
941 int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id;
942
943 mpt->mpt_disc_enable = 0xffff;
944 mpt->mpt_tag_enable = 0;
945
946 if (mpt->mpt_port_page1.Configuration != pp1val) {
947 fCONFIG_PAGE_SCSI_PORT_1 tmp;
948
949 mpt_prt(mpt,
950 "SPI Port Page 1 Config value bad (%x)- should be %x",
951 mpt->mpt_port_page1.Configuration, pp1val);
952 tmp = mpt->mpt_port_page1;
953 tmp.Configuration = pp1val;
954 host2mpt_config_page_scsi_port_1(&tmp);
955 if (mpt_write_cfg_page(mpt, 0, &tmp.Header)) {
956 return (-1);
957 }
958 if (mpt_read_cfg_page(mpt, 0, &tmp.Header)) {
959 return (-1);
960 }
961 mpt2host_config_page_scsi_port_1(&tmp);
962 if (tmp.Configuration != pp1val) {
963 mpt_prt(mpt,
964 "failed to reset SPI Port Page 1 Config value");
965 return (-1);
966 }
967 mpt->mpt_port_page1 = tmp;
968 }
969
970 i = 0;
971 for (i = 0; i < 16; i++) {
972 fCONFIG_PAGE_SCSI_DEVICE_1 tmp;
973
974 tmp = mpt->mpt_dev_page1[i];
975 tmp.RequestedParameters = 0;
976 tmp.Configuration = 0;
977 if (mpt->verbose > 1) {
978 mpt_prt(mpt,
979 "Set Tgt %d SPI DevicePage 1 values to %x 0 %x",
980 i, tmp.RequestedParameters, tmp.Configuration);
981 }
982 host2mpt_config_page_scsi_device_1(&tmp);
983 if (mpt_write_cfg_page(mpt, i, &tmp.Header)) {
984 return (-1);
985 }
986 if (mpt_read_cfg_page(mpt, i, &tmp.Header)) {
987 return (-1);
988 }
989 mpt2host_config_page_scsi_device_1(&tmp);
990 mpt->mpt_dev_page1[i] = tmp;
991 if (mpt->verbose > 1) {
992 mpt_prt(mpt,
993 "SPI Tgt %d Page 1: RParm %x Configuration %x", i,
994 mpt->mpt_dev_page1[i].RequestedParameters,
995 mpt->mpt_dev_page1[i].Configuration);
996 }
997 }
998 return (0);
999 }
1000
1001 /*
1002 * Enable IOC port
1003 */
1004 static int
mpt_send_port_enable(mpt_softc_t * mpt,int port)1005 mpt_send_port_enable(mpt_softc_t *mpt, int port)
1006 {
1007 int count;
1008 request_t *req;
1009 MSG_PORT_ENABLE *enable_req;
1010
1011 req = mpt_get_request(mpt);
1012
1013 enable_req = req->req_vbuf;
1014 memset(enable_req, 0, sizeof *enable_req);
1015
1016 enable_req->Function = MPI_FUNCTION_PORT_ENABLE;
1017 enable_req->MsgContext = htole32(req->index | 0x80000000);
1018 enable_req->PortNumber = port;
1019
1020 mpt_check_doorbell(mpt);
1021 if (mpt->verbose > 1) {
1022 mpt_prt(mpt, "enabling port %d", port);
1023 }
1024 mpt_send_cmd(mpt, req);
1025
1026 count = 0;
1027 do {
1028 DELAY(500);
1029 mpt_intr(mpt);
1030 if (++count == 100000) {
1031 mpt_prt(mpt, "port enable timed out");
1032 return (-1);
1033 }
1034 } while (req->debug == REQ_ON_CHIP);
1035 mpt_free_request(mpt, req);
1036 return (0);
1037 }
1038
1039 /*
1040 * Enable/Disable asynchronous event reporting.
1041 *
1042 * NB: this is the first command we send via shared memory
1043 * instead of the handshake register.
1044 */
1045 static int
mpt_send_event_request(mpt_softc_t * mpt,int onoff)1046 mpt_send_event_request(mpt_softc_t *mpt, int onoff)
1047 {
1048 request_t *req;
1049 MSG_EVENT_NOTIFY *enable_req;
1050
1051 req = mpt_get_request(mpt);
1052
1053 enable_req = req->req_vbuf;
1054 memset(enable_req, 0, sizeof *enable_req);
1055
1056 enable_req->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
1057 enable_req->MsgContext = htole32(req->index | 0x80000000);
1058 enable_req->Switch = onoff;
1059
1060 mpt_check_doorbell(mpt);
1061 if (mpt->verbose > 1) {
1062 mpt_prt(mpt, "%sabling async events", onoff? "en" : "dis");
1063 }
1064 mpt_send_cmd(mpt, req);
1065
1066 return (0);
1067 }
1068
1069 /*
1070 * Un-mask the interrupts on the chip.
1071 */
1072 void
mpt_enable_ints(mpt_softc_t * mpt)1073 mpt_enable_ints(mpt_softc_t *mpt)
1074 {
1075 /* Unmask every thing except door bell int */
1076 mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK);
1077 }
1078
1079 /*
1080 * Mask the interrupts on the chip.
1081 */
1082 void
mpt_disable_ints(mpt_softc_t * mpt)1083 mpt_disable_ints(mpt_softc_t *mpt)
1084 {
1085 /* Mask all interrupts */
1086 mpt_write(mpt, MPT_OFFSET_INTR_MASK,
1087 MPT_INTR_REPLY_MASK | MPT_INTR_DB_MASK);
1088 }
1089
1090 /* (Re)Initialize the chip for use */
1091 int
mpt_hw_init(mpt_softc_t * mpt)1092 mpt_hw_init(mpt_softc_t *mpt)
1093 {
1094 u_int32_t db;
1095 int try;
1096
1097 /*
1098 * Start by making sure we're not at FAULT or RESET state
1099 */
1100 for (try = 0; try < MPT_MAX_TRYS; try++) {
1101
1102 db = mpt_rd_db(mpt);
1103
1104 switch (MPT_STATE(db)) {
1105 case MPT_DB_STATE_READY:
1106 return (0);
1107
1108 default:
1109 /* if peer has already reset us, don't do it again! */
1110 if (MPT_WHO(db) == MPT_DB_INIT_PCIPEER)
1111 return (0);
1112 /*FALLTHRU*/
1113 case MPT_DB_STATE_RESET:
1114 case MPT_DB_STATE_FAULT:
1115 if (mpt_reset(mpt) != MPT_OK) {
1116 DELAY(10000);
1117 continue;
1118 }
1119 break;
1120 }
1121 }
1122 return (EIO);
1123 }
1124
1125 int
mpt_init(mpt_softc_t * mpt,u_int32_t who)1126 mpt_init(mpt_softc_t *mpt, u_int32_t who)
1127 {
1128 int try;
1129 MSG_IOC_FACTS_REPLY facts;
1130 MSG_PORT_FACTS_REPLY pfp;
1131 prop_dictionary_t dict;
1132 uint32_t ini_id;
1133 uint32_t pptr;
1134 int val;
1135
1136 /* Put all request buffers (back) on the free list */
1137 SLIST_INIT(&mpt->request_free_list);
1138 for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
1139 mpt_free_request(mpt, &mpt->request_pool[val]);
1140 }
1141
1142 if (mpt->verbose > 1) {
1143 mpt_prt(mpt, "doorbell req = %s",
1144 mpt_ioc_diag(mpt_read(mpt, MPT_OFFSET_DOORBELL)));
1145 }
1146
1147 /*
1148 * Start by making sure we're not at FAULT or RESET state
1149 */
1150 if (mpt_hw_init(mpt) != 0)
1151 return (EIO);
1152
1153 dict = device_properties(mpt->sc_dev);
1154
1155 for (try = 0; try < MPT_MAX_TRYS; try++) {
1156 /*
1157 * No need to reset if the IOC is already in the READY state.
1158 */
1159
1160 if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) {
1161 mpt_prt(mpt, "mpt_get_iocfacts failed");
1162 continue;
1163 }
1164 mpt2host_iocfacts_reply(&facts);
1165
1166 if (mpt->verbose > 1) {
1167 mpt_prt(mpt,
1168 "IOCFACTS: GlobalCredits=%d BlockSize=%u "
1169 "Request Frame Size %u", facts.GlobalCredits,
1170 facts.BlockSize, facts.RequestFrameSize);
1171 }
1172 mpt->mpt_max_devices = facts.MaxDevices;
1173 mpt->mpt_global_credits = facts.GlobalCredits;
1174 mpt->request_frame_size = facts.RequestFrameSize;
1175
1176 if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) {
1177 mpt_prt(mpt, "mpt_get_portfacts failed");
1178 continue;
1179 }
1180 mpt2host_portfacts_reply(&pfp);
1181
1182 if (mpt->verbose > 1) {
1183 mpt_prt(mpt,
1184 "PORTFACTS: Type %x PFlags %x IID %d MaxDev %d",
1185 pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID,
1186 pfp.MaxDevices);
1187 }
1188
1189 if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
1190 mpt_prt(mpt, "initiator role unsupported");
1191 return (ENXIO);
1192 }
1193
1194 switch (pfp.PortType) {
1195 case MPI_PORTFACTS_PORTTYPE_FC:
1196 mpt->is_fc = 1;
1197 mpt->mpt_max_devices = 255;
1198 break;
1199 case MPI_PORTFACTS_PORTTYPE_SCSI:
1200 mpt->is_scsi = 1;
1201 /* some SPI controllers (VMWare, Sun) lie */
1202 mpt->mpt_max_devices = 16;
1203 break;
1204 case MPI_PORTFACTS_PORTTYPE_SAS:
1205 mpt->is_sas = 1;
1206 break;
1207 default:
1208 mpt_prt(mpt, "Unsupported Port Type (%x)",
1209 pfp.PortType);
1210 return (ENXIO);
1211 }
1212
1213 if (!mpt->is_sas && !mpt->is_fc &&
1214 prop_dictionary_get_uint32(dict, "scsi-initiator-id", &ini_id))
1215 mpt->mpt_ini_id = ini_id;
1216 else
1217 mpt->mpt_ini_id = pfp.PortSCSIID;
1218
1219 if (mpt_send_ioc_init(mpt, who) != MPT_OK) {
1220 mpt_prt(mpt, "mpt_send_ioc_init failed");
1221 continue;
1222 }
1223
1224 if (mpt->verbose > 1) {
1225 mpt_prt(mpt, "mpt_send_ioc_init ok");
1226 }
1227
1228 if (mpt_wait_state(mpt, MPT_DB_STATE_RUNNING) != MPT_OK) {
1229 mpt_prt(mpt, "IOC failed to go to run state");
1230 continue;
1231 }
1232 if (mpt->verbose > 1) {
1233 mpt_prt(mpt, "IOC now at RUNSTATE");
1234 }
1235
1236 /*
1237 * Give it reply buffers
1238 *
1239 * Do *not* except global credits.
1240 */
1241 for (val = 0, pptr = mpt->reply_phys;
1242 (pptr + MPT_REPLY_SIZE) < (mpt->reply_phys + PAGE_SIZE);
1243 pptr += MPT_REPLY_SIZE) {
1244 mpt_free_reply(mpt, pptr);
1245 if (++val == mpt->mpt_global_credits - 1)
1246 break;
1247 }
1248
1249 /*
1250 * Enable asynchronous event reporting
1251 */
1252 mpt_send_event_request(mpt, 1);
1253
1254
1255 /*
1256 * Read set up initial configuration information
1257 * (SPI only for now)
1258 */
1259
1260 if (mpt->is_scsi) {
1261 if (mpt_read_config_info_spi(mpt)) {
1262 return (EIO);
1263 }
1264 if (mpt_set_initial_config_spi(mpt)) {
1265 return (EIO);
1266 }
1267 }
1268
1269 /*
1270 * Now enable the port
1271 */
1272 if (mpt_send_port_enable(mpt, 0) != MPT_OK) {
1273 mpt_prt(mpt, "failed to enable port 0");
1274 continue;
1275 }
1276
1277 if (mpt->verbose > 1) {
1278 mpt_prt(mpt, "enabled port 0");
1279 }
1280
1281 /* Everything worked */
1282 break;
1283 }
1284
1285 if (try >= MPT_MAX_TRYS) {
1286 mpt_prt(mpt, "failed to initialize IOC");
1287 return (EIO);
1288 }
1289
1290 if (mpt->verbose > 1) {
1291 mpt_prt(mpt, "enabling interrupts");
1292 }
1293
1294 mpt_enable_ints(mpt);
1295 return (0);
1296 }
1297
1298 /*
1299 * Endian Conversion Functions- only used on Big Endian machines
1300 */
1301 #if _BYTE_ORDER == _BIG_ENDIAN
1302 void
mpt2host_sge_simple_union(SGE_SIMPLE_UNION * sge)1303 mpt2host_sge_simple_union(SGE_SIMPLE_UNION *sge)
1304 {
1305
1306 MPT_2_HOST32(sge, FlagsLength);
1307 MPT_2_HOST32(sge, _u.Address64.Low);
1308 MPT_2_HOST32(sge, _u.Address64.High);
1309 }
1310
1311 void
mpt2host_iocfacts_reply(MSG_IOC_FACTS_REPLY * rp)1312 mpt2host_iocfacts_reply(MSG_IOC_FACTS_REPLY *rp)
1313 {
1314
1315 MPT_2_HOST16(rp, MsgVersion);
1316 #if 0
1317 MPT_2_HOST16(rp, HeaderVersion);
1318 #endif
1319 MPT_2_HOST32(rp, MsgContext);
1320 MPT_2_HOST16(rp, IOCExceptions);
1321 MPT_2_HOST16(rp, IOCStatus);
1322 MPT_2_HOST32(rp, IOCLogInfo);
1323 MPT_2_HOST16(rp, ReplyQueueDepth);
1324 MPT_2_HOST16(rp, RequestFrameSize);
1325 MPT_2_HOST16(rp, Reserved_0101_FWVersion);
1326 MPT_2_HOST16(rp, ProductID);
1327 MPT_2_HOST32(rp, CurrentHostMfaHighAddr);
1328 MPT_2_HOST16(rp, GlobalCredits);
1329 MPT_2_HOST32(rp, CurrentSenseBufferHighAddr);
1330 MPT_2_HOST16(rp, CurReplyFrameSize);
1331 MPT_2_HOST32(rp, FWImageSize);
1332 #if 0
1333 MPT_2_HOST32(rp, IOCCapabilities);
1334 #endif
1335 MPT_2_HOST32(rp, FWVersion.Word);
1336 #if 0
1337 MPT_2_HOST16(rp, HighPriorityQueueDepth);
1338 MPT_2_HOST16(rp, Reserved2);
1339 mpt2host_sge_simple_union(&rp->HostPageBufferSGE);
1340 MPT_2_HOST32(rp, ReplyFifoHostSignalingAddr);
1341 #endif
1342 }
1343
1344 void
mpt2host_portfacts_reply(MSG_PORT_FACTS_REPLY * pfp)1345 mpt2host_portfacts_reply(MSG_PORT_FACTS_REPLY *pfp)
1346 {
1347
1348 MPT_2_HOST16(pfp, Reserved);
1349 MPT_2_HOST16(pfp, Reserved1);
1350 MPT_2_HOST32(pfp, MsgContext);
1351 MPT_2_HOST16(pfp, Reserved2);
1352 MPT_2_HOST16(pfp, IOCStatus);
1353 MPT_2_HOST32(pfp, IOCLogInfo);
1354 MPT_2_HOST16(pfp, MaxDevices);
1355 MPT_2_HOST16(pfp, PortSCSIID);
1356 MPT_2_HOST16(pfp, ProtocolFlags);
1357 MPT_2_HOST16(pfp, MaxPostedCmdBuffers);
1358 MPT_2_HOST16(pfp, MaxPersistentIDs);
1359 MPT_2_HOST16(pfp, MaxLanBuckets);
1360 MPT_2_HOST16(pfp, Reserved4);
1361 MPT_2_HOST32(pfp, Reserved5);
1362 }
1363
1364 void
mpt2host_config_page_scsi_port_0(fCONFIG_PAGE_SCSI_PORT_0 * sp0)1365 mpt2host_config_page_scsi_port_0(fCONFIG_PAGE_SCSI_PORT_0 *sp0)
1366 {
1367
1368 MPT_2_HOST32(sp0, Capabilities);
1369 MPT_2_HOST32(sp0, PhysicalInterface);
1370 }
1371
1372 void
mpt2host_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 * sp1)1373 mpt2host_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 *sp1)
1374 {
1375
1376 MPT_2_HOST32(sp1, Configuration);
1377 MPT_2_HOST32(sp1, OnBusTimerValue);
1378 #if 0
1379 MPT_2_HOST16(sp1, IDConfig);
1380 #endif
1381 }
1382
1383 void
host2mpt_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 * sp1)1384 host2mpt_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 *sp1)
1385 {
1386
1387 HOST_2_MPT32(sp1, Configuration);
1388 HOST_2_MPT32(sp1, OnBusTimerValue);
1389 #if 0
1390 HOST_2_MPT16(sp1, IDConfig);
1391 #endif
1392 }
1393
1394 void
mpt2host_config_page_scsi_port_2(fCONFIG_PAGE_SCSI_PORT_2 * sp2)1395 mpt2host_config_page_scsi_port_2(fCONFIG_PAGE_SCSI_PORT_2 *sp2)
1396 {
1397 int i;
1398
1399 MPT_2_HOST32(sp2, PortFlags);
1400 MPT_2_HOST32(sp2, PortSettings);
1401 for (i = 0; i < sizeof(sp2->DeviceSettings) /
1402 sizeof(*sp2->DeviceSettings); i++) {
1403 MPT_2_HOST16(sp2, DeviceSettings[i].DeviceFlags);
1404 }
1405 }
1406
1407 void
mpt2host_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 * sd0)1408 mpt2host_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 *sd0)
1409 {
1410
1411 MPT_2_HOST32(sd0, NegotiatedParameters);
1412 MPT_2_HOST32(sd0, Information);
1413 }
1414
1415 void
host2mpt_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 * sd0)1416 host2mpt_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 *sd0)
1417 {
1418
1419 HOST_2_MPT32(sd0, NegotiatedParameters);
1420 HOST_2_MPT32(sd0, Information);
1421 }
1422
1423 void
mpt2host_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 * sd1)1424 mpt2host_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 *sd1)
1425 {
1426
1427 MPT_2_HOST32(sd1, RequestedParameters);
1428 MPT_2_HOST32(sd1, Reserved);
1429 MPT_2_HOST32(sd1, Configuration);
1430 }
1431
1432 void
host2mpt_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 * sd1)1433 host2mpt_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 *sd1)
1434 {
1435
1436 HOST_2_MPT32(sd1, RequestedParameters);
1437 HOST_2_MPT32(sd1, Reserved);
1438 HOST_2_MPT32(sd1, Configuration);
1439 }
1440
1441 void
mpt2host_config_page_fc_port_0(fCONFIG_PAGE_FC_PORT_0 * fp0)1442 mpt2host_config_page_fc_port_0(fCONFIG_PAGE_FC_PORT_0 *fp0)
1443 {
1444
1445 MPT_2_HOST32(fp0, Flags);
1446 MPT_2_HOST32(fp0, PortIdentifier);
1447 MPT_2_HOST32(fp0, WWNN.Low);
1448 MPT_2_HOST32(fp0, WWNN.High);
1449 MPT_2_HOST32(fp0, WWPN.Low);
1450 MPT_2_HOST32(fp0, WWPN.High);
1451 MPT_2_HOST32(fp0, SupportedServiceClass);
1452 MPT_2_HOST32(fp0, SupportedSpeeds);
1453 MPT_2_HOST32(fp0, CurrentSpeed);
1454 MPT_2_HOST32(fp0, MaxFrameSize);
1455 MPT_2_HOST32(fp0, FabricWWNN.Low);
1456 MPT_2_HOST32(fp0, FabricWWNN.High);
1457 MPT_2_HOST32(fp0, FabricWWPN.Low);
1458 MPT_2_HOST32(fp0, FabricWWPN.High);
1459 MPT_2_HOST32(fp0, DiscoveredPortsCount);
1460 MPT_2_HOST32(fp0, MaxInitiators);
1461 }
1462
1463 void
mpt2host_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 * fp1)1464 mpt2host_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *fp1)
1465 {
1466
1467 MPT_2_HOST32(fp1, Flags);
1468 MPT_2_HOST32(fp1, NoSEEPROMWWNN.Low);
1469 MPT_2_HOST32(fp1, NoSEEPROMWWNN.High);
1470 MPT_2_HOST32(fp1, NoSEEPROMWWPN.Low);
1471 MPT_2_HOST32(fp1, NoSEEPROMWWPN.High);
1472 }
1473
1474 void
host2mpt_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 * fp1)1475 host2mpt_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *fp1)
1476 {
1477
1478 HOST_2_MPT32(fp1, Flags);
1479 HOST_2_MPT32(fp1, NoSEEPROMWWNN.Low);
1480 HOST_2_MPT32(fp1, NoSEEPROMWWNN.High);
1481 HOST_2_MPT32(fp1, NoSEEPROMWWPN.Low);
1482 HOST_2_MPT32(fp1, NoSEEPROMWWPN.High);
1483 }
1484
1485 void
mpt2host_config_page_raid_vol_0(fCONFIG_PAGE_RAID_VOL_0 * volp)1486 mpt2host_config_page_raid_vol_0(fCONFIG_PAGE_RAID_VOL_0 *volp)
1487 {
1488 int i;
1489
1490 MPT_2_HOST16(volp, VolumeStatus.Reserved);
1491 MPT_2_HOST16(volp, VolumeSettings.Settings);
1492 MPT_2_HOST32(volp, MaxLBA);
1493 #if 0
1494 MPT_2_HOST32(volp, MaxLBAHigh);
1495 #endif
1496 MPT_2_HOST32(volp, StripeSize);
1497 MPT_2_HOST32(volp, Reserved2);
1498 MPT_2_HOST32(volp, Reserved3);
1499 for (i = 0; i < MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX; i++) {
1500 MPT_2_HOST16(volp, PhysDisk[i].Reserved);
1501 }
1502 }
1503
1504 void
mpt2host_config_page_raid_phys_disk_0(fCONFIG_PAGE_RAID_PHYS_DISK_0 * rpd0)1505 mpt2host_config_page_raid_phys_disk_0(fCONFIG_PAGE_RAID_PHYS_DISK_0 *rpd0)
1506 {
1507
1508 MPT_2_HOST32(rpd0, Reserved1);
1509 MPT_2_HOST16(rpd0, PhysDiskStatus.Reserved);
1510 MPT_2_HOST32(rpd0, MaxLBA);
1511 MPT_2_HOST16(rpd0, ErrorData.Reserved);
1512 MPT_2_HOST16(rpd0, ErrorData.ErrorCount);
1513 MPT_2_HOST16(rpd0, ErrorData.SmartCount);
1514 }
1515
1516 void
mpt2host_config_page_ioc_2(fCONFIG_PAGE_IOC_2 * ioc2)1517 mpt2host_config_page_ioc_2(fCONFIG_PAGE_IOC_2 *ioc2)
1518 {
1519 MPT_2_HOST32(ioc2, CapabilitiesFlags);
1520 }
1521
1522 #endif
1523