xref: /netbsd/sys/dev/ic/mpt.c (revision 3cdf3367)
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