2 * Generic routines for LSI '909 FC adapters.
5 * Copyright (c) 2000, 2001 by Greg Ansley
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice immediately at the beginning of the file, without modification,
12 * this list of conditions, and the following disclaimer.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * Additional Copyright (c) 2002 by Matthew Jacob under same license.
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
35 #include <dev/mpt/mpt_freebsd.h>
37 #define MPT_MAX_TRYS 3
38 #define MPT_MAX_WAIT 300000
40 static int maxwait_ack = 0;
41 static int maxwait_int = 0;
42 static int maxwait_state = 0;
44 static INLINE u_int32_t mpt_rd_db(mpt_softc_t *mpt);
45 static INLINE u_int32_t mpt_rd_intr(mpt_softc_t *mpt);
47 static INLINE u_int32_t
48 mpt_rd_db(mpt_softc_t *mpt)
50 return mpt_read(mpt, MPT_OFFSET_DOORBELL);
53 static INLINE u_int32_t
54 mpt_rd_intr(mpt_softc_t *mpt)
56 return mpt_read(mpt, MPT_OFFSET_INTR_STATUS);
59 /* Busy wait for a door bell to be read by IOC */
61 mpt_wait_db_ack(mpt_softc_t *mpt)
64 for (i=0; i < MPT_MAX_WAIT; i++) {
65 if (!MPT_DB_IS_BUSY(mpt_rd_intr(mpt))) {
66 maxwait_ack = i > maxwait_ack ? i : maxwait_ack;
75 /* Busy wait for a door bell interrupt */
77 mpt_wait_db_int(mpt_softc_t *mpt)
80 for (i=0; i < MPT_MAX_WAIT; i++) {
81 if (MPT_DB_INTR(mpt_rd_intr(mpt))) {
82 maxwait_int = i > maxwait_int ? i : maxwait_int;
90 /* Wait for IOC to transition to a give state */
92 mpt_check_doorbell(mpt_softc_t *mpt)
94 u_int32_t db = mpt_rd_db(mpt);
95 if (MPT_STATE(db) != MPT_DB_STATE_RUNNING) {
96 mpt_prt(mpt, "Device not running");
101 /* Wait for IOC to transition to a give state */
103 mpt_wait_state(mpt_softc_t *mpt, enum DB_STATE_BITS state)
107 for (i = 0; i < MPT_MAX_WAIT; i++) {
108 u_int32_t db = mpt_rd_db(mpt);
109 if (MPT_STATE(db) == state) {
110 maxwait_state = i > maxwait_state ? i : maxwait_state;
119 /* Issue the reset COMMAND to the IOC */
121 mpt_soft_reset(mpt_softc_t *mpt)
124 mpt_prt(mpt, "soft reset");
127 /* Have to use hard reset if we are not in Running state */
128 if (MPT_STATE(mpt_rd_db(mpt)) != MPT_DB_STATE_RUNNING) {
129 mpt_prt(mpt, "soft reset failed: device not running");
133 /* If door bell is in use we don't have a chance of getting
134 * a word in since the IOC probably crashed in message
135 * processing. So don't waste our time.
137 if (MPT_DB_IS_IN_USE(mpt_rd_db(mpt))) {
138 mpt_prt(mpt, "soft reset failed: doorbell wedged");
142 /* Send the reset request to the IOC */
143 mpt_write(mpt, MPT_OFFSET_DOORBELL,
144 MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET << MPI_DOORBELL_FUNCTION_SHIFT);
145 if (mpt_wait_db_ack(mpt) != MPT_OK) {
146 mpt_prt(mpt, "soft reset failed: ack timeout");
150 /* Wait for the IOC to reload and come out of reset state */
151 if (mpt_wait_state(mpt, MPT_DB_STATE_READY) != MPT_OK) {
152 mpt_prt(mpt, "soft reset failed: device did not start running");
159 /* This is a magic diagnostic reset that resets all the ARM
160 * processors in the chip.
163 mpt_hard_reset(mpt_softc_t *mpt)
165 /* This extra read comes for the Linux source
166 * released by LSI. It's function is undocumented!
169 mpt_prt(mpt, "hard reset");
171 mpt_read(mpt, MPT_OFFSET_FUBAR);
173 /* Enable diagnostic registers */
174 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_1);
175 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_2);
176 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_3);
177 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_4);
178 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_5);
180 /* Diag. port is now active so we can now hit the reset bit */
181 mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, MPT_DIAG_RESET_IOC);
185 /* Disable Diagnostic Register */
186 mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFF);
188 /* Restore the config register values */
189 /* Hard resets are known to screw up the BAR for diagnostic
190 memory accesses (Mem1). */
191 mpt_set_config_regs(mpt);
192 if (mpt->mpt2 != NULL) {
193 mpt_set_config_regs(mpt->mpt2);
196 /* Note that if there is no valid firmware to run, the doorbell will
197 remain in the reset state (0x00000000) */
201 * Reset the IOC when needed. Try software command first then if needed
202 * poke at the magic diagnostic reset. Note that a hard reset resets
203 * *both* IOCs on dual function chips (FC929 && LSI1030) as well as
204 * fouls up the PCI configuration registers.
207 mpt_reset(mpt_softc_t *mpt)
211 /* Try a soft reset */
212 if ((ret = mpt_soft_reset(mpt)) != MPT_OK) {
213 /* Failed; do a hard reset */
216 /* Wait for the IOC to reload and come out of reset state */
217 ret = mpt_wait_state(mpt, MPT_DB_STATE_READY);
219 mpt_prt(mpt, "failed to reset device");
226 /* Return a command buffer to the free queue */
228 mpt_free_request(mpt_softc_t *mpt, request_t *req)
230 if (req == NULL || req != &mpt->request_pool[req->index]) {
231 panic("mpt_free_request bad req ptr\n");
236 req->debug = REQ_FREE;
237 SLIST_INSERT_HEAD(&mpt->request_free_list, req, link);
240 /* Get a command buffer from the free queue */
242 mpt_get_request(mpt_softc_t *mpt)
245 req = SLIST_FIRST(&mpt->request_free_list);
247 if (req != &mpt->request_pool[req->index]) {
248 panic("mpt_get_request: corrupted request free list\n");
250 if (req->ccb != NULL) {
251 panic("mpt_get_request: corrupted request free list (ccb)\n");
253 SLIST_REMOVE_HEAD(&mpt->request_free_list, link);
254 req->debug = REQ_IN_PROGRESS;
259 /* Pass the command to the IOC */
261 mpt_send_cmd(mpt_softc_t *mpt, request_t *req)
263 req->sequence = mpt->sequence++;
264 if (mpt->verbose > 1) {
266 pReq = req->req_vbuf;
267 mpt_prt(mpt, "Send Request %d (0x%x):",
268 req->index, req->req_pbuf);
269 mpt_prt(mpt, "%08x %08x %08x %08x",
270 pReq[0], pReq[1], pReq[2], pReq[3]);
271 mpt_prt(mpt, "%08x %08x %08x %08x",
272 pReq[4], pReq[5], pReq[6], pReq[7]);
273 mpt_prt(mpt, "%08x %08x %08x %08x",
274 pReq[8], pReq[9], pReq[10], pReq[11]);
275 mpt_prt(mpt, "%08x %08x %08x %08x",
276 pReq[12], pReq[13], pReq[14], pReq[15]);
278 bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap,
279 BUS_DMASYNC_PREWRITE);
280 req->debug = REQ_ON_CHIP;
281 mpt_write(mpt, MPT_OFFSET_REQUEST_Q, (u_int32_t) req->req_pbuf);
285 * Give the reply buffer back to the IOC after we have
286 * finished processing it.
289 mpt_free_reply(mpt_softc_t *mpt, u_int32_t ptr)
291 mpt_write(mpt, MPT_OFFSET_REPLY_Q, ptr);
294 /* Get a reply from the IOC */
296 mpt_pop_reply_queue(mpt_softc_t *mpt)
298 return mpt_read(mpt, MPT_OFFSET_REPLY_Q);
302 * Send a command to the IOC via the handshake register.
304 * Only done at initialization time and for certain unusual
305 * commands such as device/bus reset as specified by LSI.
308 mpt_send_handshake_cmd(mpt_softc_t *mpt, size_t len, void *cmd)
311 u_int32_t data, *data32;
313 /* Check condition of the IOC */
314 data = mpt_rd_db(mpt);
315 if (((MPT_STATE(data) != MPT_DB_STATE_READY) &&
316 (MPT_STATE(data) != MPT_DB_STATE_RUNNING) &&
317 (MPT_STATE(data) != MPT_DB_STATE_FAULT)) ||
318 ( MPT_DB_IS_IN_USE(data) )) {
319 mpt_prt(mpt, "handshake aborted due to invalid doorbell state");
324 /* We move things in 32 bit chunks */
325 len = (len + 3) >> 2;
328 /* Clear any left over pending doorbell interupts */
329 if (MPT_DB_INTR(mpt_rd_intr(mpt)))
330 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
333 * Tell the handshake reg. we are going to send a command
334 * and how long it is going to be.
336 data = (MPI_FUNCTION_HANDSHAKE << MPI_DOORBELL_FUNCTION_SHIFT) |
337 (len << MPI_DOORBELL_ADD_DWORDS_SHIFT);
338 mpt_write(mpt, MPT_OFFSET_DOORBELL, data);
340 /* Wait for the chip to notice */
341 if (mpt_wait_db_int(mpt) != MPT_OK) {
342 mpt_prt(mpt, "mpt_send_handshake_cmd timeout1");
346 /* Clear the interrupt */
347 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
349 if (mpt_wait_db_ack(mpt) != MPT_OK) {
350 mpt_prt(mpt, "mpt_send_handshake_cmd timeout2");
354 /* Send the command */
355 for (i = 0; i < len; i++) {
356 mpt_write(mpt, MPT_OFFSET_DOORBELL, *data32++);
357 if (mpt_wait_db_ack(mpt) != MPT_OK) {
359 "mpt_send_handshake_cmd timeout! index = %d", i);
366 /* Get the response from the handshake register */
368 mpt_recv_handshake_reply(mpt_softc_t *mpt, size_t reply_len, void *reply)
370 int left, reply_left;
372 MSG_DEFAULT_REPLY *hdr;
374 /* We move things out in 16 bit chunks */
376 data16 = (u_int16_t *)reply;
378 hdr = (MSG_DEFAULT_REPLY *)reply;
381 if (mpt_wait_db_int(mpt) != MPT_OK) {
382 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout1");
385 *data16++ = mpt_read(mpt, MPT_OFFSET_DOORBELL) & MPT_DB_DATA_MASK;
386 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
388 /* Get Second Word */
389 if (mpt_wait_db_int(mpt) != MPT_OK) {
390 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout2");
393 *data16++ = mpt_read(mpt, MPT_OFFSET_DOORBELL) & MPT_DB_DATA_MASK;
394 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
396 /* With the second word, we can now look at the length */
397 if (mpt->verbose > 1 && ((reply_len >> 1) != hdr->MsgLength)) {
398 mpt_prt(mpt, "reply length does not match message length: "
399 "got 0x%02x, expected 0x%02x",
400 hdr->MsgLength << 2, reply_len << 1);
403 /* Get rest of the reply; but don't overflow the provided buffer */
404 left = (hdr->MsgLength << 1) - 2;
405 reply_left = reply_len - 2;
409 if (mpt_wait_db_int(mpt) != MPT_OK) {
410 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout3");
413 datum = mpt_read(mpt, MPT_OFFSET_DOORBELL);
415 if (reply_left-- > 0)
416 *data16++ = datum & MPT_DB_DATA_MASK;
418 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
421 /* One more wait & clear at the end */
422 if (mpt_wait_db_int(mpt) != MPT_OK) {
423 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout4");
426 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
428 if ((hdr->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
429 if (mpt->verbose > 1)
430 mpt_print_reply(hdr);
431 return (MPT_FAIL | hdr->IOCStatus);
438 mpt_get_iocfacts(mpt_softc_t *mpt, MSG_IOC_FACTS_REPLY *freplp)
443 bzero(&f_req, sizeof f_req);
444 f_req.Function = MPI_FUNCTION_IOC_FACTS;
445 f_req.MsgContext = 0x12071942;
446 error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
449 error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
454 mpt_get_portfacts(mpt_softc_t *mpt, MSG_PORT_FACTS_REPLY *freplp)
456 MSG_PORT_FACTS f_req;
459 /* XXX: Only getting PORT FACTS for Port 0 */
460 bzero(&f_req, sizeof f_req);
461 f_req.Function = MPI_FUNCTION_PORT_FACTS;
462 f_req.MsgContext = 0x12071943;
463 error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
466 error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
471 * Send the initialization request. This is where we specify how many
472 * SCSI busses and how many devices per bus we wish to emulate.
473 * This is also the command that specifies the max size of the reply
474 * frames from the IOC that we will be allocating.
477 mpt_send_ioc_init(mpt_softc_t *mpt, u_int32_t who)
481 MSG_IOC_INIT_REPLY reply;
483 bzero(&init, sizeof init);
485 init.Function = MPI_FUNCTION_IOC_INIT;
487 init.MaxDevices = 255;
489 init.MaxDevices = 16;
492 init.ReplyFrameSize = MPT_REPLY_SIZE;
493 init.MsgContext = 0x12071941;
495 if ((error = mpt_send_handshake_cmd(mpt, sizeof init, &init)) != 0) {
499 error = mpt_recv_handshake_reply(mpt, sizeof reply, &reply);
505 * Utiltity routine to read configuration headers and pages
509 mpt_read_cfg_header(mpt_softc_t *, int, int, int, CONFIG_PAGE_HEADER *);
512 mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber,
513 int PageAddress, CONFIG_PAGE_HEADER *rslt)
518 MSG_CONFIG_REPLY *reply;
520 req = mpt_get_request(mpt);
522 cfgp = req->req_vbuf;
523 bzero(cfgp, sizeof *cfgp);
525 cfgp->Action = MPI_CONFIG_ACTION_PAGE_HEADER;
526 cfgp->Function = MPI_FUNCTION_CONFIG;
527 cfgp->Header.PageNumber = (U8) PageNumber;
528 cfgp->Header.PageType = (U8) PageType;
529 cfgp->PageAddress = PageAddress;
530 MPI_pSGE_SET_FLAGS(((SGE_SIMPLE32 *) &cfgp->PageBufferSGE),
531 (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
532 MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
533 cfgp->MsgContext = req->index | 0x80000000;
535 mpt_check_doorbell(mpt);
536 mpt_send_cmd(mpt, req);
541 if (++count == 1000) {
542 mpt_prt(mpt, "read_cfg_header timed out");
545 } while (req->debug == REQ_ON_CHIP);
547 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
548 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
549 mpt_prt(mpt, "mpt_read_cfg_header: Config Info Status %x",
551 mpt_free_reply(mpt, (req->sequence << 1));
554 bcopy(&reply->Header, rslt, sizeof (CONFIG_PAGE_HEADER));
555 mpt_free_reply(mpt, (req->sequence << 1));
556 mpt_free_request(mpt, req);
560 #define CFG_DATA_OFF 128
563 mpt_read_cfg_page(mpt_softc_t *mpt, int PageAddress, CONFIG_PAGE_HEADER *hdr)
570 MSG_CONFIG_REPLY *reply;
572 req = mpt_get_request(mpt);
574 cfgp = req->req_vbuf;
575 bzero(cfgp, MPT_REQUEST_AREA);
576 cfgp->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
577 cfgp->Function = MPI_FUNCTION_CONFIG;
579 amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
580 cfgp->Header.PageType &= MPI_CONFIG_PAGETYPE_MASK;
581 cfgp->PageAddress = PageAddress;
582 se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
583 se->Address = req->req_pbuf + CFG_DATA_OFF;
584 MPI_pSGE_SET_LENGTH(se, amt);
585 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
586 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
587 MPI_SGE_FLAGS_END_OF_LIST));
589 cfgp->MsgContext = req->index | 0x80000000;
591 mpt_check_doorbell(mpt);
592 mpt_send_cmd(mpt, req);
597 if (++count == 1000) {
598 mpt_prt(mpt, "read_cfg_page timed out");
601 } while (req->debug == REQ_ON_CHIP);
603 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
604 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
605 mpt_prt(mpt, "mpt_read_cfg_page: Config Info Status %x",
607 mpt_free_reply(mpt, (req->sequence << 1));
610 mpt_free_reply(mpt, (req->sequence << 1));
611 bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap,
612 BUS_DMASYNC_POSTREAD);
613 if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
614 cfgp->Header.PageNumber == 0) {
615 amt = sizeof (CONFIG_PAGE_SCSI_PORT_0);
616 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
617 cfgp->Header.PageNumber == 1) {
618 amt = sizeof (CONFIG_PAGE_SCSI_PORT_1);
619 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
620 cfgp->Header.PageNumber == 2) {
621 amt = sizeof (CONFIG_PAGE_SCSI_PORT_2);
622 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
623 cfgp->Header.PageNumber == 0) {
624 amt = sizeof (CONFIG_PAGE_SCSI_DEVICE_0);
625 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
626 cfgp->Header.PageNumber == 1) {
627 amt = sizeof (CONFIG_PAGE_SCSI_DEVICE_1);
629 bcopy(((caddr_t)req->req_vbuf)+CFG_DATA_OFF, hdr, amt);
630 mpt_free_request(mpt, req);
635 mpt_write_cfg_page(mpt_softc_t *mpt, int PageAddress, CONFIG_PAGE_HEADER *hdr)
642 MSG_CONFIG_REPLY *reply;
644 req = mpt_get_request(mpt);
646 cfgp = req->req_vbuf;
647 bzero(cfgp, sizeof *cfgp);
649 hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK;
650 if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE &&
651 hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) {
652 mpt_prt(mpt, "page type 0x%x not changeable",
653 hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
656 hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK;
658 cfgp->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
659 cfgp->Function = MPI_FUNCTION_CONFIG;
661 amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
662 cfgp->PageAddress = PageAddress;
664 se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
665 se->Address = req->req_pbuf + CFG_DATA_OFF;
666 MPI_pSGE_SET_LENGTH(se, amt);
667 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
668 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
669 MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_HOST_TO_IOC));
671 cfgp->MsgContext = req->index | 0x80000000;
673 if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
674 cfgp->Header.PageNumber == 0) {
675 amt = sizeof (CONFIG_PAGE_SCSI_PORT_0);
676 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
677 cfgp->Header.PageNumber == 1) {
678 amt = sizeof (CONFIG_PAGE_SCSI_PORT_1);
679 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
680 cfgp->Header.PageNumber == 2) {
681 amt = sizeof (CONFIG_PAGE_SCSI_PORT_2);
682 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
683 cfgp->Header.PageNumber == 0) {
684 amt = sizeof (CONFIG_PAGE_SCSI_DEVICE_0);
685 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE &&
686 cfgp->Header.PageNumber == 1) {
687 amt = sizeof (CONFIG_PAGE_SCSI_DEVICE_1);
689 bcopy(hdr, ((caddr_t)req->req_vbuf)+CFG_DATA_OFF, amt);
690 /* Restore stripped out attributes */
691 hdr->PageType |= hdr_attr;
693 mpt_check_doorbell(mpt);
694 mpt_send_cmd(mpt, req);
699 if (++count == 1000) {
700 hdr->PageType |= hdr_attr;
701 mpt_prt(mpt, "mpt_write_cfg_page timed out");
704 } while (req->debug == REQ_ON_CHIP);
706 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
707 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
708 mpt_prt(mpt, "mpt_write_cfg_page: Config Info Status %x",
710 mpt_free_reply(mpt, (req->sequence << 1));
713 mpt_free_reply(mpt, (req->sequence << 1));
715 mpt_free_request(mpt, req);
720 * Read SCSI configuration information
723 mpt_read_config_info_spi(mpt_softc_t *mpt)
727 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0,
728 0, &mpt->mpt_port_page0.Header);
732 if (mpt->verbose > 1) {
733 mpt_prt(mpt, "SPI Port Page 0 Header: %x %x %x %x",
734 mpt->mpt_port_page0.Header.PageVersion,
735 mpt->mpt_port_page0.Header.PageLength,
736 mpt->mpt_port_page0.Header.PageNumber,
737 mpt->mpt_port_page0.Header.PageType);
740 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1,
741 0, &mpt->mpt_port_page1.Header);
745 if (mpt->verbose > 1) {
746 mpt_prt(mpt, "SPI Port Page 1 Header: %x %x %x %x",
747 mpt->mpt_port_page1.Header.PageVersion,
748 mpt->mpt_port_page1.Header.PageLength,
749 mpt->mpt_port_page1.Header.PageNumber,
750 mpt->mpt_port_page1.Header.PageType);
753 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2,
754 0, &mpt->mpt_port_page2.Header);
759 if (mpt->verbose > 1) {
760 mpt_prt(mpt, "SPI Port Page 2 Header: %x %x %x %x",
761 mpt->mpt_port_page1.Header.PageVersion,
762 mpt->mpt_port_page1.Header.PageLength,
763 mpt->mpt_port_page1.Header.PageNumber,
764 mpt->mpt_port_page1.Header.PageType);
767 for (i = 0; i < 16; i++) {
768 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
769 0, i, &mpt->mpt_dev_page0[i].Header);
773 if (mpt->verbose > 1) {
775 "SPI Target %d Device Page 0 Header: %x %x %x %x",
776 i, mpt->mpt_dev_page0[i].Header.PageVersion,
777 mpt->mpt_dev_page0[i].Header.PageLength,
778 mpt->mpt_dev_page0[i].Header.PageNumber,
779 mpt->mpt_dev_page0[i].Header.PageType);
782 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
783 1, i, &mpt->mpt_dev_page1[i].Header);
787 if (mpt->verbose > 1) {
789 "SPI Target %d Device Page 1 Header: %x %x %x %x",
790 i, mpt->mpt_dev_page1[i].Header.PageVersion,
791 mpt->mpt_dev_page1[i].Header.PageLength,
792 mpt->mpt_dev_page1[i].Header.PageNumber,
793 mpt->mpt_dev_page1[i].Header.PageType);
798 * At this point, we don't *have* to fail. As long as we have
799 * valid config header information, we can (barely) lurch
803 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page0.Header);
805 mpt_prt(mpt, "failed to read SPI Port Page 0");
806 } else if (mpt->verbose > 1) {
808 "SPI Port Page 0: Capabilities %x PhysicalInterface %x",
809 mpt->mpt_port_page0.Capabilities,
810 mpt->mpt_port_page0.PhysicalInterface);
813 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header);
815 mpt_prt(mpt, "failed to read SPI Port Page 1");
816 } else if (mpt->verbose > 1) {
818 "SPI Port Page 1: Configuration %x OnBusTimerValue %x",
819 mpt->mpt_port_page1.Configuration,
820 mpt->mpt_port_page1.OnBusTimerValue);
823 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header);
825 mpt_prt(mpt, "failed to read SPI Port Page 2");
826 } else if (mpt->verbose > 1) {
828 "SPI Port Page 2: Flags %x Settings %x",
829 mpt->mpt_port_page2.PortFlags,
830 mpt->mpt_port_page2.PortSettings);
831 for (i = 0; i < 16; i++) {
833 "SPI Port Page 2 Tgt %d: timo %x SF %x Flags %x",
834 i, mpt->mpt_port_page2.DeviceSettings[i].Timeout,
835 mpt->mpt_port_page2.DeviceSettings[i].SyncFactor,
836 mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags);
840 for (i = 0; i < 16; i++) {
841 rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page0[i].Header);
843 mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 0", i);
846 if (mpt->verbose > 1) {
848 "SPI Tgt %d Page 0: NParms %x Information %x",
849 i, mpt->mpt_dev_page0[i].NegotiatedParameters,
850 mpt->mpt_dev_page0[i].Information);
852 rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page1[i].Header);
854 mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 1", i);
857 if (mpt->verbose > 1) {
859 "SPI Tgt %d Page 1: RParms %x Configuration %x",
860 i, mpt->mpt_dev_page1[i].RequestedParameters,
861 mpt->mpt_dev_page1[i].Configuration);
868 * Validate SPI configuration information.
870 * In particular, validate SPI Port Page 1.
873 mpt_set_initial_config_spi(mpt_softc_t *mpt)
875 int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id;
877 mpt->mpt_disc_enable = 0xff;
878 mpt->mpt_tag_enable = 0;
880 if (mpt->mpt_port_page1.Configuration != pp1val) {
881 CONFIG_PAGE_SCSI_PORT_1 tmp;
883 "SPI Port Page 1 Config value bad (%x)- should be %x",
884 mpt->mpt_port_page1.Configuration, pp1val);
885 tmp = mpt->mpt_port_page1;
886 tmp.Configuration = pp1val;
887 if (mpt_write_cfg_page(mpt, 0, &tmp.Header)) {
890 if (mpt_read_cfg_page(mpt, 0, &tmp.Header)) {
893 if (tmp.Configuration != pp1val) {
895 "failed to reset SPI Port Page 1 Config value");
898 mpt->mpt_port_page1 = tmp;
901 for (i = 0; i < 16; i++) {
902 CONFIG_PAGE_SCSI_DEVICE_1 tmp;
903 tmp = mpt->mpt_dev_page1[i];
904 tmp.RequestedParameters = 0;
905 tmp.Configuration = 0;
906 if (mpt->verbose > 1) {
908 "Set Tgt %d SPI DevicePage 1 values to %x 0 %x",
909 i, tmp.RequestedParameters, tmp.Configuration);
911 if (mpt_write_cfg_page(mpt, i, &tmp.Header)) {
914 if (mpt_read_cfg_page(mpt, i, &tmp.Header)) {
917 mpt->mpt_dev_page1[i] = tmp;
918 if (mpt->verbose > 1) {
920 "SPI Tgt %d Page 1: RParm %x Configuration %x", i,
921 mpt->mpt_dev_page1[i].RequestedParameters,
922 mpt->mpt_dev_page1[i].Configuration);
932 mpt_send_port_enable(mpt_softc_t *mpt, int port)
936 MSG_PORT_ENABLE *enable_req;
938 req = mpt_get_request(mpt);
940 enable_req = req->req_vbuf;
941 bzero(enable_req, sizeof *enable_req);
943 enable_req->Function = MPI_FUNCTION_PORT_ENABLE;
944 enable_req->MsgContext = req->index | 0x80000000;
945 enable_req->PortNumber = port;
947 mpt_check_doorbell(mpt);
948 if (mpt->verbose > 1) {
949 mpt_prt(mpt, "enabling port %d", port);
951 mpt_send_cmd(mpt, req);
957 if (++count == 100000) {
958 mpt_prt(mpt, "port enable timed out");
961 } while (req->debug == REQ_ON_CHIP);
962 mpt_free_request(mpt, req);
967 * Enable/Disable asynchronous event reporting.
969 * NB: this is the first command we send via shared memory
970 * instead of the handshake register.
973 mpt_send_event_request(mpt_softc_t *mpt, int onoff)
976 MSG_EVENT_NOTIFY *enable_req;
978 req = mpt_get_request(mpt);
980 enable_req = req->req_vbuf;
981 bzero(enable_req, sizeof *enable_req);
983 enable_req->Function = MPI_FUNCTION_EVENT_NOTIFICATION;
984 enable_req->MsgContext = req->index | 0x80000000;
985 enable_req->Switch = onoff;
987 mpt_check_doorbell(mpt);
988 if (mpt->verbose > 1) {
989 mpt_prt(mpt, "%sabling async events", onoff? "en" : "dis");
991 mpt_send_cmd(mpt, req);
997 * Un-mask the interupts on the chip.
1000 mpt_enable_ints(mpt_softc_t *mpt)
1002 /* Unmask every thing except door bell int */
1003 mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK);
1007 * Mask the interupts on the chip.
1010 mpt_disable_ints(mpt_softc_t *mpt)
1012 /* Mask all interrupts */
1013 mpt_write(mpt, MPT_OFFSET_INTR_MASK,
1014 MPT_INTR_REPLY_MASK | MPT_INTR_DB_MASK);
1017 /* (Re)Initialize the chip for use */
1019 mpt_init(mpt_softc_t *mpt, u_int32_t who)
1022 MSG_IOC_FACTS_REPLY facts;
1023 MSG_PORT_FACTS_REPLY pfp;
1027 /* Put all request buffers (back) on the free list */
1028 SLIST_INIT(&mpt->request_free_list);
1029 for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
1030 mpt_free_request(mpt, &mpt->request_pool[val]);
1033 if (mpt->verbose > 1) {
1034 mpt_prt(mpt, "doorbell req = %s",
1035 mpt_ioc_diag(mpt_read(mpt, MPT_OFFSET_DOORBELL)));
1039 * Start by making sure we're not at FAULT or RESET state
1041 switch (mpt_rd_db(mpt) & MPT_DB_STATE_MASK) {
1042 case MPT_DB_STATE_RESET:
1043 case MPT_DB_STATE_FAULT:
1044 if (mpt_reset(mpt) != MPT_OK) {
1051 for (try = 0; try < MPT_MAX_TRYS; try++) {
1053 * No need to reset if the IOC is already in the READY state.
1055 * Force reset if initialization failed previously.
1056 * Note that a hard_reset of the second channel of a '929
1057 * will stop operation of the first channel. Hopefully, if the
1058 * first channel is ok, the second will not require a hard
1061 if ((mpt_rd_db(mpt) & MPT_DB_STATE_MASK) !=
1062 MPT_DB_STATE_READY) {
1063 if (mpt_reset(mpt) != MPT_OK) {
1069 if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) {
1070 mpt_prt(mpt, "mpt_get_iocfacts failed");
1074 if (mpt->verbose > 1) {
1076 "IOCFACTS: GlobalCredits=%d BlockSize=%u "
1077 "Request Frame Size %u\n", facts.GlobalCredits,
1078 facts.BlockSize, facts.RequestFrameSize);
1080 mpt->mpt_global_credits = facts.GlobalCredits;
1081 mpt->request_frame_size = facts.RequestFrameSize;
1083 if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) {
1084 mpt_prt(mpt, "mpt_get_portfacts failed");
1088 if (mpt->verbose > 1) {
1090 "PORTFACTS: Type %x PFlags %x IID %d MaxDev %d\n",
1091 pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID,
1095 if (pfp.PortType != MPI_PORTFACTS_PORTTYPE_SCSI &&
1096 pfp.PortType != MPI_PORTFACTS_PORTTYPE_FC) {
1097 mpt_prt(mpt, "Unsupported Port Type (%x)",
1101 if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
1102 mpt_prt(mpt, "initiator role unsupported");
1105 if (pfp.PortType == MPI_PORTFACTS_PORTTYPE_FC) {
1110 mpt->mpt_ini_id = pfp.PortSCSIID;
1112 if (mpt_send_ioc_init(mpt, who) != MPT_OK) {
1113 mpt_prt(mpt, "mpt_send_ioc_init failed");
1117 if (mpt->verbose > 1) {
1118 mpt_prt(mpt, "mpt_send_ioc_init ok");
1121 if (mpt_wait_state(mpt, MPT_DB_STATE_RUNNING) != MPT_OK) {
1122 mpt_prt(mpt, "IOC failed to go to run state");
1125 if (mpt->verbose > 1) {
1126 mpt_prt(mpt, "IOC now at RUNSTATE");
1130 * Give it reply buffers
1132 * Do *not* except global credits.
1134 for (val = 0, pptr = mpt->reply_phys;
1135 (pptr + MPT_REPLY_SIZE) < (mpt->reply_phys + PAGE_SIZE);
1136 pptr += MPT_REPLY_SIZE) {
1137 mpt_free_reply(mpt, pptr);
1138 if (++val == mpt->mpt_global_credits - 1)
1143 * Enable asynchronous event reporting
1145 mpt_send_event_request(mpt, 1);
1149 * Read set up initial configuration information
1150 * (SPI only for now)
1153 if (mpt->is_fc == 0) {
1154 if (mpt_read_config_info_spi(mpt)) {
1157 if (mpt_set_initial_config_spi(mpt)) {
1163 * Now enable the port
1165 if (mpt_send_port_enable(mpt, 0) != MPT_OK) {
1166 mpt_prt(mpt, "failed to enable port 0");
1170 if (mpt->verbose > 1) {
1171 mpt_prt(mpt, "enabled port 0");
1174 /* Everything worked */
1178 if (try >= MPT_MAX_TRYS) {
1179 mpt_prt(mpt, "failed to initialize IOC");
1183 if (mpt->verbose > 1) {
1184 mpt_prt(mpt, "enabling interrupts");
1187 mpt_enable_ints(mpt);