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