FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/mpt.c
1 /* $NetBSD: mpt.c,v 1.10.42.1 2010/12/02 23:45:59 snj 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.10.42.1 2010/12/02 23:45:59 snj 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
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
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
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
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
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
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
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
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
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
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 *
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
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 (0x%x):",
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
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
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
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
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 0x%02x",
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
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 bzero(&f_req, 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
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 bzero(&f_req, 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
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 bzero(&init, 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 static int
569 mpt_read_cfg_header(mpt_softc_t *, int, int, int, fCONFIG_PAGE_HEADER *);
570
571 static int
572 mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber,
573 int PageAddress, fCONFIG_PAGE_HEADER *rslt)
574 {
575 int count;
576 request_t *req;
577 MSG_CONFIG *cfgp;
578 MSG_CONFIG_REPLY *reply;
579
580 req = mpt_get_request(mpt);
581
582 cfgp = req->req_vbuf;
583 bzero(cfgp, sizeof *cfgp);
584
585 cfgp->Action = MPI_CONFIG_ACTION_PAGE_HEADER;
586 cfgp->Function = MPI_FUNCTION_CONFIG;
587 cfgp->Header.PageNumber = (U8) PageNumber;
588 cfgp->Header.PageType = (U8) PageType;
589 cfgp->PageAddress = htole32(PageAddress);
590 MPI_pSGE_SET_FLAGS(((SGE_SIMPLE32 *) &cfgp->PageBufferSGE),
591 (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
592 MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
593 cfgp->MsgContext = htole32(req->index | 0x80000000);
594
595 mpt_check_doorbell(mpt);
596 mpt_send_cmd(mpt, req);
597 count = 0;
598 do {
599 DELAY(500);
600 mpt_intr(mpt);
601 if (++count == 1000) {
602 mpt_prt(mpt, "read_cfg_header timed out");
603 return (-1);
604 }
605 } while (req->debug == REQ_ON_CHIP);
606
607 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
608 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
609 mpt_prt(mpt, "mpt_read_cfg_header: Config Info Status %x",
610 reply->IOCStatus);
611 mpt_free_reply(mpt, (req->sequence << 1));
612 return (-1);
613 }
614 bcopy(&reply->Header, rslt, sizeof (fCONFIG_PAGE_HEADER));
615 mpt_free_reply(mpt, (req->sequence << 1));
616 mpt_free_request(mpt, req);
617 return (0);
618 }
619
620 #define CFG_DATA_OFF 128
621
622 int
623 mpt_read_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
624 {
625 int count;
626 request_t *req;
627 SGE_SIMPLE32 *se;
628 MSG_CONFIG *cfgp;
629 size_t amt;
630 MSG_CONFIG_REPLY *reply;
631
632 req = mpt_get_request(mpt);
633
634 cfgp = req->req_vbuf;
635 bzero(cfgp, MPT_REQUEST_AREA);
636 cfgp->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
637 cfgp->Function = MPI_FUNCTION_CONFIG;
638 cfgp->Header = *hdr;
639 amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
640 cfgp->Header.PageType &= MPI_CONFIG_PAGETYPE_MASK;
641 cfgp->PageAddress = htole32(PageAddress);
642 se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
643 se->Address = htole32(req->req_pbuf + CFG_DATA_OFF);
644 MPI_pSGE_SET_LENGTH(se, amt);
645 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
646 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
647 MPI_SGE_FLAGS_END_OF_LIST));
648 se->FlagsLength = htole32(se->FlagsLength);
649
650 cfgp->MsgContext = htole32(req->index | 0x80000000);
651
652 mpt_check_doorbell(mpt);
653 mpt_send_cmd(mpt, req);
654 count = 0;
655 do {
656 DELAY(500);
657 mpt_intr(mpt);
658 if (++count == 1000) {
659 mpt_prt(mpt, "read_cfg_page timed out");
660 return (-1);
661 }
662 } while (req->debug == REQ_ON_CHIP);
663
664 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
665 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
666 mpt_prt(mpt, "mpt_read_cfg_page: Config Info Status %x",
667 reply->IOCStatus);
668 mpt_free_reply(mpt, (req->sequence << 1));
669 return (-1);
670 }
671 mpt_free_reply(mpt, (req->sequence << 1));
672 #if 0 /* XXXJRT */
673 bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap,
674 BUS_DMASYNC_POSTREAD);
675 #endif
676 if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
677 cfgp->Header.PageNumber == 0) {
678 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
679 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
680 cfgp->Header.PageNumber == 1) {
681 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
682 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
683 cfgp->Header.PageNumber == 2) {
684 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
685 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
686 cfgp->Header.PageNumber == 0) {
687 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
688 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
689 cfgp->Header.PageNumber == 1) {
690 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
691 }
692 memcpy(hdr, (char *)req->req_vbuf + CFG_DATA_OFF, amt);
693 mpt_free_request(mpt, req);
694 return (0);
695 }
696
697 int
698 mpt_write_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
699 {
700 int count, hdr_attr;
701 request_t *req;
702 SGE_SIMPLE32 *se;
703 MSG_CONFIG *cfgp;
704 size_t amt;
705 MSG_CONFIG_REPLY *reply;
706
707 req = mpt_get_request(mpt);
708
709 cfgp = req->req_vbuf;
710 bzero(cfgp, sizeof *cfgp);
711
712 hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK;
713 if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE &&
714 hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) {
715 mpt_prt(mpt, "page type 0x%x not changeable",
716 hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
717 return (-1);
718 }
719 hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK;
720
721 cfgp->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
722 cfgp->Function = MPI_FUNCTION_CONFIG;
723 cfgp->Header = *hdr;
724 amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
725 cfgp->PageAddress = htole32(PageAddress);
726
727 se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
728 se->Address = htole32(req->req_pbuf + CFG_DATA_OFF);
729 MPI_pSGE_SET_LENGTH(se, amt);
730 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
731 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
732 MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_HOST_TO_IOC));
733 se->FlagsLength = htole32(se->FlagsLength);
734
735 cfgp->MsgContext = htole32(req->index | 0x80000000);
736
737 if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
738 cfgp->Header.PageNumber == 0) {
739 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
740 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
741 cfgp->Header.PageNumber == 1) {
742 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
743 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
744 cfgp->Header.PageNumber == 2) {
745 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
746 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
747 cfgp->Header.PageNumber == 0) {
748 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
749 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
750 cfgp->Header.PageNumber == 1) {
751 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
752 }
753 memcpy((char *)req->req_vbuf + CFG_DATA_OFF, hdr, amt);
754 /* Restore stripped out attributes */
755 hdr->PageType |= hdr_attr;
756
757 mpt_check_doorbell(mpt);
758 mpt_send_cmd(mpt, req);
759 count = 0;
760 do {
761 DELAY(500);
762 mpt_intr(mpt);
763 if (++count == 1000) {
764 hdr->PageType |= hdr_attr;
765 mpt_prt(mpt, "mpt_write_cfg_page timed out");
766 return (-1);
767 }
768 } while (req->debug == REQ_ON_CHIP);
769
770 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
771 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
772 mpt_prt(mpt, "mpt_write_cfg_page: Config Info Status %x",
773 le16toh(reply->IOCStatus));
774 mpt_free_reply(mpt, (req->sequence << 1));
775 return (-1);
776 }
777 mpt_free_reply(mpt, (req->sequence << 1));
778
779 mpt_free_request(mpt, req);
780 return (0);
781 }
782
783 /*
784 * Read SCSI configuration information
785 */
786 static int
787 mpt_read_config_info_spi(mpt_softc_t *mpt)
788 {
789 int rv, i;
790
791 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0,
792 0, &mpt->mpt_port_page0.Header);
793 if (rv) {
794 return (-1);
795 }
796 if (mpt->verbose > 1) {
797 mpt_prt(mpt, "SPI Port Page 0 Header: %x %x %x %x",
798 mpt->mpt_port_page0.Header.PageVersion,
799 mpt->mpt_port_page0.Header.PageLength,
800 mpt->mpt_port_page0.Header.PageNumber,
801 mpt->mpt_port_page0.Header.PageType);
802 }
803
804 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1,
805 0, &mpt->mpt_port_page1.Header);
806 if (rv) {
807 return (-1);
808 }
809 if (mpt->verbose > 1) {
810 mpt_prt(mpt, "SPI Port Page 1 Header: %x %x %x %x",
811 mpt->mpt_port_page1.Header.PageVersion,
812 mpt->mpt_port_page1.Header.PageLength,
813 mpt->mpt_port_page1.Header.PageNumber,
814 mpt->mpt_port_page1.Header.PageType);
815 }
816
817 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2,
818 0, &mpt->mpt_port_page2.Header);
819 if (rv) {
820 return (-1);
821 }
822
823 if (mpt->verbose > 1) {
824 mpt_prt(mpt, "SPI Port Page 2 Header: %x %x %x %x",
825 mpt->mpt_port_page1.Header.PageVersion,
826 mpt->mpt_port_page1.Header.PageLength,
827 mpt->mpt_port_page1.Header.PageNumber,
828 mpt->mpt_port_page1.Header.PageType);
829 }
830
831 for (i = 0; i < 16; i++) {
832 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
833 0, i, &mpt->mpt_dev_page0[i].Header);
834 if (rv) {
835 return (-1);
836 }
837 if (mpt->verbose > 1) {
838 mpt_prt(mpt,
839 "SPI Target %d Device Page 0 Header: %x %x %x %x",
840 i, mpt->mpt_dev_page0[i].Header.PageVersion,
841 mpt->mpt_dev_page0[i].Header.PageLength,
842 mpt->mpt_dev_page0[i].Header.PageNumber,
843 mpt->mpt_dev_page0[i].Header.PageType);
844 }
845
846 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
847 1, i, &mpt->mpt_dev_page1[i].Header);
848 if (rv) {
849 return (-1);
850 }
851 if (mpt->verbose > 1) {
852 mpt_prt(mpt,
853 "SPI Target %d Device Page 1 Header: %x %x %x %x",
854 i, mpt->mpt_dev_page1[i].Header.PageVersion,
855 mpt->mpt_dev_page1[i].Header.PageLength,
856 mpt->mpt_dev_page1[i].Header.PageNumber,
857 mpt->mpt_dev_page1[i].Header.PageType);
858 }
859 }
860
861 /*
862 * At this point, we don't *have* to fail. As long as we have
863 * valid config header information, we can (barely) lurch
864 * along.
865 */
866
867 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page0.Header);
868 mpt2host_config_page_scsi_port_0(&mpt->mpt_port_page0);
869 if (rv) {
870 mpt_prt(mpt, "failed to read SPI Port Page 0");
871 } else if (mpt->verbose > 1) {
872 mpt_prt(mpt,
873 "SPI Port Page 0: Capabilities %x PhysicalInterface %x",
874 mpt->mpt_port_page0.Capabilities,
875 mpt->mpt_port_page0.PhysicalInterface);
876 }
877
878 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header);
879 mpt2host_config_page_scsi_port_1(&mpt->mpt_port_page1);
880 if (rv) {
881 mpt_prt(mpt, "failed to read SPI Port Page 1");
882 } else if (mpt->verbose > 1) {
883 mpt_prt(mpt,
884 "SPI Port Page 1: Configuration %x OnBusTimerValue %x",
885 mpt->mpt_port_page1.Configuration,
886 mpt->mpt_port_page1.OnBusTimerValue);
887 }
888
889 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header);
890 mpt2host_config_page_scsi_port_2(&mpt->mpt_port_page2);
891 if (rv) {
892 mpt_prt(mpt, "failed to read SPI Port Page 2");
893 } else if (mpt->verbose > 1) {
894 mpt_prt(mpt,
895 "SPI Port Page 2: Flags %x Settings %x",
896 mpt->mpt_port_page2.PortFlags,
897 mpt->mpt_port_page2.PortSettings);
898 for (i = 0; i < 1; i++) {
899 mpt_prt(mpt,
900 "SPI Port Page 2 Tgt %d: timo %x SF %x Flags %x",
901 i, mpt->mpt_port_page2.DeviceSettings[i].Timeout,
902 mpt->mpt_port_page2.DeviceSettings[i].SyncFactor,
903 mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags);
904 }
905 }
906
907 for (i = 0; i < 16; i++) {
908 rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page0[i].Header);
909 mpt2host_config_page_scsi_device_0(&mpt->mpt_dev_page0[i]);
910 if (rv) {
911 mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 0", i);
912 continue;
913 }
914 if (mpt->verbose > 1) {
915 mpt_prt(mpt,
916 "SPI Tgt %d Page 0: NParms %x Information %x",
917 i, mpt->mpt_dev_page0[i].NegotiatedParameters,
918 mpt->mpt_dev_page0[i].Information);
919 }
920 rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page1[i].Header);
921 mpt2host_config_page_scsi_device_1(&mpt->mpt_dev_page1[i]);
922 if (rv) {
923 mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 1", i);
924 continue;
925 }
926 if (mpt->verbose > 1) {
927 mpt_prt(mpt,
928 "SPI Tgt %d Page 1: RParms %x Configuration %x",
929 i, mpt->mpt_dev_page1[i].RequestedParameters,
930 mpt->mpt_dev_page1[i].Configuration);
931 }
932 }
933 return (0);
934 }
935
936 /*
937 * Validate SPI configuration information.
938 *
939 * In particular, validate SPI Port Page 1.
940 */
941 static int
942 mpt_set_initial_config_spi(mpt_softc_t *mpt)
943 {
944 int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id;
945
946 mpt->mpt_disc_enable = 0xff;
947 mpt->mpt_tag_enable = 0;
948
949 if (mpt->mpt_port_page1.Configuration != pp1val) {
950 fCONFIG_PAGE_SCSI_PORT_1 tmp;
951
952 mpt_prt(mpt,
953 "SPI Port Page 1 Config value bad (%x)- should be %x",
954 mpt->mpt_port_page1.Configuration, pp1val);
955 tmp = mpt->mpt_port_page1;
956 tmp.Configuration = pp1val;
957 host2mpt_config_page_scsi_port_1(&tmp);
958 if (mpt_write_cfg_page(mpt, 0, &tmp.Header)) {
959 return (-1);
960 }
961 if (mpt_read_cfg_page(mpt, 0, &tmp.Header)) {
962 return (-1);
963 }
964 mpt2host_config_page_scsi_port_1(&tmp);
965 if (tmp.Configuration != pp1val) {
966 mpt_prt(mpt,
967 "failed to reset SPI Port Page 1 Config value");
968 return (-1);
969 }
970 mpt->mpt_port_page1 = tmp;
971 }
972
973 i = 0;
974 for (i = 0; i < 16; i++) {
975 fCONFIG_PAGE_SCSI_DEVICE_1 tmp;
976
977 tmp = mpt->mpt_dev_page1[i];
978 tmp.RequestedParameters = 0;
979 tmp.Configuration = 0;
980 if (mpt->verbose > 1) {
981 mpt_prt(mpt,
982 "Set Tgt %d SPI DevicePage 1 values to %x 0 %x",
983 i, tmp.RequestedParameters, tmp.Configuration);
984 }
985 host2mpt_config_page_scsi_device_1(&tmp);
986 if (mpt_write_cfg_page(mpt, i, &tmp.Header)) {
987 return (-1);
988 }
989 if (mpt_read_cfg_page(mpt, i, &tmp.Header)) {
990 return (-1);
991 }
992 mpt2host_config_page_scsi_device_1(&tmp);
993 mpt->mpt_dev_page1[i] = tmp;
994 if (mpt->verbose > 1) {
995 mpt_prt(mpt,
996 "SPI Tgt %d Page 1: RParm %x Configuration %x", i,
997 mpt->mpt_dev_page1[i].RequestedParameters,
998 mpt->mpt_dev_page1[i].Configuration);
999 }
1000 }
1001 return (0);
1002 }
1003
1004 /*
1005 * Enable IOC port
1006 */
1007 static int
1008 mpt_send_port_enable(mpt_softc_t *mpt, int port)
1009 {
1010 int count;
1011 request_t *req;
1012 MSG_PORT_ENABLE *enable_req;
1013
1014 req = mpt_get_request(mpt);
1015
1016 enable_req = req->req_vbuf;
1017 bzero(enable_req, sizeof *enable_req);
1018
1019 enable_req->Function = MPI_FUNCTION_PORT_ENABLE;
1020 enable_req->MsgContext = htole32(req->index | 0x80000000);
1021 enable_req->PortNumber = port;
1022
1023 mpt_check_doorbell(mpt);
1024 if (mpt->verbose > 1) {
1025 mpt_prt(mpt, "enabling port %d", port);
1026 }
1027 mpt_send_cmd(mpt, req);
1028
1029 count = 0;
1030 do {
1031 DELAY(500);
1032 mpt_intr(mpt);
1033 if (++count == 100000) {
1034 mpt_prt(mpt, "port enable timed out");
1035 return (-1);
1036 }
1037 } while (req->debug == REQ_ON_CHIP);
1038 mpt_free_request(mpt, req);
1039 return (0);
1040 }
1041
1042 /*
1043 * Enable/Disable asynchronous event reporting.
1044 *
1045 * NB: this is the first command we send via shared memory
1046 * instead of the handshake register.
1047 */
1048 static int
1049 mpt_send_event_request(mpt_softc_t *mpt, int onoff)
1050 {
1051 request_t *req;
1052 MSG_EVENT_NOTIFY *enable_req;
1053
1054 req = mpt_get_request(mpt);
1055
1056 enable_req = req->req_vbuf;
1057 bzero(enable_req, sizeof *enable_req);
1058
1059 enable_req->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
1060 enable_req->MsgContext = htole32(req->index | 0x80000000);
1061 enable_req->Switch = onoff;
1062
1063 mpt_check_doorbell(mpt);
1064 if (mpt->verbose > 1) {
1065 mpt_prt(mpt, "%sabling async events", onoff? "en" : "dis");
1066 }
1067 mpt_send_cmd(mpt, req);
1068
1069 return (0);
1070 }
1071
1072 /*
1073 * Un-mask the interrupts on the chip.
1074 */
1075 void
1076 mpt_enable_ints(mpt_softc_t *mpt)
1077 {
1078 /* Unmask every thing except door bell int */
1079 mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK);
1080 }
1081
1082 /*
1083 * Mask the interrupts on the chip.
1084 */
1085 void
1086 mpt_disable_ints(mpt_softc_t *mpt)
1087 {
1088 /* Mask all interrupts */
1089 mpt_write(mpt, MPT_OFFSET_INTR_MASK,
1090 MPT_INTR_REPLY_MASK | MPT_INTR_DB_MASK);
1091 }
1092
1093 /* (Re)Initialize the chip for use */
1094 int
1095 mpt_hw_init(mpt_softc_t *mpt)
1096 {
1097 u_int32_t db;
1098 int try;
1099
1100 /*
1101 * Start by making sure we're not at FAULT or RESET state
1102 */
1103 for (try = 0; try < MPT_MAX_TRYS; try++) {
1104
1105 db = mpt_rd_db(mpt);
1106
1107 switch (MPT_STATE(db)) {
1108 case MPT_DB_STATE_READY:
1109 return (0);
1110
1111 default:
1112 /* if peer has already reset us, don't do it again! */
1113 if (MPT_WHO(db) == MPT_DB_INIT_PCIPEER)
1114 return (0);
1115 /*FALLTHRU*/
1116 case MPT_DB_STATE_RESET:
1117 case MPT_DB_STATE_FAULT:
1118 if (mpt_reset(mpt) != MPT_OK) {
1119 DELAY(10000);
1120 continue;
1121 }
1122 break;
1123 }
1124 }
1125 return (EIO);
1126 }
1127
1128 int
1129 mpt_init(mpt_softc_t *mpt, u_int32_t who)
1130 {
1131 int try;
1132 MSG_IOC_FACTS_REPLY facts;
1133 MSG_PORT_FACTS_REPLY pfp;
1134 u_int32_t pptr;
1135 int val;
1136
1137 /* Put all request buffers (back) on the free list */
1138 SLIST_INIT(&mpt->request_free_list);
1139 for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
1140 mpt_free_request(mpt, &mpt->request_pool[val]);
1141 }
1142
1143 if (mpt->verbose > 1) {
1144 mpt_prt(mpt, "doorbell req = %s",
1145 mpt_ioc_diag(mpt_read(mpt, MPT_OFFSET_DOORBELL)));
1146 }
1147
1148 /*
1149 * Start by making sure we're not at FAULT or RESET state
1150 */
1151 if (mpt_hw_init(mpt) != 0)
1152 return (EIO);
1153
1154 for (try = 0; try < MPT_MAX_TRYS; try++) {
1155 /*
1156 * No need to reset if the IOC is already in the READY state.
1157 */
1158
1159 if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) {
1160 mpt_prt(mpt, "mpt_get_iocfacts failed");
1161 continue;
1162 }
1163 mpt2host_iocfacts_reply(&facts);
1164
1165 if (mpt->verbose > 1) {
1166 mpt_prt(mpt,
1167 "IOCFACTS: GlobalCredits=%d BlockSize=%u "
1168 "Request Frame Size %u", facts.GlobalCredits,
1169 facts.BlockSize, facts.RequestFrameSize);
1170 }
1171 mpt->mpt_max_devices = facts.MaxDevices;
1172 mpt->mpt_global_credits = facts.GlobalCredits;
1173 mpt->request_frame_size = facts.RequestFrameSize;
1174
1175 if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) {
1176 mpt_prt(mpt, "mpt_get_portfacts failed");
1177 continue;
1178 }
1179 mpt2host_portfacts_reply(&pfp);
1180
1181 if (mpt->verbose > 1) {
1182 mpt_prt(mpt,
1183 "PORTFACTS: Type %x PFlags %x IID %d MaxDev %d",
1184 pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID,
1185 pfp.MaxDevices);
1186 }
1187
1188 if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
1189 mpt_prt(mpt, "initiator role unsupported");
1190 return (ENXIO);
1191 }
1192
1193 switch (pfp.PortType) {
1194 case MPI_PORTFACTS_PORTTYPE_FC:
1195 mpt->is_fc = 1;
1196 mpt->mpt_max_devices = 255;
1197 break;
1198 case MPI_PORTFACTS_PORTTYPE_SCSI:
1199 mpt->is_scsi = 1;
1200 /* some SPI controllers (VMWare, Sun) lie */
1201 mpt->mpt_max_devices = 16;
1202 break;
1203 case MPI_PORTFACTS_PORTTYPE_SAS:
1204 mpt->is_sas = 1;
1205 break;
1206 default:
1207 mpt_prt(mpt, "Unsupported Port Type (%x)",
1208 pfp.PortType);
1209 return (ENXIO);
1210 }
1211
1212 mpt->mpt_ini_id = pfp.PortSCSIID;
1213
1214 if (mpt_send_ioc_init(mpt, who) != MPT_OK) {
1215 mpt_prt(mpt, "mpt_send_ioc_init failed");
1216 continue;
1217 }
1218
1219 if (mpt->verbose > 1) {
1220 mpt_prt(mpt, "mpt_send_ioc_init ok");
1221 }
1222
1223 if (mpt_wait_state(mpt, MPT_DB_STATE_RUNNING) != MPT_OK) {
1224 mpt_prt(mpt, "IOC failed to go to run state");
1225 continue;
1226 }
1227 if (mpt->verbose > 1) {
1228 mpt_prt(mpt, "IOC now at RUNSTATE");
1229 }
1230
1231 /*
1232 * Give it reply buffers
1233 *
1234 * Do *not* except global credits.
1235 */
1236 for (val = 0, pptr = mpt->reply_phys;
1237 (pptr + MPT_REPLY_SIZE) < (mpt->reply_phys + PAGE_SIZE);
1238 pptr += MPT_REPLY_SIZE) {
1239 mpt_free_reply(mpt, pptr);
1240 if (++val == mpt->mpt_global_credits - 1)
1241 break;
1242 }
1243
1244 /*
1245 * Enable asynchronous event reporting
1246 */
1247 mpt_send_event_request(mpt, 1);
1248
1249
1250 /*
1251 * Read set up initial configuration information
1252 * (SPI only for now)
1253 */
1254
1255 if (mpt->is_scsi) {
1256 if (mpt_read_config_info_spi(mpt)) {
1257 return (EIO);
1258 }
1259 if (mpt_set_initial_config_spi(mpt)) {
1260 return (EIO);
1261 }
1262 }
1263
1264 /*
1265 * Now enable the port
1266 */
1267 if (mpt_send_port_enable(mpt, 0) != MPT_OK) {
1268 mpt_prt(mpt, "failed to enable port 0");
1269 continue;
1270 }
1271
1272 if (mpt->verbose > 1) {
1273 mpt_prt(mpt, "enabled port 0");
1274 }
1275
1276 /* Everything worked */
1277 break;
1278 }
1279
1280 if (try >= MPT_MAX_TRYS) {
1281 mpt_prt(mpt, "failed to initialize IOC");
1282 return (EIO);
1283 }
1284
1285 if (mpt->verbose > 1) {
1286 mpt_prt(mpt, "enabling interrupts");
1287 }
1288
1289 mpt_enable_ints(mpt);
1290 return (0);
1291 }
1292
1293 /*
1294 * Endian Conversion Functions- only used on Big Endian machines
1295 */
1296 #if _BYTE_ORDER == _BIG_ENDIAN
1297 void
1298 mpt2host_sge_simple_union(SGE_SIMPLE_UNION *sge)
1299 {
1300
1301 MPT_2_HOST32(sge, FlagsLength);
1302 MPT_2_HOST32(sge, _u.Address64.Low);
1303 MPT_2_HOST32(sge, _u.Address64.High);
1304 }
1305
1306 void
1307 mpt2host_iocfacts_reply(MSG_IOC_FACTS_REPLY *rp)
1308 {
1309
1310 MPT_2_HOST16(rp, MsgVersion);
1311 #if 0
1312 MPT_2_HOST16(rp, HeaderVersion);
1313 #endif
1314 MPT_2_HOST32(rp, MsgContext);
1315 MPT_2_HOST16(rp, IOCExceptions);
1316 MPT_2_HOST16(rp, IOCStatus);
1317 MPT_2_HOST32(rp, IOCLogInfo);
1318 MPT_2_HOST16(rp, ReplyQueueDepth);
1319 MPT_2_HOST16(rp, RequestFrameSize);
1320 MPT_2_HOST16(rp, Reserved_0101_FWVersion);
1321 MPT_2_HOST16(rp, ProductID);
1322 MPT_2_HOST32(rp, CurrentHostMfaHighAddr);
1323 MPT_2_HOST16(rp, GlobalCredits);
1324 MPT_2_HOST32(rp, CurrentSenseBufferHighAddr);
1325 MPT_2_HOST16(rp, CurReplyFrameSize);
1326 MPT_2_HOST32(rp, FWImageSize);
1327 #if 0
1328 MPT_2_HOST32(rp, IOCCapabilities);
1329 #endif
1330 MPT_2_HOST32(rp, FWVersion.Word);
1331 #if 0
1332 MPT_2_HOST16(rp, HighPriorityQueueDepth);
1333 MPT_2_HOST16(rp, Reserved2);
1334 mpt2host_sge_simple_union(&rp->HostPageBufferSGE);
1335 MPT_2_HOST32(rp, ReplyFifoHostSignalingAddr);
1336 #endif
1337 }
1338
1339 void
1340 mpt2host_portfacts_reply(MSG_PORT_FACTS_REPLY *pfp)
1341 {
1342
1343 MPT_2_HOST16(pfp, Reserved);
1344 MPT_2_HOST16(pfp, Reserved1);
1345 MPT_2_HOST32(pfp, MsgContext);
1346 MPT_2_HOST16(pfp, Reserved2);
1347 MPT_2_HOST16(pfp, IOCStatus);
1348 MPT_2_HOST32(pfp, IOCLogInfo);
1349 MPT_2_HOST16(pfp, MaxDevices);
1350 MPT_2_HOST16(pfp, PortSCSIID);
1351 MPT_2_HOST16(pfp, ProtocolFlags);
1352 MPT_2_HOST16(pfp, MaxPostedCmdBuffers);
1353 MPT_2_HOST16(pfp, MaxPersistentIDs);
1354 MPT_2_HOST16(pfp, MaxLanBuckets);
1355 MPT_2_HOST16(pfp, Reserved4);
1356 MPT_2_HOST32(pfp, Reserved5);
1357 }
1358
1359 void
1360 mpt2host_config_page_scsi_port_0(fCONFIG_PAGE_SCSI_PORT_0 *sp0)
1361 {
1362
1363 MPT_2_HOST32(sp0, Capabilities);
1364 MPT_2_HOST32(sp0, PhysicalInterface);
1365 }
1366
1367 void
1368 mpt2host_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 *sp1)
1369 {
1370
1371 MPT_2_HOST32(sp1, Configuration);
1372 MPT_2_HOST32(sp1, OnBusTimerValue);
1373 #if 0
1374 MPT_2_HOST16(sp1, IDConfig);
1375 #endif
1376 }
1377
1378 void
1379 host2mpt_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 *sp1)
1380 {
1381
1382 HOST_2_MPT32(sp1, Configuration);
1383 HOST_2_MPT32(sp1, OnBusTimerValue);
1384 #if 0
1385 HOST_2_MPT16(sp1, IDConfig);
1386 #endif
1387 }
1388
1389 void
1390 mpt2host_config_page_scsi_port_2(fCONFIG_PAGE_SCSI_PORT_2 *sp2)
1391 {
1392 int i;
1393
1394 MPT_2_HOST32(sp2, PortFlags);
1395 MPT_2_HOST32(sp2, PortSettings);
1396 for (i = 0; i < sizeof(sp2->DeviceSettings) /
1397 sizeof(*sp2->DeviceSettings); i++) {
1398 MPT_2_HOST16(sp2, DeviceSettings[i].DeviceFlags);
1399 }
1400 }
1401
1402 void
1403 mpt2host_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 *sd0)
1404 {
1405
1406 MPT_2_HOST32(sd0, NegotiatedParameters);
1407 MPT_2_HOST32(sd0, Information);
1408 }
1409
1410 void
1411 host2mpt_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 *sd0)
1412 {
1413
1414 HOST_2_MPT32(sd0, NegotiatedParameters);
1415 HOST_2_MPT32(sd0, Information);
1416 }
1417
1418 void
1419 mpt2host_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 *sd1)
1420 {
1421
1422 MPT_2_HOST32(sd1, RequestedParameters);
1423 MPT_2_HOST32(sd1, Reserved);
1424 MPT_2_HOST32(sd1, Configuration);
1425 }
1426
1427 void
1428 host2mpt_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 *sd1)
1429 {
1430
1431 HOST_2_MPT32(sd1, RequestedParameters);
1432 HOST_2_MPT32(sd1, Reserved);
1433 HOST_2_MPT32(sd1, Configuration);
1434 }
1435
1436 void
1437 mpt2host_config_page_fc_port_0(fCONFIG_PAGE_FC_PORT_0 *fp0)
1438 {
1439
1440 MPT_2_HOST32(fp0, Flags);
1441 MPT_2_HOST32(fp0, PortIdentifier);
1442 MPT_2_HOST32(fp0, WWNN.Low);
1443 MPT_2_HOST32(fp0, WWNN.High);
1444 MPT_2_HOST32(fp0, WWPN.Low);
1445 MPT_2_HOST32(fp0, WWPN.High);
1446 MPT_2_HOST32(fp0, SupportedServiceClass);
1447 MPT_2_HOST32(fp0, SupportedSpeeds);
1448 MPT_2_HOST32(fp0, CurrentSpeed);
1449 MPT_2_HOST32(fp0, MaxFrameSize);
1450 MPT_2_HOST32(fp0, FabricWWNN.Low);
1451 MPT_2_HOST32(fp0, FabricWWNN.High);
1452 MPT_2_HOST32(fp0, FabricWWPN.Low);
1453 MPT_2_HOST32(fp0, FabricWWPN.High);
1454 MPT_2_HOST32(fp0, DiscoveredPortsCount);
1455 MPT_2_HOST32(fp0, MaxInitiators);
1456 }
1457
1458 void
1459 mpt2host_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *fp1)
1460 {
1461
1462 MPT_2_HOST32(fp1, Flags);
1463 MPT_2_HOST32(fp1, NoSEEPROMWWNN.Low);
1464 MPT_2_HOST32(fp1, NoSEEPROMWWNN.High);
1465 MPT_2_HOST32(fp1, NoSEEPROMWWPN.Low);
1466 MPT_2_HOST32(fp1, NoSEEPROMWWPN.High);
1467 }
1468
1469 void
1470 host2mpt_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *fp1)
1471 {
1472
1473 HOST_2_MPT32(fp1, Flags);
1474 HOST_2_MPT32(fp1, NoSEEPROMWWNN.Low);
1475 HOST_2_MPT32(fp1, NoSEEPROMWWNN.High);
1476 HOST_2_MPT32(fp1, NoSEEPROMWWPN.Low);
1477 HOST_2_MPT32(fp1, NoSEEPROMWWPN.High);
1478 }
1479
1480 void
1481 mpt2host_config_page_raid_vol_0(fCONFIG_PAGE_RAID_VOL_0 *volp)
1482 {
1483 int i;
1484
1485 MPT_2_HOST16(volp, VolumeStatus.Reserved);
1486 MPT_2_HOST16(volp, VolumeSettings.Settings);
1487 MPT_2_HOST32(volp, MaxLBA);
1488 #if 0
1489 MPT_2_HOST32(volp, MaxLBAHigh);
1490 #endif
1491 MPT_2_HOST32(volp, StripeSize);
1492 MPT_2_HOST32(volp, Reserved2);
1493 MPT_2_HOST32(volp, Reserved3);
1494 for (i = 0; i < MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX; i++) {
1495 MPT_2_HOST16(volp, PhysDisk[i].Reserved);
1496 }
1497 }
1498
1499 void
1500 mpt2host_config_page_raid_phys_disk_0(fCONFIG_PAGE_RAID_PHYS_DISK_0 *rpd0)
1501 {
1502
1503 MPT_2_HOST32(rpd0, Reserved1);
1504 MPT_2_HOST16(rpd0, PhysDiskStatus.Reserved);
1505 MPT_2_HOST32(rpd0, MaxLBA);
1506 MPT_2_HOST16(rpd0, ErrorData.Reserved);
1507 MPT_2_HOST16(rpd0, ErrorData.ErrorCount);
1508 MPT_2_HOST16(rpd0, ErrorData.SmartCount);
1509 }
1510
1511 #endif
Cache object: bda2951b98f2f1d82d3d8166f236a4ae
|