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