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