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