Sync usage with man page.
[netbsd-mini2440.git] / sys / dev / ic / mpt.c
blob17b64eb72684b2f1df3d118c7a22c91a15e93109
1 /* $NetBSD: mpt.c,v 1.12 2009/03/18 17:06:49 cegger Exp $ */
3 /*
4 * Copyright (c) 2000, 2001 by Greg Ansley
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.
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.
28 * Additional Copyright (c) 2002 by Matthew Jacob under same license.
33 * mpt.c:
35 * Generic routines for LSI Fusion adapters.
37 * Adapted from the FreeBSD "mpt" driver by Jason R. Thorpe for
38 * Wasabi Systems, Inc.
40 * Additional contributions by Garrett D'Amore on behalf of TELES AG.
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: mpt.c,v 1.12 2009/03/18 17:06:49 cegger Exp $");
46 #include <dev/ic/mpt.h>
48 #define MPT_MAX_TRYS 3
49 #define MPT_MAX_WAIT 300000
51 static int maxwait_ack = 0;
52 static int maxwait_int = 0;
53 static int maxwait_state = 0;
55 static inline u_int32_t
56 mpt_rd_db(mpt_softc_t *mpt)
58 return mpt_read(mpt, MPT_OFFSET_DOORBELL);
61 static inline u_int32_t
62 mpt_rd_intr(mpt_softc_t *mpt)
64 return mpt_read(mpt, MPT_OFFSET_INTR_STATUS);
67 /* Busy wait for a door bell to be read by IOC */
68 static int
69 mpt_wait_db_ack(mpt_softc_t *mpt)
71 int i;
72 for (i=0; i < MPT_MAX_WAIT; i++) {
73 if (!MPT_DB_IS_BUSY(mpt_rd_intr(mpt))) {
74 maxwait_ack = i > maxwait_ack ? i : maxwait_ack;
75 return MPT_OK;
78 DELAY(100);
80 return MPT_FAIL;
83 /* Busy wait for a door bell interrupt */
84 static int
85 mpt_wait_db_int(mpt_softc_t *mpt)
87 int i;
88 for (i=0; i < MPT_MAX_WAIT; i++) {
89 if (MPT_DB_INTR(mpt_rd_intr(mpt))) {
90 maxwait_int = i > maxwait_int ? i : maxwait_int;
91 return MPT_OK;
93 DELAY(100);
95 return MPT_FAIL;
98 /* Wait for IOC to transition to a give state */
99 void
100 mpt_check_doorbell(mpt_softc_t *mpt)
102 u_int32_t db = mpt_rd_db(mpt);
103 if (MPT_STATE(db) != MPT_DB_STATE_RUNNING) {
104 mpt_prt(mpt, "Device not running");
105 mpt_print_db(db);
109 /* Wait for IOC to transition to a give state */
110 static int
111 mpt_wait_state(mpt_softc_t *mpt, enum DB_STATE_BITS state)
113 int i;
115 for (i = 0; i < MPT_MAX_WAIT; i++) {
116 u_int32_t db = mpt_rd_db(mpt);
117 if (MPT_STATE(db) == state) {
118 maxwait_state = i > maxwait_state ? i : maxwait_state;
119 return (MPT_OK);
121 DELAY(100);
123 return (MPT_FAIL);
127 /* Issue the reset COMMAND to the IOC */
129 mpt_soft_reset(mpt_softc_t *mpt)
131 if (mpt->verbose) {
132 mpt_prt(mpt, "soft reset");
135 /* Have to use hard reset if we are not in Running state */
136 if (MPT_STATE(mpt_rd_db(mpt)) != MPT_DB_STATE_RUNNING) {
137 mpt_prt(mpt, "soft reset failed: device not running");
138 return MPT_FAIL;
141 /* If door bell is in use we don't have a chance of getting
142 * a word in since the IOC probably crashed in message
143 * processing. So don't waste our time.
145 if (MPT_DB_IS_IN_USE(mpt_rd_db(mpt))) {
146 mpt_prt(mpt, "soft reset failed: doorbell wedged");
147 return MPT_FAIL;
150 /* Send the reset request to the IOC */
151 mpt_write(mpt, MPT_OFFSET_DOORBELL,
152 MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET << MPI_DOORBELL_FUNCTION_SHIFT);
153 if (mpt_wait_db_ack(mpt) != MPT_OK) {
154 mpt_prt(mpt, "soft reset failed: ack timeout");
155 return MPT_FAIL;
158 /* Wait for the IOC to reload and come out of reset state */
159 if (mpt_wait_state(mpt, MPT_DB_STATE_READY) != MPT_OK) {
160 mpt_prt(mpt, "soft reset failed: device did not start running");
161 return MPT_FAIL;
164 return MPT_OK;
167 /* This is a magic diagnostic reset that resets all the ARM
168 * processors in the chip.
170 void
171 mpt_hard_reset(mpt_softc_t *mpt)
173 if (mpt->verbose) {
174 mpt_prt(mpt, "hard reset");
176 mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xff);
178 /* Enable diagnostic registers */
179 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_1);
180 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_2);
181 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_3);
182 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_4);
183 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_5);
185 /* Diag. port is now active so we can now hit the reset bit */
186 mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, MPT_DIAG_RESET_IOC);
188 DELAY(10000);
190 /* Disable Diagnostic Register */
191 mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFF);
195 * Reset the IOC when needed. Try software command first then if needed
196 * poke at the magic diagnostic reset. Note that a hard reset resets
197 * *both* IOCs on dual function chips (FC929 && LSI1030) as well as
198 * fouls up the PCI configuration registers.
201 mpt_reset(mpt_softc_t *mpt)
203 int ret;
205 /* Try a soft reset */
206 if ((ret = mpt_soft_reset(mpt)) != MPT_OK) {
207 /* Failed; do a hard reset */
208 mpt_hard_reset(mpt);
210 /* Wait for the IOC to reload and come out of reset state */
211 ret = mpt_wait_state(mpt, MPT_DB_STATE_READY);
212 if (ret != MPT_OK) {
213 mpt_prt(mpt, "failed to reset device");
217 return ret;
220 /* Return a command buffer to the free queue */
221 void
222 mpt_free_request(mpt_softc_t *mpt, request_t *req)
224 if (req == NULL || req != &mpt->request_pool[req->index]) {
225 panic("mpt_free_request bad req ptr\n");
226 return;
228 req->sequence = 0;
229 req->xfer = NULL;
230 req->debug = REQ_FREE;
231 SLIST_INSERT_HEAD(&mpt->request_free_list, req, link);
234 /* Get a command buffer from the free queue */
235 request_t *
236 mpt_get_request(mpt_softc_t *mpt)
238 request_t *req;
239 req = SLIST_FIRST(&mpt->request_free_list);
240 if (req != NULL) {
241 if (req != &mpt->request_pool[req->index]) {
242 panic("mpt_get_request: corrupted request free list\n");
244 if (req->xfer != NULL) {
245 panic("mpt_get_request: corrupted request free list (xfer)\n");
247 SLIST_REMOVE_HEAD(&mpt->request_free_list, link);
248 req->debug = REQ_IN_PROGRESS;
250 return req;
253 /* Pass the command to the IOC */
254 void
255 mpt_send_cmd(mpt_softc_t *mpt, request_t *req)
257 req->sequence = mpt->sequence++;
258 if (mpt->verbose > 1) {
259 u_int32_t *pReq;
260 pReq = req->req_vbuf;
261 mpt_prt(mpt, "Send Request %d (0x%x):",
262 req->index, req->req_pbuf);
263 mpt_prt(mpt, "%08x %08x %08x %08x",
264 pReq[0], pReq[1], pReq[2], pReq[3]);
265 mpt_prt(mpt, "%08x %08x %08x %08x",
266 pReq[4], pReq[5], pReq[6], pReq[7]);
267 mpt_prt(mpt, "%08x %08x %08x %08x",
268 pReq[8], pReq[9], pReq[10], pReq[11]);
269 mpt_prt(mpt, "%08x %08x %08x %08x",
270 pReq[12], pReq[13], pReq[14], pReq[15]);
272 MPT_SYNC_REQ(mpt, req, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
273 req->debug = REQ_ON_CHIP;
274 mpt_write(mpt, MPT_OFFSET_REQUEST_Q, (u_int32_t) req->req_pbuf);
278 * Give the reply buffer back to the IOC after we have
279 * finished processing it.
281 void
282 mpt_free_reply(mpt_softc_t *mpt, u_int32_t ptr)
284 mpt_write(mpt, MPT_OFFSET_REPLY_Q, ptr);
287 /* Get a reply from the IOC */
288 u_int32_t
289 mpt_pop_reply_queue(mpt_softc_t *mpt)
291 return mpt_read(mpt, MPT_OFFSET_REPLY_Q);
295 * Send a command to the IOC via the handshake register.
297 * Only done at initialization time and for certain unusual
298 * commands such as device/bus reset as specified by LSI.
301 mpt_send_handshake_cmd(mpt_softc_t *mpt, size_t len, void *cmd)
303 int i;
304 u_int32_t data, *data32;
306 /* Check condition of the IOC */
307 data = mpt_rd_db(mpt);
308 if (((MPT_STATE(data) != MPT_DB_STATE_READY) &&
309 (MPT_STATE(data) != MPT_DB_STATE_RUNNING) &&
310 (MPT_STATE(data) != MPT_DB_STATE_FAULT)) ||
311 ( MPT_DB_IS_IN_USE(data) )) {
312 mpt_prt(mpt, "handshake aborted due to invalid doorbell state");
313 mpt_print_db(data);
314 return(EBUSY);
317 /* We move things in 32 bit chunks */
318 len = (len + 3) >> 2;
319 data32 = cmd;
321 /* Clear any left over pending doorbell interrupts */
322 if (MPT_DB_INTR(mpt_rd_intr(mpt)))
323 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
326 * Tell the handshake reg. we are going to send a command
327 * and how long it is going to be.
329 data = (MPI_FUNCTION_HANDSHAKE << MPI_DOORBELL_FUNCTION_SHIFT) |
330 (len << MPI_DOORBELL_ADD_DWORDS_SHIFT);
331 mpt_write(mpt, MPT_OFFSET_DOORBELL, data);
333 /* Wait for the chip to notice */
334 if (mpt_wait_db_int(mpt) != MPT_OK) {
335 mpt_prt(mpt, "mpt_send_handshake_cmd timeout1");
336 return ETIMEDOUT;
339 /* Clear the interrupt */
340 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
342 if (mpt_wait_db_ack(mpt) != MPT_OK) {
343 mpt_prt(mpt, "mpt_send_handshake_cmd timeout2");
344 return ETIMEDOUT;
347 /* Send the command */
348 for (i = 0; i < len; i++) {
349 mpt_write(mpt, MPT_OFFSET_DOORBELL, *data32++);
350 if (mpt_wait_db_ack(mpt) != MPT_OK) {
351 mpt_prt(mpt,
352 "mpt_send_handshake_cmd timeout! index = %d", i);
353 return ETIMEDOUT;
356 return MPT_OK;
359 /* Get the response from the handshake register */
361 mpt_recv_handshake_reply(mpt_softc_t *mpt, size_t reply_len, void *reply)
363 int left, reply_left;
364 u_int16_t *data16;
365 MSG_DEFAULT_REPLY *hdr;
367 /* We move things out in 16 bit chunks */
368 reply_len >>= 1;
369 data16 = (u_int16_t *)reply;
371 hdr = (MSG_DEFAULT_REPLY *)reply;
373 /* Get first word */
374 if (mpt_wait_db_int(mpt) != MPT_OK) {
375 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout1");
376 return ETIMEDOUT;
378 *data16++ = mpt_read(mpt, MPT_OFFSET_DOORBELL) & MPT_DB_DATA_MASK;
379 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
381 /* Get Second Word */
382 if (mpt_wait_db_int(mpt) != MPT_OK) {
383 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout2");
384 return ETIMEDOUT;
386 *data16++ = mpt_read(mpt, MPT_OFFSET_DOORBELL) & MPT_DB_DATA_MASK;
387 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
389 /* With the second word, we can now look at the length */
390 if (mpt->verbose > 1 && ((reply_len >> 1) != hdr->MsgLength)) {
391 mpt_prt(mpt, "reply length does not match message length: "
392 "got 0x%02x, expected 0x%02x",
393 hdr->MsgLength << 2, reply_len << 1);
396 /* Get rest of the reply; but don't overflow the provided buffer */
397 left = (hdr->MsgLength << 1) - 2;
398 reply_left = reply_len - 2;
399 while (left--) {
400 u_int16_t datum;
402 if (mpt_wait_db_int(mpt) != MPT_OK) {
403 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout3");
404 return ETIMEDOUT;
406 datum = mpt_read(mpt, MPT_OFFSET_DOORBELL);
408 if (reply_left-- > 0)
409 *data16++ = datum & MPT_DB_DATA_MASK;
411 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
414 /* One more wait & clear at the end */
415 if (mpt_wait_db_int(mpt) != MPT_OK) {
416 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout4");
417 return ETIMEDOUT;
419 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
421 if ((hdr->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
422 if (mpt->verbose > 1)
423 mpt_print_reply(hdr);
424 return (MPT_FAIL | hdr->IOCStatus);
427 return (0);
430 static int
431 mpt_get_iocfacts(mpt_softc_t *mpt, MSG_IOC_FACTS_REPLY *freplp)
433 MSG_IOC_FACTS f_req;
434 int error;
436 memset(&f_req, 0, sizeof f_req);
437 f_req.Function = MPI_FUNCTION_IOC_FACTS;
438 f_req.MsgContext = 0x12071942;
439 error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
440 if (error)
441 return(error);
442 error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
443 return (error);
446 static int
447 mpt_get_portfacts(mpt_softc_t *mpt, MSG_PORT_FACTS_REPLY *freplp)
449 MSG_PORT_FACTS f_req;
450 int error;
452 /* XXX: Only getting PORT FACTS for Port 0 */
453 memset(&f_req, 0, sizeof f_req);
454 f_req.Function = MPI_FUNCTION_PORT_FACTS;
455 f_req.MsgContext = 0x12071943;
456 error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
457 if (error)
458 return(error);
459 error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
460 return (error);
464 * Send the initialization request. This is where we specify how many
465 * SCSI busses and how many devices per bus we wish to emulate.
466 * This is also the command that specifies the max size of the reply
467 * frames from the IOC that we will be allocating.
469 static int
470 mpt_send_ioc_init(mpt_softc_t *mpt, u_int32_t who)
472 int error = 0;
473 MSG_IOC_INIT init;
474 MSG_IOC_INIT_REPLY reply;
476 memset(&init, 0, sizeof init);
477 init.WhoInit = who;
478 init.Function = MPI_FUNCTION_IOC_INIT;
479 init.MaxDevices = mpt->mpt_max_devices;
480 init.MaxBuses = 1;
481 init.ReplyFrameSize = MPT_REPLY_SIZE;
482 init.MsgContext = 0x12071941;
484 if ((error = mpt_send_handshake_cmd(mpt, sizeof init, &init)) != 0) {
485 return(error);
488 error = mpt_recv_handshake_reply(mpt, sizeof reply, &reply);
489 return (error);
494 * Utiltity routine to read configuration headers and pages
497 static int
498 mpt_read_cfg_header(mpt_softc_t *, int, int, int, fCONFIG_PAGE_HEADER *);
500 static int
501 mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber,
502 int PageAddress, fCONFIG_PAGE_HEADER *rslt)
504 int count;
505 request_t *req;
506 MSG_CONFIG *cfgp;
507 MSG_CONFIG_REPLY *reply;
509 req = mpt_get_request(mpt);
511 cfgp = req->req_vbuf;
512 memset(cfgp, 0, sizeof *cfgp);
514 cfgp->Action = MPI_CONFIG_ACTION_PAGE_HEADER;
515 cfgp->Function = MPI_FUNCTION_CONFIG;
516 cfgp->Header.PageNumber = (U8) PageNumber;
517 cfgp->Header.PageType = (U8) PageType;
518 cfgp->PageAddress = PageAddress;
519 MPI_pSGE_SET_FLAGS(((SGE_SIMPLE32 *) &cfgp->PageBufferSGE),
520 (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
521 MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
522 cfgp->MsgContext = req->index | 0x80000000;
524 mpt_check_doorbell(mpt);
525 mpt_send_cmd(mpt, req);
526 count = 0;
527 do {
528 DELAY(500);
529 mpt_intr(mpt);
530 if (++count == 1000) {
531 mpt_prt(mpt, "read_cfg_header timed out");
532 return (-1);
534 } while (req->debug == REQ_ON_CHIP);
536 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
537 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
538 mpt_prt(mpt, "mpt_read_cfg_header: Config Info Status %x",
539 reply->IOCStatus);
540 mpt_free_reply(mpt, (req->sequence << 1));
541 return (-1);
543 memcpy(rslt, &reply->Header, sizeof (fCONFIG_PAGE_HEADER));
544 mpt_free_reply(mpt, (req->sequence << 1));
545 mpt_free_request(mpt, req);
546 return (0);
549 #define CFG_DATA_OFF 128
552 mpt_read_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
554 int count;
555 request_t *req;
556 SGE_SIMPLE32 *se;
557 MSG_CONFIG *cfgp;
558 size_t amt;
559 MSG_CONFIG_REPLY *reply;
561 req = mpt_get_request(mpt);
563 cfgp = req->req_vbuf;
564 memset(cfgp, 0, MPT_REQUEST_AREA);
565 cfgp->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
566 cfgp->Function = MPI_FUNCTION_CONFIG;
567 cfgp->Header = *hdr;
568 amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
569 cfgp->Header.PageType &= MPI_CONFIG_PAGETYPE_MASK;
570 cfgp->PageAddress = PageAddress;
571 se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
572 se->Address = req->req_pbuf + CFG_DATA_OFF;
573 MPI_pSGE_SET_LENGTH(se, amt);
574 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
575 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
576 MPI_SGE_FLAGS_END_OF_LIST));
578 cfgp->MsgContext = req->index | 0x80000000;
580 mpt_check_doorbell(mpt);
581 mpt_send_cmd(mpt, req);
582 count = 0;
583 do {
584 DELAY(500);
585 mpt_intr(mpt);
586 if (++count == 1000) {
587 mpt_prt(mpt, "read_cfg_page timed out");
588 return (-1);
590 } while (req->debug == REQ_ON_CHIP);
592 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
593 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
594 mpt_prt(mpt, "mpt_read_cfg_page: Config Info Status %x",
595 reply->IOCStatus);
596 mpt_free_reply(mpt, (req->sequence << 1));
597 return (-1);
599 mpt_free_reply(mpt, (req->sequence << 1));
600 #if 0 /* XXXJRT */
601 bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap,
602 BUS_DMASYNC_POSTREAD);
603 #endif
604 if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
605 cfgp->Header.PageNumber == 0) {
606 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
607 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
608 cfgp->Header.PageNumber == 1) {
609 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
610 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
611 cfgp->Header.PageNumber == 2) {
612 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
613 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
614 cfgp->Header.PageNumber == 0) {
615 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
616 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
617 cfgp->Header.PageNumber == 1) {
618 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
620 memcpy(hdr, (char *)req->req_vbuf + CFG_DATA_OFF, amt);
621 mpt_free_request(mpt, req);
622 return (0);
626 mpt_write_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
628 int count, hdr_attr;
629 request_t *req;
630 SGE_SIMPLE32 *se;
631 MSG_CONFIG *cfgp;
632 size_t amt;
633 MSG_CONFIG_REPLY *reply;
635 req = mpt_get_request(mpt);
637 cfgp = req->req_vbuf;
638 memset(cfgp, 0, sizeof *cfgp);
640 hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK;
641 if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE &&
642 hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) {
643 mpt_prt(mpt, "page type 0x%x not changeable",
644 hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
645 return (-1);
647 hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK;
649 cfgp->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
650 cfgp->Function = MPI_FUNCTION_CONFIG;
651 cfgp->Header = *hdr;
652 amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
653 cfgp->PageAddress = PageAddress;
655 se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
656 se->Address = req->req_pbuf + CFG_DATA_OFF;
657 MPI_pSGE_SET_LENGTH(se, amt);
658 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
659 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
660 MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_HOST_TO_IOC));
662 cfgp->MsgContext = req->index | 0x80000000;
664 if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
665 cfgp->Header.PageNumber == 0) {
666 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
667 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
668 cfgp->Header.PageNumber == 1) {
669 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
670 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
671 cfgp->Header.PageNumber == 2) {
672 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
673 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
674 cfgp->Header.PageNumber == 0) {
675 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
676 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
677 cfgp->Header.PageNumber == 1) {
678 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
680 memcpy((char *)req->req_vbuf + CFG_DATA_OFF, hdr, amt);
681 /* Restore stripped out attributes */
682 hdr->PageType |= hdr_attr;
684 mpt_check_doorbell(mpt);
685 mpt_send_cmd(mpt, req);
686 count = 0;
687 do {
688 DELAY(500);
689 mpt_intr(mpt);
690 if (++count == 1000) {
691 hdr->PageType |= hdr_attr;
692 mpt_prt(mpt, "mpt_write_cfg_page timed out");
693 return (-1);
695 } while (req->debug == REQ_ON_CHIP);
697 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
698 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
699 mpt_prt(mpt, "mpt_write_cfg_page: Config Info Status %x",
700 reply->IOCStatus);
701 mpt_free_reply(mpt, (req->sequence << 1));
702 return (-1);
704 mpt_free_reply(mpt, (req->sequence << 1));
706 mpt_free_request(mpt, req);
707 return (0);
711 * Read SCSI configuration information
713 static int
714 mpt_read_config_info_spi(mpt_softc_t *mpt)
716 int rv, i;
718 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0,
719 0, &mpt->mpt_port_page0.Header);
720 if (rv) {
721 return (-1);
723 if (mpt->verbose > 1) {
724 mpt_prt(mpt, "SPI Port Page 0 Header: %x %x %x %x",
725 mpt->mpt_port_page0.Header.PageVersion,
726 mpt->mpt_port_page0.Header.PageLength,
727 mpt->mpt_port_page0.Header.PageNumber,
728 mpt->mpt_port_page0.Header.PageType);
731 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1,
732 0, &mpt->mpt_port_page1.Header);
733 if (rv) {
734 return (-1);
736 if (mpt->verbose > 1) {
737 mpt_prt(mpt, "SPI Port Page 1 Header: %x %x %x %x",
738 mpt->mpt_port_page1.Header.PageVersion,
739 mpt->mpt_port_page1.Header.PageLength,
740 mpt->mpt_port_page1.Header.PageNumber,
741 mpt->mpt_port_page1.Header.PageType);
744 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2,
745 0, &mpt->mpt_port_page2.Header);
746 if (rv) {
747 return (-1);
750 if (mpt->verbose > 1) {
751 mpt_prt(mpt, "SPI Port Page 2 Header: %x %x %x %x",
752 mpt->mpt_port_page1.Header.PageVersion,
753 mpt->mpt_port_page1.Header.PageLength,
754 mpt->mpt_port_page1.Header.PageNumber,
755 mpt->mpt_port_page1.Header.PageType);
758 for (i = 0; i < 16; i++) {
759 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
760 0, i, &mpt->mpt_dev_page0[i].Header);
761 if (rv) {
762 return (-1);
764 if (mpt->verbose > 1) {
765 mpt_prt(mpt,
766 "SPI Target %d Device Page 0 Header: %x %x %x %x",
767 i, mpt->mpt_dev_page0[i].Header.PageVersion,
768 mpt->mpt_dev_page0[i].Header.PageLength,
769 mpt->mpt_dev_page0[i].Header.PageNumber,
770 mpt->mpt_dev_page0[i].Header.PageType);
773 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
774 1, i, &mpt->mpt_dev_page1[i].Header);
775 if (rv) {
776 return (-1);
778 if (mpt->verbose > 1) {
779 mpt_prt(mpt,
780 "SPI Target %d Device Page 1 Header: %x %x %x %x",
781 i, mpt->mpt_dev_page1[i].Header.PageVersion,
782 mpt->mpt_dev_page1[i].Header.PageLength,
783 mpt->mpt_dev_page1[i].Header.PageNumber,
784 mpt->mpt_dev_page1[i].Header.PageType);
789 * At this point, we don't *have* to fail. As long as we have
790 * valid config header information, we can (barely) lurch
791 * along.
794 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page0.Header);
795 if (rv) {
796 mpt_prt(mpt, "failed to read SPI Port Page 0");
797 } else if (mpt->verbose > 1) {
798 mpt_prt(mpt,
799 "SPI Port Page 0: Capabilities %x PhysicalInterface %x",
800 mpt->mpt_port_page0.Capabilities,
801 mpt->mpt_port_page0.PhysicalInterface);
804 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header);
805 if (rv) {
806 mpt_prt(mpt, "failed to read SPI Port Page 1");
807 } else if (mpt->verbose > 1) {
808 mpt_prt(mpt,
809 "SPI Port Page 1: Configuration %x OnBusTimerValue %x",
810 mpt->mpt_port_page1.Configuration,
811 mpt->mpt_port_page1.OnBusTimerValue);
814 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header);
815 if (rv) {
816 mpt_prt(mpt, "failed to read SPI Port Page 2");
817 } else if (mpt->verbose > 1) {
818 mpt_prt(mpt,
819 "SPI Port Page 2: Flags %x Settings %x",
820 mpt->mpt_port_page2.PortFlags,
821 mpt->mpt_port_page2.PortSettings);
822 for (i = 0; i < 16; i++) {
823 mpt_prt(mpt,
824 "SPI Port Page 2 Tgt %d: timo %x SF %x Flags %x",
825 i, mpt->mpt_port_page2.DeviceSettings[i].Timeout,
826 mpt->mpt_port_page2.DeviceSettings[i].SyncFactor,
827 mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags);
831 for (i = 0; i < 16; i++) {
832 rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page0[i].Header);
833 if (rv) {
834 mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 0", i);
835 continue;
837 if (mpt->verbose > 1) {
838 mpt_prt(mpt,
839 "SPI Tgt %d Page 0: NParms %x Information %x",
840 i, mpt->mpt_dev_page0[i].NegotiatedParameters,
841 mpt->mpt_dev_page0[i].Information);
843 rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page1[i].Header);
844 if (rv) {
845 mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 1", i);
846 continue;
848 if (mpt->verbose > 1) {
849 mpt_prt(mpt,
850 "SPI Tgt %d Page 1: RParms %x Configuration %x",
851 i, mpt->mpt_dev_page1[i].RequestedParameters,
852 mpt->mpt_dev_page1[i].Configuration);
855 return (0);
859 * Validate SPI configuration information.
861 * In particular, validate SPI Port Page 1.
863 static int
864 mpt_set_initial_config_spi(mpt_softc_t *mpt)
866 int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id;
868 mpt->mpt_disc_enable = 0xff;
869 mpt->mpt_tag_enable = 0;
871 if (mpt->mpt_port_page1.Configuration != pp1val) {
872 fCONFIG_PAGE_SCSI_PORT_1 tmp;
873 mpt_prt(mpt,
874 "SPI Port Page 1 Config value bad (%x)- should be %x",
875 mpt->mpt_port_page1.Configuration, pp1val);
876 tmp = mpt->mpt_port_page1;
877 tmp.Configuration = pp1val;
878 if (mpt_write_cfg_page(mpt, 0, &tmp.Header)) {
879 return (-1);
881 if (mpt_read_cfg_page(mpt, 0, &tmp.Header)) {
882 return (-1);
884 if (tmp.Configuration != pp1val) {
885 mpt_prt(mpt,
886 "failed to reset SPI Port Page 1 Config value");
887 return (-1);
889 mpt->mpt_port_page1 = tmp;
892 for (i = 0; i < 16; i++) {
893 fCONFIG_PAGE_SCSI_DEVICE_1 tmp;
894 tmp = mpt->mpt_dev_page1[i];
895 tmp.RequestedParameters = 0;
896 tmp.Configuration = 0;
897 if (mpt->verbose > 1) {
898 mpt_prt(mpt,
899 "Set Tgt %d SPI DevicePage 1 values to %x 0 %x",
900 i, tmp.RequestedParameters, tmp.Configuration);
902 if (mpt_write_cfg_page(mpt, i, &tmp.Header)) {
903 return (-1);
905 if (mpt_read_cfg_page(mpt, i, &tmp.Header)) {
906 return (-1);
908 mpt->mpt_dev_page1[i] = tmp;
909 if (mpt->verbose > 1) {
910 mpt_prt(mpt,
911 "SPI Tgt %d Page 1: RParm %x Configuration %x", i,
912 mpt->mpt_dev_page1[i].RequestedParameters,
913 mpt->mpt_dev_page1[i].Configuration);
916 return (0);
920 * Enable IOC port
922 static int
923 mpt_send_port_enable(mpt_softc_t *mpt, int port)
925 int count;
926 request_t *req;
927 MSG_PORT_ENABLE *enable_req;
929 req = mpt_get_request(mpt);
931 enable_req = req->req_vbuf;
932 memset(enable_req, 0, sizeof *enable_req);
934 enable_req->Function = MPI_FUNCTION_PORT_ENABLE;
935 enable_req->MsgContext = req->index | 0x80000000;
936 enable_req->PortNumber = port;
938 mpt_check_doorbell(mpt);
939 if (mpt->verbose > 1) {
940 mpt_prt(mpt, "enabling port %d", port);
942 mpt_send_cmd(mpt, req);
944 count = 0;
945 do {
946 DELAY(500);
947 mpt_intr(mpt);
948 if (++count == 100000) {
949 mpt_prt(mpt, "port enable timed out");
950 return (-1);
952 } while (req->debug == REQ_ON_CHIP);
953 mpt_free_request(mpt, req);
954 return (0);
958 * Enable/Disable asynchronous event reporting.
960 * NB: this is the first command we send via shared memory
961 * instead of the handshake register.
963 static int
964 mpt_send_event_request(mpt_softc_t *mpt, int onoff)
966 request_t *req;
967 MSG_EVENT_NOTIFY *enable_req;
969 req = mpt_get_request(mpt);
971 enable_req = req->req_vbuf;
972 memset(enable_req, 0, sizeof *enable_req);
974 enable_req->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
975 enable_req->MsgContext = req->index | 0x80000000;
976 enable_req->Switch = onoff;
978 mpt_check_doorbell(mpt);
979 if (mpt->verbose > 1) {
980 mpt_prt(mpt, "%sabling async events", onoff? "en" : "dis");
982 mpt_send_cmd(mpt, req);
984 return (0);
988 * Un-mask the interrupts on the chip.
990 void
991 mpt_enable_ints(mpt_softc_t *mpt)
993 /* Unmask every thing except door bell int */
994 mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK);
998 * Mask the interrupts on the chip.
1000 void
1001 mpt_disable_ints(mpt_softc_t *mpt)
1003 /* Mask all interrupts */
1004 mpt_write(mpt, MPT_OFFSET_INTR_MASK,
1005 MPT_INTR_REPLY_MASK | MPT_INTR_DB_MASK);
1008 /* (Re)Initialize the chip for use */
1010 mpt_hw_init(mpt_softc_t *mpt)
1012 u_int32_t db;
1013 int try;
1016 * Start by making sure we're not at FAULT or RESET state
1018 for (try = 0; try < MPT_MAX_TRYS; try++) {
1020 db = mpt_rd_db(mpt);
1022 switch (MPT_STATE(db)) {
1023 case MPT_DB_STATE_READY:
1024 return (0);
1026 default:
1027 /* if peer has already reset us, don't do it again! */
1028 if (MPT_WHO(db) == MPT_DB_INIT_PCIPEER)
1029 return (0);
1030 /*FALLTHRU*/
1031 case MPT_DB_STATE_RESET:
1032 case MPT_DB_STATE_FAULT:
1033 if (mpt_reset(mpt) != MPT_OK) {
1034 DELAY(10000);
1035 continue;
1037 break;
1040 return (EIO);
1044 mpt_init(mpt_softc_t *mpt, u_int32_t who)
1046 int try;
1047 MSG_IOC_FACTS_REPLY facts;
1048 MSG_PORT_FACTS_REPLY pfp;
1049 u_int32_t pptr;
1050 int val;
1052 /* Put all request buffers (back) on the free list */
1053 SLIST_INIT(&mpt->request_free_list);
1054 for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
1055 mpt_free_request(mpt, &mpt->request_pool[val]);
1058 if (mpt->verbose > 1) {
1059 mpt_prt(mpt, "doorbell req = %s",
1060 mpt_ioc_diag(mpt_read(mpt, MPT_OFFSET_DOORBELL)));
1064 * Start by making sure we're not at FAULT or RESET state
1066 if (mpt_hw_init(mpt) != 0)
1067 return (EIO);
1069 for (try = 0; try < MPT_MAX_TRYS; try++) {
1071 * No need to reset if the IOC is already in the READY state.
1074 if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) {
1075 mpt_prt(mpt, "mpt_get_iocfacts failed");
1076 continue;
1079 if (mpt->verbose > 1) {
1080 mpt_prt(mpt,
1081 "IOCFACTS: GlobalCredits=%d BlockSize=%u "
1082 "Request Frame Size %u\n", facts.GlobalCredits,
1083 facts.BlockSize, facts.RequestFrameSize);
1085 mpt->mpt_max_devices = facts.MaxDevices;
1086 mpt->mpt_global_credits = facts.GlobalCredits;
1087 mpt->request_frame_size = facts.RequestFrameSize;
1089 if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) {
1090 mpt_prt(mpt, "mpt_get_portfacts failed");
1091 continue;
1094 if (mpt->verbose > 1) {
1095 mpt_prt(mpt,
1096 "PORTFACTS: Type %x PFlags %x IID %d MaxDev %d\n",
1097 pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID,
1098 pfp.MaxDevices);
1101 if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
1102 mpt_prt(mpt, "initiator role unsupported");
1103 return (ENXIO);
1106 switch (pfp.PortType) {
1107 case MPI_PORTFACTS_PORTTYPE_FC:
1108 mpt->is_fc = 1;
1109 mpt->mpt_max_devices = 255;
1110 break;
1111 case MPI_PORTFACTS_PORTTYPE_SCSI:
1112 mpt->is_scsi = 1;
1113 /* some SPI controllers (VMWare, Sun) lie */
1114 mpt->mpt_max_devices = 16;
1115 break;
1116 case MPI_PORTFACTS_PORTTYPE_SAS:
1117 mpt->is_sas = 1;
1118 break;
1119 default:
1120 mpt_prt(mpt, "Unsupported Port Type (%x)",
1121 pfp.PortType);
1122 return (ENXIO);
1125 mpt->mpt_ini_id = pfp.PortSCSIID;
1127 if (mpt_send_ioc_init(mpt, who) != MPT_OK) {
1128 mpt_prt(mpt, "mpt_send_ioc_init failed");
1129 continue;
1132 if (mpt->verbose > 1) {
1133 mpt_prt(mpt, "mpt_send_ioc_init ok");
1136 if (mpt_wait_state(mpt, MPT_DB_STATE_RUNNING) != MPT_OK) {
1137 mpt_prt(mpt, "IOC failed to go to run state");
1138 continue;
1140 if (mpt->verbose > 1) {
1141 mpt_prt(mpt, "IOC now at RUNSTATE");
1145 * Give it reply buffers
1147 * Do *not* except global credits.
1149 for (val = 0, pptr = mpt->reply_phys;
1150 (pptr + MPT_REPLY_SIZE) < (mpt->reply_phys + PAGE_SIZE);
1151 pptr += MPT_REPLY_SIZE) {
1152 mpt_free_reply(mpt, pptr);
1153 if (++val == mpt->mpt_global_credits - 1)
1154 break;
1158 * Enable asynchronous event reporting
1160 mpt_send_event_request(mpt, 1);
1164 * Read set up initial configuration information
1165 * (SPI only for now)
1168 if (mpt->is_scsi) {
1169 if (mpt_read_config_info_spi(mpt)) {
1170 return (EIO);
1172 if (mpt_set_initial_config_spi(mpt)) {
1173 return (EIO);
1178 * Now enable the port
1180 if (mpt_send_port_enable(mpt, 0) != MPT_OK) {
1181 mpt_prt(mpt, "failed to enable port 0");
1182 continue;
1185 if (mpt->verbose > 1) {
1186 mpt_prt(mpt, "enabled port 0");
1189 /* Everything worked */
1190 break;
1193 if (try >= MPT_MAX_TRYS) {
1194 mpt_prt(mpt, "failed to initialize IOC");
1195 return (EIO);
1198 if (mpt->verbose > 1) {
1199 mpt_prt(mpt, "enabling interrupts");
1202 mpt_enable_ints(mpt);
1203 return (0);