1 /* $NetBSD: mlx.c,v 1.46 2006/10/12 01:31:01 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /*- 40 * Copyright (c) 1999 Michael Smith 41 * All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 * 64 * from FreeBSD: mlx.c,v 1.14.2.3 2000/08/04 06:52:50 msmith Exp 65 */ 66 67 /* 68 * Driver for the Mylex DAC960 family of RAID controllers. 69 * 70 * TODO: 71 * 72 * o Test and enable channel pause. 73 * o SCSI pass-through. 74 */ 75 76 #include <sys/cdefs.h> 77 __KERNEL_RCSID(0, "$NetBSD: mlx.c,v 1.46 2006/10/12 01:31:01 christos Exp $"); 78 79 #include "ld.h" 80 81 #include <sys/param.h> 82 #include <sys/systm.h> 83 #include <sys/kernel.h> 84 #include <sys/device.h> 85 #include <sys/queue.h> 86 #include <sys/proc.h> 87 #include <sys/buf.h> 88 #include <sys/bufq.h> 89 #include <sys/endian.h> 90 #include <sys/malloc.h> 91 #include <sys/conf.h> 92 #include <sys/kthread.h> 93 #include <sys/disk.h> 94 95 #include <machine/vmparam.h> 96 #include <machine/bus.h> 97 98 #include <uvm/uvm_extern.h> 99 100 #include <dev/ldvar.h> 101 102 #include <dev/ic/mlxreg.h> 103 #include <dev/ic/mlxio.h> 104 #include <dev/ic/mlxvar.h> 105 106 #include "locators.h" 107 108 #define MLX_TIMEOUT 60 109 110 #ifdef DIAGNOSTIC 111 #define DPRINTF(x) printf x 112 #else 113 #define DPRINTF(x) 114 #endif 115 116 static void mlx_adjqparam(struct mlx_softc *, int, int); 117 static int mlx_ccb_submit(struct mlx_softc *, struct mlx_ccb *); 118 static int mlx_check(struct mlx_softc *, int); 119 static void mlx_configure(struct mlx_softc *, int); 120 static void mlx_describe(struct mlx_softc *); 121 static void *mlx_enquire(struct mlx_softc *, int, size_t, 122 void (*)(struct mlx_ccb *), int); 123 static int mlx_fw_message(struct mlx_softc *, int, int, int); 124 static void mlx_pause_action(struct mlx_softc *); 125 static void mlx_pause_done(struct mlx_ccb *); 126 static void mlx_periodic(struct mlx_softc *); 127 static void mlx_periodic_create(void *); 128 static void mlx_periodic_enquiry(struct mlx_ccb *); 129 static void mlx_periodic_eventlog_poll(struct mlx_softc *); 130 static void mlx_periodic_eventlog_respond(struct mlx_ccb *); 131 static void mlx_periodic_rebuild(struct mlx_ccb *); 132 static void mlx_periodic_thread(void *); 133 static int mlx_print(void *, const char *); 134 static int mlx_rebuild(struct mlx_softc *, int, int); 135 static void mlx_shutdown(void *); 136 static int mlx_user_command(struct mlx_softc *, struct mlx_usercommand *); 137 138 dev_type_open(mlxopen); 139 dev_type_close(mlxclose); 140 dev_type_ioctl(mlxioctl); 141 142 const struct cdevsw mlx_cdevsw = { 143 mlxopen, mlxclose, noread, nowrite, mlxioctl, 144 nostop, notty, nopoll, nommap, nokqfilter, D_OTHER, 145 }; 146 147 extern struct cfdriver mlx_cd; 148 static struct proc *mlx_periodic_proc; 149 static void *mlx_sdh; 150 151 static struct { 152 int hwid; 153 const char *name; 154 } const mlx_cname[] = { 155 { 0x00, "960E/960M" }, 156 { 0x01, "960P/PD" }, 157 { 0x02, "960PL" }, 158 { 0x10, "960PG" }, 159 { 0x11, "960PJ" }, 160 { 0x12, "960PR" }, 161 { 0x13, "960PT" }, 162 { 0x14, "960PTL0" }, 163 { 0x15, "960PRL" }, 164 { 0x16, "960PTL1" }, 165 { 0x20, "1164PVX" }, 166 }; 167 168 static const char * const mlx_sense_msgs[] = { 169 "because write recovery failed", 170 "because of SCSI bus reset failure", 171 "because of double check condition", 172 "because it was removed", 173 "because of gross error on SCSI chip", 174 "because of bad tag returned from drive", 175 "because of timeout on SCSI command", 176 "because of reset SCSI command issued from system", 177 "because busy or parity error count exceeded limit", 178 "because of 'kill drive' command from system", 179 "because of selection timeout", 180 "due to SCSI phase sequence error", 181 "due to unknown status" 182 }; 183 184 static const char * const mlx_status_msgs[] = { 185 "normal completion", /* 0 */ 186 "irrecoverable data error", /* 1 */ 187 "drive does not exist, or is offline", /* 2 */ 188 "attempt to write beyond end of drive", /* 3 */ 189 "bad data encountered", /* 4 */ 190 "invalid log entry request", /* 5 */ 191 "attempt to rebuild online drive", /* 6 */ 192 "new disk failed during rebuild", /* 7 */ 193 "invalid channel/target", /* 8 */ 194 "rebuild/check already in progress", /* 9 */ 195 "one or more disks are dead", /* 10 */ 196 "invalid or non-redundant drive", /* 11 */ 197 "channel is busy", /* 12 */ 198 "channel is not stopped", /* 13 */ 199 "rebuild successfully terminated", /* 14 */ 200 "unsupported command", /* 15 */ 201 "check condition received", /* 16 */ 202 "device is busy", /* 17 */ 203 "selection or command timeout", /* 18 */ 204 "command terminated abnormally", /* 19 */ 205 "controller wedged", /* 20 */ 206 "software timeout", /* 21 */ 207 "command busy (?)", /* 22 */ 208 }; 209 210 static struct { 211 u_char command; 212 u_char msg; /* Index into mlx_status_msgs[]. */ 213 u_short status; 214 } const mlx_msgs[] = { 215 { MLX_CMD_READSG, 1, 0x0001 }, 216 { MLX_CMD_READSG, 1, 0x0002 }, 217 { MLX_CMD_READSG, 3, 0x0105 }, 218 { MLX_CMD_READSG, 4, 0x010c }, 219 { MLX_CMD_WRITESG, 1, 0x0001 }, 220 { MLX_CMD_WRITESG, 1, 0x0002 }, 221 { MLX_CMD_WRITESG, 3, 0x0105 }, 222 { MLX_CMD_READSG_OLD, 1, 0x0001 }, 223 { MLX_CMD_READSG_OLD, 1, 0x0002 }, 224 { MLX_CMD_READSG_OLD, 3, 0x0105 }, 225 { MLX_CMD_WRITESG_OLD, 1, 0x0001 }, 226 { MLX_CMD_WRITESG_OLD, 1, 0x0002 }, 227 { MLX_CMD_WRITESG_OLD, 3, 0x0105 }, 228 { MLX_CMD_LOGOP, 5, 0x0105 }, 229 { MLX_CMD_REBUILDASYNC, 6, 0x0002 }, 230 { MLX_CMD_REBUILDASYNC, 7, 0x0004 }, 231 { MLX_CMD_REBUILDASYNC, 8, 0x0105 }, 232 { MLX_CMD_REBUILDASYNC, 9, 0x0106 }, 233 { MLX_CMD_REBUILDASYNC, 14, 0x0107 }, 234 { MLX_CMD_CHECKASYNC, 10, 0x0002 }, 235 { MLX_CMD_CHECKASYNC, 11, 0x0105 }, 236 { MLX_CMD_CHECKASYNC, 9, 0x0106 }, 237 { MLX_CMD_STOPCHANNEL, 12, 0x0106 }, 238 { MLX_CMD_STOPCHANNEL, 8, 0x0105 }, 239 { MLX_CMD_STARTCHANNEL, 13, 0x0005 }, 240 { MLX_CMD_STARTCHANNEL, 8, 0x0105 }, 241 { MLX_CMD_DIRECT_CDB, 16, 0x0002 }, 242 { MLX_CMD_DIRECT_CDB, 17, 0x0008 }, 243 { MLX_CMD_DIRECT_CDB, 18, 0x000e }, 244 { MLX_CMD_DIRECT_CDB, 19, 0x000f }, 245 { MLX_CMD_DIRECT_CDB, 8, 0x0105 }, 246 247 { 0, 20, MLX_STATUS_WEDGED }, 248 { 0, 21, MLX_STATUS_LOST }, 249 { 0, 22, MLX_STATUS_BUSY }, 250 251 { 0, 14, 0x0104 }, 252 }; 253 254 /* 255 * Initialise the controller and our interface. 256 */ 257 void 258 mlx_init(struct mlx_softc *mlx, const char *intrstr) 259 { 260 struct mlx_ccb *mc; 261 struct mlx_enquiry_old *meo; 262 struct mlx_enquiry2 *me2; 263 struct mlx_cinfo *ci; 264 int rv, fwminor, hscode, hserr, hsparam1, hsparam2, hsmsg; 265 int size, i, rseg; 266 const char *wantfwstr; 267 bus_dma_segment_t seg; 268 269 SIMPLEQ_INIT(&mlx->mlx_ccb_queue); 270 SLIST_INIT(&mlx->mlx_ccb_freelist); 271 TAILQ_INIT(&mlx->mlx_ccb_worklist); 272 273 if (intrstr != NULL) 274 printf("%s: interrupting at %s\n", mlx->mlx_dv.dv_xname, 275 intrstr); 276 277 /* 278 * Allocate the scatter/gather lists. 279 */ 280 size = MLX_SGL_SIZE * MLX_MAX_QUEUECNT; 281 282 if ((rv = bus_dmamem_alloc(mlx->mlx_dmat, size, PAGE_SIZE, 0, &seg, 1, 283 &rseg, BUS_DMA_NOWAIT)) != 0) { 284 printf("%s: unable to allocate sglists, rv = %d\n", 285 mlx->mlx_dv.dv_xname, rv); 286 return; 287 } 288 289 if ((rv = bus_dmamem_map(mlx->mlx_dmat, &seg, rseg, size, 290 (caddr_t *)&mlx->mlx_sgls, 291 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { 292 printf("%s: unable to map sglists, rv = %d\n", 293 mlx->mlx_dv.dv_xname, rv); 294 return; 295 } 296 297 if ((rv = bus_dmamap_create(mlx->mlx_dmat, size, 1, size, 0, 298 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mlx->mlx_dmamap)) != 0) { 299 printf("%s: unable to create sglist DMA map, rv = %d\n", 300 mlx->mlx_dv.dv_xname, rv); 301 return; 302 } 303 304 if ((rv = bus_dmamap_load(mlx->mlx_dmat, mlx->mlx_dmamap, 305 mlx->mlx_sgls, size, NULL, BUS_DMA_NOWAIT)) != 0) { 306 printf("%s: unable to load sglist DMA map, rv = %d\n", 307 mlx->mlx_dv.dv_xname, rv); 308 return; 309 } 310 311 mlx->mlx_sgls_paddr = mlx->mlx_dmamap->dm_segs[0].ds_addr; 312 memset(mlx->mlx_sgls, 0, size); 313 314 /* 315 * Allocate and initialize the CCBs. 316 */ 317 mc = malloc(sizeof(*mc) * MLX_MAX_QUEUECNT, M_DEVBUF, M_NOWAIT); 318 mlx->mlx_ccbs = mc; 319 320 for (i = 0; i < MLX_MAX_QUEUECNT; i++, mc++) { 321 mc->mc_ident = i; 322 rv = bus_dmamap_create(mlx->mlx_dmat, MLX_MAX_XFER, 323 MLX_MAX_SEGS, MLX_MAX_XFER, 0, 324 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 325 &mc->mc_xfer_map); 326 if (rv != 0) 327 break; 328 mlx->mlx_nccbs++; 329 mlx_ccb_free(mlx, mc); 330 } 331 if (mlx->mlx_nccbs != MLX_MAX_QUEUECNT) 332 printf("%s: %d/%d CCBs usable\n", mlx->mlx_dv.dv_xname, 333 mlx->mlx_nccbs, MLX_MAX_QUEUECNT); 334 335 /* Disable interrupts before we start talking to the controller */ 336 (*mlx->mlx_intaction)(mlx, 0); 337 338 /* If we've got a reset routine, then reset the controller now. */ 339 if (mlx->mlx_reset != NULL) { 340 printf("%s: resetting controller...\n", mlx->mlx_dv.dv_xname); 341 if ((*mlx->mlx_reset)(mlx) != 0) { 342 printf("%s: reset failed\n", mlx->mlx_dv.dv_xname); 343 return; 344 } 345 } 346 347 /* 348 * Wait for the controller to come ready, handshaking with the 349 * firmware if required. This is typically only necessary on 350 * platforms where the controller BIOS does not run. 351 */ 352 hsmsg = 0; 353 354 for (;;) { 355 hscode = (*mlx->mlx_fw_handshake)(mlx, &hserr, &hsparam1, 356 &hsparam2); 357 if (hscode == 0) { 358 if (hsmsg != 0) 359 printf("%s: initialization complete\n", 360 mlx->mlx_dv.dv_xname); 361 break; 362 } 363 364 /* Report first time around... */ 365 if (hsmsg == 0) { 366 printf("%s: initializing (may take some time)...\n", 367 mlx->mlx_dv.dv_xname); 368 hsmsg = 1; 369 } 370 371 /* Did we get a real message? */ 372 if (hscode == 2) { 373 hscode = mlx_fw_message(mlx, hserr, hsparam1, hsparam2); 374 375 /* Fatal initialisation error? */ 376 if (hscode != 0) 377 return; 378 } 379 } 380 381 /* 382 * Do quirk/feature related things. 383 */ 384 ci = &mlx->mlx_ci; 385 386 if (ci->ci_iftype > 1) { 387 me2 = mlx_enquire(mlx, MLX_CMD_ENQUIRY2, 388 sizeof(struct mlx_enquiry2), NULL, 0); 389 if (me2 == NULL) { 390 printf("%s: ENQUIRY2 failed\n", mlx->mlx_dv.dv_xname); 391 return; 392 } 393 394 ci->ci_firmware_id[0] = me2->me_firmware_id[0]; 395 ci->ci_firmware_id[1] = me2->me_firmware_id[1]; 396 ci->ci_firmware_id[2] = me2->me_firmware_id[2]; 397 ci->ci_firmware_id[3] = me2->me_firmware_id[3]; 398 ci->ci_hardware_id = me2->me_hardware_id[0]; 399 ci->ci_mem_size = le32toh(me2->me_mem_size); 400 ci->ci_max_sg = le16toh(me2->me_max_sg); 401 ci->ci_max_commands = le16toh(me2->me_max_commands); 402 ci->ci_nchan = me2->me_actual_channels; 403 404 free(me2, M_DEVBUF); 405 } 406 407 if (ci->ci_iftype <= 2) { 408 /* 409 * These controllers may not report the firmware version in 410 * the ENQUIRY2 response, or may not even support it. 411 */ 412 meo = mlx_enquire(mlx, MLX_CMD_ENQUIRY_OLD, 413 sizeof(struct mlx_enquiry_old), NULL, 0); 414 if (meo == NULL) { 415 printf("%s: ENQUIRY_OLD failed\n", mlx->mlx_dv.dv_xname); 416 return; 417 } 418 ci->ci_firmware_id[0] = meo->me_fwmajor; 419 ci->ci_firmware_id[1] = meo->me_fwminor; 420 ci->ci_firmware_id[2] = 0; 421 ci->ci_firmware_id[3] = '0'; 422 423 if (ci->ci_iftype == 1) { 424 ci->ci_hardware_id = 0; /* XXX */ 425 ci->ci_mem_size = 0; /* XXX */ 426 ci->ci_max_sg = 17; /* XXX */ 427 ci->ci_max_commands = meo->me_max_commands; 428 } 429 430 free(meo, M_DEVBUF); 431 } 432 433 wantfwstr = NULL; 434 fwminor = ci->ci_firmware_id[1]; 435 436 switch (ci->ci_firmware_id[0]) { 437 case 2: 438 if (ci->ci_iftype == 1) { 439 if (fwminor < 14) 440 wantfwstr = "2.14"; 441 } else if (fwminor < 42) 442 wantfwstr = "2.42"; 443 break; 444 445 case 3: 446 if (fwminor < 51) 447 wantfwstr = "3.51"; 448 break; 449 450 case 4: 451 if (fwminor < 6) 452 wantfwstr = "4.06"; 453 break; 454 455 case 5: 456 if (fwminor < 7) 457 wantfwstr = "5.07"; 458 break; 459 } 460 461 /* Print a little information about the controller. */ 462 mlx_describe(mlx); 463 464 if (wantfwstr != NULL) { 465 printf("%s: WARNING: this f/w revision is not recommended\n", 466 mlx->mlx_dv.dv_xname); 467 printf("%s: WARNING: use revision %s or later\n", 468 mlx->mlx_dv.dv_xname, wantfwstr); 469 } 470 471 /* We don't (yet) know where the event log is up to. */ 472 mlx->mlx_currevent = -1; 473 474 /* No user-requested background operation is in progress. */ 475 mlx->mlx_bg = 0; 476 mlx->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE; 477 478 /* Set maximum number of queued commands for `regular' operations. */ 479 mlx->mlx_max_queuecnt = 480 min(ci->ci_max_commands, MLX_MAX_QUEUECNT) - 481 MLX_NCCBS_CONTROL; 482 #ifdef DIAGNOSTIC 483 if (mlx->mlx_max_queuecnt < MLX_NCCBS_CONTROL + MLX_MAX_DRIVES) 484 printf("%s: WARNING: few CCBs available\n", 485 mlx->mlx_dv.dv_xname); 486 if (ci->ci_max_sg < MLX_MAX_SEGS) { 487 printf("%s: oops, not enough S/G segments\n", 488 mlx->mlx_dv.dv_xname); 489 return; 490 } 491 #endif 492 493 if (mlx_sdh == NULL) { 494 /* 495 * Set our `shutdownhook' before we start any device 496 * activity. 497 */ 498 mlx_sdh = shutdownhook_establish(mlx_shutdown, NULL); 499 500 /* Arrange to create a status monitoring thread. */ 501 kthread_create(mlx_periodic_create, NULL); 502 } 503 504 /* Finally, attach child devices and enable interrupts. */ 505 mlx_configure(mlx, 0); 506 (*mlx->mlx_intaction)(mlx, 1); 507 508 mlx->mlx_flags |= MLXF_INITOK; 509 } 510 511 /* 512 * Tell the world about the controller. 513 */ 514 static void 515 mlx_describe(struct mlx_softc *mlx) 516 { 517 struct mlx_cinfo *ci; 518 static char tbuf[80]; 519 const char *model; 520 int i; 521 522 model = NULL; 523 ci = &mlx->mlx_ci; 524 525 for (i = 0; i < sizeof(mlx_cname) / sizeof(mlx_cname[0]); i++) 526 if (ci->ci_hardware_id == mlx_cname[i].hwid) { 527 model = mlx_cname[i].name; 528 break; 529 } 530 531 if (model == NULL) { 532 snprintf(tbuf, sizeof(tbuf), " model 0x%x", ci->ci_hardware_id); 533 model = tbuf; 534 } 535 536 printf("%s: DAC%s, %d channel%s, firmware %d.%02d-%c-%02d", 537 mlx->mlx_dv.dv_xname, model, ci->ci_nchan, 538 ci->ci_nchan > 1 ? "s" : "", 539 ci->ci_firmware_id[0], ci->ci_firmware_id[1], 540 ci->ci_firmware_id[3], ci->ci_firmware_id[2]); 541 if (ci->ci_mem_size != 0) 542 printf(", %dMB RAM", ci->ci_mem_size >> 20); 543 printf("\n"); 544 } 545 546 /* 547 * Locate disk resources and attach children to them. 548 */ 549 static void 550 mlx_configure(struct mlx_softc *mlx, int waitok) 551 { 552 struct mlx_enquiry *me; 553 struct mlx_enquiry_old *meo; 554 struct mlx_enq_sys_drive *mes; 555 struct mlx_sysdrive *ms; 556 struct mlx_attach_args mlxa; 557 int i, nunits; 558 u_int size; 559 int locs[MLXCF_NLOCS]; 560 561 mlx->mlx_flags |= MLXF_RESCANNING; 562 563 if (mlx->mlx_ci.ci_iftype <= 2) { 564 meo = mlx_enquire(mlx, MLX_CMD_ENQUIRY_OLD, 565 sizeof(struct mlx_enquiry_old), NULL, waitok); 566 if (meo == NULL) { 567 printf("%s: ENQUIRY_OLD failed\n", 568 mlx->mlx_dv.dv_xname); 569 goto out; 570 } 571 mlx->mlx_numsysdrives = meo->me_num_sys_drvs; 572 free(meo, M_DEVBUF); 573 } else { 574 me = mlx_enquire(mlx, MLX_CMD_ENQUIRY, 575 sizeof(struct mlx_enquiry), NULL, waitok); 576 if (me == NULL) { 577 printf("%s: ENQUIRY failed\n", mlx->mlx_dv.dv_xname); 578 goto out; 579 } 580 mlx->mlx_numsysdrives = me->me_num_sys_drvs; 581 free(me, M_DEVBUF); 582 } 583 584 mes = mlx_enquire(mlx, MLX_CMD_ENQSYSDRIVE, 585 sizeof(*mes) * MLX_MAX_DRIVES, NULL, waitok); 586 if (mes == NULL) { 587 printf("%s: error fetching drive status\n", 588 mlx->mlx_dv.dv_xname); 589 goto out; 590 } 591 592 /* Allow 1 queued command per unit while re-configuring. */ 593 mlx_adjqparam(mlx, 1, 0); 594 595 ms = &mlx->mlx_sysdrive[0]; 596 nunits = 0; 597 for (i = 0; i < MLX_MAX_DRIVES; i++, ms++) { 598 size = le32toh(mes[i].sd_size); 599 ms->ms_state = mes[i].sd_state; 600 601 /* 602 * If an existing device has changed in some way (e.g. no 603 * longer present) then detach it. 604 */ 605 if (ms->ms_dv != NULL && (size != ms->ms_size || 606 (mes[i].sd_raidlevel & 0xf) != ms->ms_raidlevel)) 607 config_detach(ms->ms_dv, DETACH_FORCE); 608 609 ms->ms_size = size; 610 ms->ms_raidlevel = mes[i].sd_raidlevel & 0xf; 611 ms->ms_state = mes[i].sd_state; 612 ms->ms_dv = NULL; 613 614 if (i >= mlx->mlx_numsysdrives) 615 continue; 616 if (size == 0xffffffffU || size == 0) 617 continue; 618 619 /* 620 * Attach a new device. 621 */ 622 mlxa.mlxa_unit = i; 623 624 locs[MLXCF_UNIT] = i; 625 626 ms->ms_dv = config_found_sm_loc(&mlx->mlx_dv, "mlx", locs, 627 &mlxa, mlx_print, config_stdsubmatch); 628 nunits += (ms->ms_dv != NULL); 629 } 630 631 free(mes, M_DEVBUF); 632 633 if (nunits != 0) 634 mlx_adjqparam(mlx, mlx->mlx_max_queuecnt / nunits, 635 mlx->mlx_max_queuecnt % nunits); 636 out: 637 mlx->mlx_flags &= ~MLXF_RESCANNING; 638 } 639 640 /* 641 * Print autoconfiguration message for a sub-device. 642 */ 643 static int 644 mlx_print(void *aux, const char *pnp) 645 { 646 struct mlx_attach_args *mlxa; 647 648 mlxa = (struct mlx_attach_args *)aux; 649 650 if (pnp != NULL) 651 aprint_normal("block device at %s", pnp); 652 aprint_normal(" unit %d", mlxa->mlxa_unit); 653 return (UNCONF); 654 } 655 656 /* 657 * Shut down all configured `mlx' devices. 658 */ 659 static void 660 mlx_shutdown(void *cookie __unused) 661 { 662 struct mlx_softc *mlx; 663 int i; 664 665 for (i = 0; i < mlx_cd.cd_ndevs; i++) 666 if ((mlx = device_lookup(&mlx_cd, i)) != NULL) 667 mlx_flush(mlx, 0); 668 } 669 670 /* 671 * Adjust queue parameters for all child devices. 672 */ 673 static void 674 mlx_adjqparam(struct mlx_softc *mlx, int mpu, int slop) 675 { 676 #if NLD > 0 677 extern struct cfdriver ld_cd; 678 struct ld_softc *ld; 679 int i; 680 681 for (i = 0; i < ld_cd.cd_ndevs; i++) { 682 if ((ld = device_lookup(&ld_cd, i)) == NULL) 683 continue; 684 if (device_parent(&ld->sc_dv) != &mlx->mlx_dv) 685 continue; 686 ldadjqparam(ld, mpu + (slop-- > 0)); 687 } 688 #endif 689 } 690 691 /* 692 * Accept an open operation on the control device. 693 */ 694 int 695 mlxopen(dev_t dev, int flag __unused, int mode __unused, struct lwp *l __unused) 696 { 697 struct mlx_softc *mlx; 698 699 if ((mlx = device_lookup(&mlx_cd, minor(dev))) == NULL) 700 return (ENXIO); 701 if ((mlx->mlx_flags & MLXF_INITOK) == 0) 702 return (ENXIO); 703 if ((mlx->mlx_flags & MLXF_OPEN) != 0) 704 return (EBUSY); 705 706 mlx->mlx_flags |= MLXF_OPEN; 707 return (0); 708 } 709 710 /* 711 * Accept the last close on the control device. 712 */ 713 int 714 mlxclose(dev_t dev, int flag __unused, int mode __unused, 715 struct lwp *l __unused) 716 { 717 struct mlx_softc *mlx; 718 719 mlx = device_lookup(&mlx_cd, minor(dev)); 720 mlx->mlx_flags &= ~MLXF_OPEN; 721 return (0); 722 } 723 724 /* 725 * Handle control operations. 726 */ 727 int 728 mlxioctl(dev_t dev, u_long cmd, caddr_t data, int flag __unused, 729 struct lwp *l __unused) 730 { 731 struct mlx_softc *mlx; 732 struct mlx_rebuild_request *rb; 733 struct mlx_rebuild_status *rs; 734 struct mlx_pause *mp; 735 struct mlx_sysdrive *ms; 736 int i, rv, *arg, result; 737 738 mlx = device_lookup(&mlx_cd, minor(dev)); 739 740 rb = (struct mlx_rebuild_request *)data; 741 rs = (struct mlx_rebuild_status *)data; 742 arg = (int *)data; 743 rv = 0; 744 745 switch (cmd) { 746 case MLX_RESCAN_DRIVES: 747 /* 748 * Scan the controller to see whether new drives have 749 * appeared, or old ones disappeared. 750 */ 751 mlx_configure(mlx, 1); 752 return (0); 753 754 case MLX_PAUSE_CHANNEL: 755 /* 756 * Pause one or more SCSI channels for a period of time, to 757 * assist in the process of hot-swapping devices. 758 * 759 * Note that at least the 3.51 firmware on the DAC960PL 760 * doesn't seem to do this right. 761 */ 762 if ((mlx->mlx_flags & MLXF_PAUSEWORKS) == 0) 763 return (EOPNOTSUPP); 764 765 mp = (struct mlx_pause *)data; 766 767 if ((mp->mp_which == MLX_PAUSE_CANCEL) && 768 (mlx->mlx_pause.mp_when != 0)) { 769 /* Cancel a pending pause operation. */ 770 mlx->mlx_pause.mp_which = 0; 771 break; 772 } 773 774 /* Fix for legal channels. */ 775 mp->mp_which &= ((1 << mlx->mlx_ci.ci_nchan) -1); 776 777 /* Check time values. */ 778 if (mp->mp_when < 0 || mp->mp_when > 3600 || 779 mp->mp_howlong < 1 || mp->mp_howlong > (0xf * 30)) { 780 rv = EINVAL; 781 break; 782 } 783 784 /* Check for a pause currently running. */ 785 if ((mlx->mlx_pause.mp_which != 0) && 786 (mlx->mlx_pause.mp_when == 0)) { 787 rv = EBUSY; 788 break; 789 } 790 791 /* Looks ok, go with it. */ 792 mlx->mlx_pause.mp_which = mp->mp_which; 793 mlx->mlx_pause.mp_when = time_second + mp->mp_when; 794 mlx->mlx_pause.mp_howlong = 795 mlx->mlx_pause.mp_when + mp->mp_howlong; 796 797 return (0); 798 799 case MLX_COMMAND: 800 if (securelevel >= 2) 801 return (EPERM); 802 803 /* 804 * Accept a command passthrough-style. 805 */ 806 return (mlx_user_command(mlx, (struct mlx_usercommand *)data)); 807 808 case MLX_REBUILDASYNC: 809 /* 810 * Start a rebuild on a given SCSI disk 811 */ 812 if (mlx->mlx_bg != 0) { 813 rb->rr_status = 0x0106; 814 rv = EBUSY; 815 break; 816 } 817 818 rb->rr_status = mlx_rebuild(mlx, rb->rr_channel, rb->rr_target); 819 switch (rb->rr_status) { 820 case 0: 821 rv = 0; 822 break; 823 case 0x10000: 824 rv = ENOMEM; /* Couldn't set up the command. */ 825 break; 826 case 0x0002: 827 rv = EBUSY; 828 break; 829 case 0x0104: 830 rv = EIO; 831 break; 832 case 0x0105: 833 rv = ERANGE; 834 break; 835 case 0x0106: 836 rv = EBUSY; 837 break; 838 default: 839 rv = EINVAL; 840 break; 841 } 842 843 if (rv == 0) 844 mlx->mlx_bg = MLX_BG_REBUILD; 845 846 return (0); 847 848 case MLX_REBUILDSTAT: 849 /* 850 * Get the status of the current rebuild or consistency check. 851 */ 852 *rs = mlx->mlx_rebuildstat; 853 return (0); 854 855 case MLX_GET_SYSDRIVE: 856 /* 857 * Return the system drive number matching the `ld' device 858 * unit in (arg), if it happens to belong to us. 859 */ 860 for (i = 0; i < MLX_MAX_DRIVES; i++) { 861 ms = &mlx->mlx_sysdrive[i]; 862 if (ms->ms_dv != NULL) 863 if (ms->ms_dv->dv_xname[2] == '0' + *arg) { 864 *arg = i; 865 return (0); 866 } 867 } 868 return (ENOENT); 869 870 case MLX_GET_CINFO: 871 /* 872 * Return controller info. 873 */ 874 memcpy(arg, &mlx->mlx_ci, sizeof(mlx->mlx_ci)); 875 return (0); 876 } 877 878 switch (cmd) { 879 case MLXD_DETACH: 880 case MLXD_STATUS: 881 case MLXD_CHECKASYNC: 882 if ((u_int)*arg >= MLX_MAX_DRIVES) 883 return (EINVAL); 884 ms = &mlx->mlx_sysdrive[*arg]; 885 if (*arg > MLX_MAX_DRIVES || ms->ms_dv == NULL) 886 return (ENOENT); 887 break; 888 889 default: 890 return (ENOTTY); 891 } 892 893 switch (cmd) { 894 case MLXD_DETACH: 895 /* 896 * Disconnect from the specified drive; it may be about to go 897 * away. 898 */ 899 return (config_detach(ms->ms_dv, 0)); 900 901 case MLXD_STATUS: 902 /* 903 * Return the current status of this drive. 904 */ 905 *arg = ms->ms_state; 906 return (0); 907 908 case MLXD_CHECKASYNC: 909 /* 910 * Start a background consistency check on this drive. 911 */ 912 if (mlx->mlx_bg != 0) { 913 *arg = 0x0106; 914 return (EBUSY); 915 } 916 917 switch (result = mlx_check(mlx, *arg)) { 918 case 0: 919 rv = 0; 920 break; 921 case 0x10000: 922 rv = ENOMEM; /* Couldn't set up the command. */ 923 break; 924 case 0x0002: 925 rv = EIO; 926 break; 927 case 0x0105: 928 rv = ERANGE; 929 break; 930 case 0x0106: 931 rv = EBUSY; 932 break; 933 default: 934 rv = EINVAL; 935 break; 936 } 937 938 if (rv == 0) 939 mlx->mlx_bg = MLX_BG_CHECK; 940 *arg = result; 941 return (rv); 942 } 943 944 return (ENOTTY); /* XXX shut up gcc */ 945 } 946 947 /* 948 * Fire off commands to periodically check the status of connected drives. 949 * Check for commands that have timed out. 950 */ 951 static void 952 mlx_periodic_create(void *cookie __unused) 953 { 954 int rv; 955 956 rv = kthread_create1(mlx_periodic_thread, NULL, &mlx_periodic_proc, 957 "mlxtask"); 958 if (rv == 0) 959 return; 960 961 printf("mlx_periodic_create: unable to create thread (%d)\n", rv); 962 } 963 964 static void 965 mlx_periodic_thread(void *cookie __unused) 966 { 967 struct mlx_softc *mlx; 968 int i; 969 970 for (;;) { 971 for (i = 0; i < mlx_cd.cd_ndevs; i++) 972 if ((mlx = device_lookup(&mlx_cd, i)) != NULL) 973 if (mlx->mlx_ci.ci_iftype > 1) 974 mlx_periodic(mlx); 975 976 tsleep(mlx_periodic_thread, PWAIT, "mlxzzz", hz * 2); 977 } 978 } 979 980 static void 981 mlx_periodic(struct mlx_softc *mlx) 982 { 983 struct mlx_ccb *mc, *nmc; 984 int etype, s; 985 986 if ((mlx->mlx_pause.mp_which != 0) && 987 (mlx->mlx_pause.mp_when > 0) && 988 (time_second >= mlx->mlx_pause.mp_when)) { 989 /* 990 * Start bus pause. 991 */ 992 mlx_pause_action(mlx); 993 mlx->mlx_pause.mp_when = 0; 994 } else if ((mlx->mlx_pause.mp_which != 0) && 995 (mlx->mlx_pause.mp_when == 0)) { 996 /* 997 * Stop pause if required. 998 */ 999 if (time_second >= mlx->mlx_pause.mp_howlong) { 1000 mlx_pause_action(mlx); 1001 mlx->mlx_pause.mp_which = 0; 1002 } 1003 } else if (time_second > (mlx->mlx_lastpoll + 10)) { 1004 /* 1005 * Run normal periodic activities... 1006 */ 1007 mlx->mlx_lastpoll = time_second; 1008 1009 /* 1010 * Check controller status. 1011 */ 1012 if ((mlx->mlx_flags & MLXF_PERIODIC_CTLR) == 0) { 1013 mlx->mlx_flags |= MLXF_PERIODIC_CTLR; 1014 1015 if (mlx->mlx_ci.ci_iftype <= 2) 1016 etype = MLX_CMD_ENQUIRY_OLD; 1017 else 1018 etype = MLX_CMD_ENQUIRY; 1019 1020 mlx_enquire(mlx, etype, max(sizeof(struct mlx_enquiry), 1021 sizeof(struct mlx_enquiry_old)), 1022 mlx_periodic_enquiry, 1); 1023 } 1024 1025 /* 1026 * Check system drive status. 1027 */ 1028 if ((mlx->mlx_flags & MLXF_PERIODIC_DRIVE) == 0) { 1029 mlx->mlx_flags |= MLXF_PERIODIC_DRIVE; 1030 mlx_enquire(mlx, MLX_CMD_ENQSYSDRIVE, 1031 sizeof(struct mlx_enq_sys_drive) * MLX_MAX_DRIVES, 1032 mlx_periodic_enquiry, 1); 1033 } 1034 } 1035 1036 /* 1037 * Get drive rebuild/check status. 1038 */ 1039 if ((mlx->mlx_flags & MLXF_PERIODIC_REBUILD) == 0) { 1040 mlx->mlx_flags |= MLXF_PERIODIC_REBUILD; 1041 mlx_enquire(mlx, MLX_CMD_REBUILDSTAT, 1042 sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild, 1); 1043 } 1044 1045 /* 1046 * Time-out busy CCBs. 1047 */ 1048 s = splbio(); 1049 for (mc = TAILQ_FIRST(&mlx->mlx_ccb_worklist); mc != NULL; mc = nmc) { 1050 nmc = TAILQ_NEXT(mc, mc_chain.tailq); 1051 if (mc->mc_expiry > time_second) { 1052 /* 1053 * The remaining CCBs will expire after this one, so 1054 * there's no point in going further. 1055 */ 1056 break; 1057 } 1058 TAILQ_REMOVE(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq); 1059 mc->mc_status = MLX_STATUS_LOST; 1060 if (mc->mc_mx.mx_handler != NULL) 1061 (*mc->mc_mx.mx_handler)(mc); 1062 else if ((mc->mc_flags & MC_WAITING) != 0) 1063 wakeup(mc); 1064 } 1065 splx(s); 1066 } 1067 1068 /* 1069 * Handle the result of an ENQUIRY command instigated by periodic status 1070 * polling. 1071 */ 1072 static void 1073 mlx_periodic_enquiry(struct mlx_ccb *mc) 1074 { 1075 struct mlx_softc *mlx; 1076 struct mlx_enquiry *me; 1077 struct mlx_enquiry_old *meo; 1078 struct mlx_enq_sys_drive *mes; 1079 struct mlx_sysdrive *dr; 1080 const char *statestr; 1081 int i, j; 1082 u_int lsn; 1083 1084 mlx = (struct mlx_softc *)mc->mc_mx.mx_dv; 1085 mlx_ccb_unmap(mlx, mc); 1086 1087 /* 1088 * Command completed OK? 1089 */ 1090 if (mc->mc_status != 0) { 1091 printf("%s: periodic enquiry failed - %s\n", 1092 mlx->mlx_dv.dv_xname, mlx_ccb_diagnose(mc)); 1093 goto out; 1094 } 1095 1096 /* 1097 * Respond to command. 1098 */ 1099 switch (mc->mc_mbox[0]) { 1100 case MLX_CMD_ENQUIRY_OLD: 1101 /* 1102 * This is currently a bit fruitless, as we don't know how 1103 * to extract the eventlog pointer yet. 1104 */ 1105 me = (struct mlx_enquiry *)mc->mc_mx.mx_context; 1106 meo = (struct mlx_enquiry_old *)mc->mc_mx.mx_context; 1107 1108 /* Convert data in-place to new format */ 1109 i = sizeof(me->me_dead) / sizeof(me->me_dead[0]); 1110 while (--i >= 0) { 1111 me->me_dead[i].dd_chan = meo->me_dead[i].dd_chan; 1112 me->me_dead[i].dd_targ = meo->me_dead[i].dd_targ; 1113 } 1114 1115 me->me_misc_flags = 0; 1116 me->me_rebuild_count = meo->me_rebuild_count; 1117 me->me_dead_count = meo->me_dead_count; 1118 me->me_critical_sd_count = meo->me_critical_sd_count; 1119 me->me_event_log_seq_num = 0; 1120 me->me_offline_sd_count = meo->me_offline_sd_count; 1121 me->me_max_commands = meo->me_max_commands; 1122 me->me_rebuild_flag = meo->me_rebuild_flag; 1123 me->me_fwmajor = meo->me_fwmajor; 1124 me->me_fwminor = meo->me_fwminor; 1125 me->me_status_flags = meo->me_status_flags; 1126 me->me_flash_age = meo->me_flash_age; 1127 1128 i = sizeof(me->me_drvsize) / sizeof(me->me_drvsize[0]); 1129 j = sizeof(meo->me_drvsize) / sizeof(meo->me_drvsize[0]); 1130 1131 while (--i >= 0) { 1132 if (i >= j) 1133 me->me_drvsize[i] = 0; 1134 else 1135 me->me_drvsize[i] = meo->me_drvsize[i]; 1136 } 1137 1138 me->me_num_sys_drvs = meo->me_num_sys_drvs; 1139 1140 /* FALLTHROUGH */ 1141 1142 case MLX_CMD_ENQUIRY: 1143 /* 1144 * Generic controller status update. We could do more with 1145 * this than just checking the event log. 1146 */ 1147 me = (struct mlx_enquiry *)mc->mc_mx.mx_context; 1148 lsn = le16toh(me->me_event_log_seq_num); 1149 1150 if (mlx->mlx_currevent == -1) { 1151 /* Initialise our view of the event log. */ 1152 mlx->mlx_currevent = lsn; 1153 mlx->mlx_lastevent = lsn; 1154 } else if (lsn != mlx->mlx_lastevent && 1155 (mlx->mlx_flags & MLXF_EVENTLOG_BUSY) == 0) { 1156 /* Record where current events are up to */ 1157 mlx->mlx_currevent = lsn; 1158 1159 /* Mark the event log as busy. */ 1160 mlx->mlx_flags |= MLXF_EVENTLOG_BUSY; 1161 1162 /* Drain new eventlog entries. */ 1163 mlx_periodic_eventlog_poll(mlx); 1164 } 1165 break; 1166 1167 case MLX_CMD_ENQSYSDRIVE: 1168 /* 1169 * Perform drive status comparison to see if something 1170 * has failed. Don't perform the comparison if we're 1171 * reconfiguring, since the system drive table will be 1172 * changing. 1173 */ 1174 if ((mlx->mlx_flags & MLXF_RESCANNING) != 0) 1175 break; 1176 1177 mes = (struct mlx_enq_sys_drive *)mc->mc_mx.mx_context; 1178 dr = &mlx->mlx_sysdrive[0]; 1179 1180 for (i = 0; i < mlx->mlx_numsysdrives; i++) { 1181 /* Has state been changed by controller? */ 1182 if (dr->ms_state != mes[i].sd_state) { 1183 switch (mes[i].sd_state) { 1184 case MLX_SYSD_OFFLINE: 1185 statestr = "offline"; 1186 break; 1187 1188 case MLX_SYSD_ONLINE: 1189 statestr = "online"; 1190 break; 1191 1192 case MLX_SYSD_CRITICAL: 1193 statestr = "critical"; 1194 break; 1195 1196 default: 1197 statestr = "unknown"; 1198 break; 1199 } 1200 1201 printf("%s: unit %d %s\n", mlx->mlx_dv.dv_xname, 1202 i, statestr); 1203 1204 /* Save new state. */ 1205 dr->ms_state = mes[i].sd_state; 1206 } 1207 } 1208 break; 1209 1210 #ifdef DIAGNOSTIC 1211 default: 1212 printf("%s: mlx_periodic_enquiry: eh?\n", 1213 mlx->mlx_dv.dv_xname); 1214 break; 1215 #endif 1216 } 1217 1218 out: 1219 if (mc->mc_mbox[0] == MLX_CMD_ENQSYSDRIVE) 1220 mlx->mlx_flags &= ~MLXF_PERIODIC_DRIVE; 1221 else 1222 mlx->mlx_flags &= ~MLXF_PERIODIC_CTLR; 1223 1224 free(mc->mc_mx.mx_context, M_DEVBUF); 1225 mlx_ccb_free(mlx, mc); 1226 } 1227 1228 /* 1229 * Instigate a poll for one event log message on (mlx). We only poll for 1230 * one message at a time, to keep our command usage down. 1231 */ 1232 static void 1233 mlx_periodic_eventlog_poll(struct mlx_softc *mlx) 1234 { 1235 struct mlx_ccb *mc; 1236 void *result; 1237 int rv; 1238 1239 result = NULL; 1240 1241 if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0) 1242 goto out; 1243 1244 if ((result = malloc(1024, M_DEVBUF, M_WAITOK)) == NULL) { 1245 rv = ENOMEM; 1246 goto out; 1247 } 1248 if ((rv = mlx_ccb_map(mlx, mc, result, 1024, MC_XFER_IN)) != 0) 1249 goto out; 1250 if (mc->mc_nsgent != 1) { 1251 mlx_ccb_unmap(mlx, mc); 1252 printf("mlx_periodic_eventlog_poll: too many segs\n"); 1253 goto out; 1254 } 1255 1256 /* Build the command to get one log entry. */ 1257 mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1, 1258 mlx->mlx_lastevent, 0, 0, mc->mc_xfer_phys, 0); 1259 1260 mc->mc_mx.mx_handler = mlx_periodic_eventlog_respond; 1261 mc->mc_mx.mx_dv = &mlx->mlx_dv; 1262 mc->mc_mx.mx_context = result; 1263 1264 /* Start the command. */ 1265 mlx_ccb_enqueue(mlx, mc); 1266 1267 out: 1268 if (rv != 0) { 1269 if (mc != NULL) 1270 mlx_ccb_free(mlx, mc); 1271 if (result != NULL) 1272 free(result, M_DEVBUF); 1273 } 1274 } 1275 1276 /* 1277 * Handle the result of polling for a log message, generate diagnostic 1278 * output. If this wasn't the last message waiting for us, we'll go collect 1279 * another. 1280 */ 1281 static void 1282 mlx_periodic_eventlog_respond(struct mlx_ccb *mc) 1283 { 1284 struct mlx_softc *mlx; 1285 struct mlx_eventlog_entry *el; 1286 const char *reason; 1287 u_int8_t sensekey, chan, targ; 1288 1289 mlx = (struct mlx_softc *)mc->mc_mx.mx_dv; 1290 el = mc->mc_mx.mx_context; 1291 mlx_ccb_unmap(mlx, mc); 1292 1293 mlx->mlx_lastevent++; 1294 1295 if (mc->mc_status == 0) { 1296 switch (el->el_type) { 1297 case MLX_LOGMSG_SENSE: /* sense data */ 1298 sensekey = el->el_sense & 0x0f; 1299 chan = (el->el_target >> 4) & 0x0f; 1300 targ = el->el_target & 0x0f; 1301 1302 /* 1303 * This is the only sort of message we understand at 1304 * the moment. The tests here are probably 1305 * incomplete. 1306 */ 1307 1308 /* 1309 * Mylex vendor-specific message indicating a drive 1310 * was killed? 1311 */ 1312 if (sensekey == 9 && el->el_asc == 0x80) { 1313 if (el->el_asq < sizeof(mlx_sense_msgs) / 1314 sizeof(mlx_sense_msgs[0])) 1315 reason = mlx_sense_msgs[el->el_asq]; 1316 else 1317 reason = "for unknown reason"; 1318 1319 printf("%s: physical drive %d:%d killed %s\n", 1320 mlx->mlx_dv.dv_xname, chan, targ, reason); 1321 } 1322 1323 /* 1324 * SCSI drive was reset? 1325 */ 1326 if (sensekey == 6 && el->el_asc == 0x29) 1327 printf("%s: physical drive %d:%d reset\n", 1328 mlx->mlx_dv.dv_xname, chan, targ); 1329 1330 /* 1331 * SCSI drive error? 1332 */ 1333 if (!(sensekey == 0 || 1334 (sensekey == 2 && 1335 el->el_asc == 0x04 && 1336 (el->el_asq == 0x01 || el->el_asq == 0x02)))) { 1337 printf("%s: physical drive %d:%d error log: " 1338 "sense = %d asc = %x asq = %x\n", 1339 mlx->mlx_dv.dv_xname, chan, targ, sensekey, 1340 el->el_asc, el->el_asq); 1341 printf("%s: info = %d:%d:%d:%d " 1342 " csi = %d:%d:%d:%d\n", 1343 mlx->mlx_dv.dv_xname, 1344 el->el_information[0], 1345 el->el_information[1], 1346 el->el_information[2], 1347 el->el_information[3], 1348 el->el_csi[0], el->el_csi[1], 1349 el->el_csi[2], el->el_csi[3]); 1350 } 1351 1352 break; 1353 1354 default: 1355 printf("%s: unknown log message type 0x%x\n", 1356 mlx->mlx_dv.dv_xname, el->el_type); 1357 break; 1358 } 1359 } else { 1360 printf("%s: error reading message log - %s\n", 1361 mlx->mlx_dv.dv_xname, mlx_ccb_diagnose(mc)); 1362 1363 /* 1364 * Give up on all the outstanding messages, as we may have 1365 * come unsynched. 1366 */ 1367 mlx->mlx_lastevent = mlx->mlx_currevent; 1368 } 1369 1370 free(mc->mc_mx.mx_context, M_DEVBUF); 1371 mlx_ccb_free(mlx, mc); 1372 1373 /* 1374 * Is there another message to obtain? 1375 */ 1376 if (mlx->mlx_lastevent != mlx->mlx_currevent) 1377 mlx_periodic_eventlog_poll(mlx); 1378 else 1379 mlx->mlx_flags &= ~MLXF_EVENTLOG_BUSY; 1380 } 1381 1382 /* 1383 * Handle check/rebuild operations in progress. 1384 */ 1385 static void 1386 mlx_periodic_rebuild(struct mlx_ccb *mc) 1387 { 1388 struct mlx_softc *mlx; 1389 const char *opstr; 1390 struct mlx_rebuild_status *mr; 1391 1392 mlx = (struct mlx_softc *)mc->mc_mx.mx_dv; 1393 mr = mc->mc_mx.mx_context; 1394 mlx_ccb_unmap(mlx, mc); 1395 1396 switch (mc->mc_status) { 1397 case 0: 1398 /* 1399 * Operation running, update stats. 1400 */ 1401 mlx->mlx_rebuildstat = *mr; 1402 1403 /* Spontaneous rebuild/check? */ 1404 if (mlx->mlx_bg == 0) { 1405 mlx->mlx_bg = MLX_BG_SPONTANEOUS; 1406 printf("%s: background check/rebuild started\n", 1407 mlx->mlx_dv.dv_xname); 1408 } 1409 break; 1410 1411 case 0x0105: 1412 /* 1413 * Nothing running, finalise stats and report. 1414 */ 1415 switch (mlx->mlx_bg) { 1416 case MLX_BG_CHECK: 1417 /* XXX Print drive? */ 1418 opstr = "consistency check"; 1419 break; 1420 1421 case MLX_BG_REBUILD: 1422 /* XXX Print channel:target? */ 1423 opstr = "drive rebuild"; 1424 break; 1425 1426 case MLX_BG_SPONTANEOUS: 1427 default: 1428 /* 1429 * If we have previously been non-idle, report the 1430 * transition 1431 */ 1432 if (mlx->mlx_rebuildstat.rs_code != 1433 MLX_REBUILDSTAT_IDLE) 1434 opstr = "background check/rebuild"; 1435 else 1436 opstr = NULL; 1437 } 1438 1439 if (opstr != NULL) 1440 printf("%s: %s completed\n", mlx->mlx_dv.dv_xname, 1441 opstr); 1442 1443 mlx->mlx_bg = 0; 1444 mlx->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE; 1445 break; 1446 } 1447 1448 free(mc->mc_mx.mx_context, M_DEVBUF); 1449 mlx_ccb_free(mlx, mc); 1450 mlx->mlx_flags &= ~MLXF_PERIODIC_REBUILD; 1451 } 1452 1453 /* 1454 * It's time to perform a channel pause action for (mlx), either start or 1455 * stop the pause. 1456 */ 1457 static void 1458 mlx_pause_action(struct mlx_softc *mlx) 1459 { 1460 struct mlx_ccb *mc; 1461 int failsafe, i, cmd; 1462 1463 /* What are we doing here? */ 1464 if (mlx->mlx_pause.mp_when == 0) { 1465 cmd = MLX_CMD_STARTCHANNEL; 1466 failsafe = 0; 1467 } else { 1468 cmd = MLX_CMD_STOPCHANNEL; 1469 1470 /* 1471 * Channels will always start again after the failsafe 1472 * period, which is specified in multiples of 30 seconds. 1473 * This constrains us to a maximum pause of 450 seconds. 1474 */ 1475 failsafe = ((mlx->mlx_pause.mp_howlong - time_second) + 5) / 30; 1476 1477 if (failsafe > 0xf) { 1478 failsafe = 0xf; 1479 mlx->mlx_pause.mp_howlong = 1480 time_second + (0xf * 30) - 5; 1481 } 1482 } 1483 1484 /* Build commands for every channel requested. */ 1485 for (i = 0; i < mlx->mlx_ci.ci_nchan; i++) { 1486 if ((1 << i) & mlx->mlx_pause.mp_which) { 1487 if (mlx_ccb_alloc(mlx, &mc, 1) != 0) { 1488 printf("%s: %s failed for channel %d\n", 1489 mlx->mlx_dv.dv_xname, 1490 cmd == MLX_CMD_STOPCHANNEL ? 1491 "pause" : "resume", i); 1492 continue; 1493 } 1494 1495 /* Build the command. */ 1496 mlx_make_type2(mc, cmd, (failsafe << 4) | i, 0, 0, 1497 0, 0, 0, 0, 0); 1498 mc->mc_mx.mx_handler = mlx_pause_done; 1499 mc->mc_mx.mx_dv = &mlx->mlx_dv; 1500 1501 mlx_ccb_enqueue(mlx, mc); 1502 } 1503 } 1504 } 1505 1506 static void 1507 mlx_pause_done(struct mlx_ccb *mc) 1508 { 1509 struct mlx_softc *mlx; 1510 int command, channel; 1511 1512 mlx = (struct mlx_softc *)mc->mc_mx.mx_dv; 1513 command = mc->mc_mbox[0]; 1514 channel = mc->mc_mbox[2] & 0xf; 1515 1516 if (mc->mc_status != 0) 1517 printf("%s: %s command failed - %s\n", mlx->mlx_dv.dv_xname, 1518 command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", 1519 mlx_ccb_diagnose(mc)); 1520 else if (command == MLX_CMD_STOPCHANNEL) 1521 printf("%s: channel %d pausing for %ld seconds\n", 1522 mlx->mlx_dv.dv_xname, channel, 1523 (long)(mlx->mlx_pause.mp_howlong - time_second)); 1524 else 1525 printf("%s: channel %d resuming\n", mlx->mlx_dv.dv_xname, 1526 channel); 1527 1528 mlx_ccb_free(mlx, mc); 1529 } 1530 1531 /* 1532 * Perform an Enquiry command using a type-3 command buffer and a return a 1533 * single linear result buffer. If the completion function is specified, it 1534 * will be called with the completed command (and the result response will 1535 * not be valid until that point). Otherwise, the command will either be 1536 * busy-waited for (interrupts must be blocked), or slept for. 1537 */ 1538 static void * 1539 mlx_enquire(struct mlx_softc *mlx, int command, size_t bufsize, 1540 void (*handler)(struct mlx_ccb *mc), int waitok) 1541 { 1542 struct mlx_ccb *mc; 1543 void *result; 1544 int rv, mapped; 1545 1546 result = NULL; 1547 mapped = 0; 1548 1549 if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0) 1550 goto out; 1551 1552 result = malloc(bufsize, M_DEVBUF, waitok ? M_WAITOK : M_NOWAIT); 1553 if (result == NULL) { 1554 printf("mlx_enquire: malloc() failed\n"); 1555 goto out; 1556 } 1557 if ((rv = mlx_ccb_map(mlx, mc, result, bufsize, MC_XFER_IN)) != 0) 1558 goto out; 1559 mapped = 1; 1560 if (mc->mc_nsgent != 1) { 1561 printf("mlx_enquire: too many segs\n"); 1562 goto out; 1563 } 1564 1565 /* Build an enquiry command. */ 1566 mlx_make_type2(mc, command, 0, 0, 0, 0, 0, 0, mc->mc_xfer_phys, 0); 1567 1568 /* Do we want a completion callback? */ 1569 if (handler != NULL) { 1570 mc->mc_mx.mx_context = result; 1571 mc->mc_mx.mx_dv = &mlx->mlx_dv; 1572 mc->mc_mx.mx_handler = handler; 1573 mlx_ccb_enqueue(mlx, mc); 1574 } else { 1575 /* Run the command in either polled or wait mode. */ 1576 if (waitok) 1577 rv = mlx_ccb_wait(mlx, mc); 1578 else 1579 rv = mlx_ccb_poll(mlx, mc, 5000); 1580 } 1581 1582 out: 1583 /* We got a command, but nobody else will free it. */ 1584 if (handler == NULL && mc != NULL) { 1585 if (mapped) 1586 mlx_ccb_unmap(mlx, mc); 1587 mlx_ccb_free(mlx, mc); 1588 } 1589 1590 /* We got an error, and we allocated a result. */ 1591 if (rv != 0 && result != NULL) { 1592 if (mc != NULL) 1593 mlx_ccb_free(mlx, mc); 1594 free(result, M_DEVBUF); 1595 result = NULL; 1596 } 1597 1598 return (result); 1599 } 1600 1601 /* 1602 * Perform a Flush command on the nominated controller. 1603 * 1604 * May be called with interrupts enabled or disabled; will not return until 1605 * the flush operation completes or fails. 1606 */ 1607 int 1608 mlx_flush(struct mlx_softc *mlx, int async) 1609 { 1610 struct mlx_ccb *mc; 1611 int rv; 1612 1613 if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0) 1614 goto out; 1615 1616 /* Build a flush command and fire it off. */ 1617 mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0); 1618 1619 if (async) 1620 rv = mlx_ccb_wait(mlx, mc); 1621 else 1622 rv = mlx_ccb_poll(mlx, mc, MLX_TIMEOUT * 1000); 1623 if (rv != 0) 1624 goto out; 1625 1626 /* Command completed OK? */ 1627 if (mc->mc_status != 0) { 1628 printf("%s: FLUSH failed - %s\n", mlx->mlx_dv.dv_xname, 1629 mlx_ccb_diagnose(mc)); 1630 rv = EIO; 1631 } 1632 out: 1633 if (mc != NULL) 1634 mlx_ccb_free(mlx, mc); 1635 1636 return (rv); 1637 } 1638 1639 /* 1640 * Start a background consistency check on (drive). 1641 */ 1642 static int 1643 mlx_check(struct mlx_softc *mlx, int drive) 1644 { 1645 struct mlx_ccb *mc; 1646 int rv; 1647 1648 /* Get ourselves a command buffer. */ 1649 rv = 0x10000; 1650 1651 if (mlx_ccb_alloc(mlx, &mc, 1) != 0) 1652 goto out; 1653 1654 /* Build a checkasync command, set the "fix it" flag. */ 1655 mlx_make_type2(mc, MLX_CMD_CHECKASYNC, 0, 0, 0, 0, 0, drive | 0x80, 1656 0, 0); 1657 1658 /* Start the command and wait for it to be returned. */ 1659 if (mlx_ccb_wait(mlx, mc) != 0) 1660 goto out; 1661 1662 /* Command completed OK? */ 1663 if (mc->mc_status != 0) 1664 printf("%s: CHECK ASYNC failed - %s\n", mlx->mlx_dv.dv_xname, 1665 mlx_ccb_diagnose(mc)); 1666 else 1667 printf("%s: consistency check started", 1668 mlx->mlx_sysdrive[drive].ms_dv->dv_xname); 1669 1670 rv = mc->mc_status; 1671 out: 1672 if (mc != NULL) 1673 mlx_ccb_free(mlx, mc); 1674 1675 return (rv); 1676 } 1677 1678 /* 1679 * Start a background rebuild of the physical drive at (channel),(target). 1680 * 1681 * May be called with interrupts enabled or disabled; will return as soon as 1682 * the operation has started or been refused. 1683 */ 1684 static int 1685 mlx_rebuild(struct mlx_softc *mlx, int channel, int target) 1686 { 1687 struct mlx_ccb *mc; 1688 int error; 1689 1690 error = 0x10000; 1691 if (mlx_ccb_alloc(mlx, &mc, 1) != 0) 1692 goto out; 1693 1694 /* Build a rebuildasync command, set the "fix it" flag. */ 1695 mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0, 1696 0, 0); 1697 1698 /* Start the command and wait for it to be returned. */ 1699 if (mlx_ccb_wait(mlx, mc) != 0) 1700 goto out; 1701 1702 /* Command completed OK? */ 1703 printf("%s: ", mlx->mlx_dv.dv_xname); 1704 if (mc->mc_status != 0) 1705 printf("REBUILD ASYNC failed - %s\n", mlx_ccb_diagnose(mc)); 1706 else 1707 printf("rebuild started for %d:%d\n", channel, target); 1708 1709 error = mc->mc_status; 1710 1711 out: 1712 if (mc != NULL) 1713 mlx_ccb_free(mlx, mc); 1714 1715 return (error); 1716 } 1717 1718 /* 1719 * Take a command from user-space and try to run it. 1720 * 1721 * XXX Note that this can't perform very much in the way of error checking, 1722 * XXX and as such, applications _must_ be considered trustworthy. 1723 * 1724 * XXX Commands using S/G for data are not supported. 1725 */ 1726 static int 1727 mlx_user_command(struct mlx_softc *mlx, struct mlx_usercommand *mu) 1728 { 1729 struct mlx_ccb *mc; 1730 struct mlx_dcdb *dcdb; 1731 void *kbuf; 1732 int rv, mapped; 1733 1734 if ((mu->mu_bufdir & ~MU_XFER_MASK) != 0) 1735 return (EINVAL); 1736 1737 kbuf = NULL; 1738 dcdb = NULL; 1739 mapped = 0; 1740 1741 /* Get ourselves a command and copy in from user space. */ 1742 if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0) { 1743 DPRINTF(("mlx_user_command: mlx_ccb_alloc = %d\n", rv)); 1744 goto out; 1745 } 1746 1747 memcpy(mc->mc_mbox, mu->mu_command, sizeof(mc->mc_mbox)); 1748 1749 /* 1750 * If we need a buffer for data transfer, allocate one and copy in 1751 * its initial contents. 1752 */ 1753 if (mu->mu_datasize > 0) { 1754 if (mu->mu_datasize > MAXPHYS) 1755 return (EINVAL); 1756 1757 kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK); 1758 if (kbuf == NULL) { 1759 DPRINTF(("mlx_user_command: malloc = NULL\n")); 1760 rv = ENOMEM; 1761 goto out; 1762 } 1763 1764 if ((mu->mu_bufdir & MU_XFER_OUT) != 0) { 1765 rv = copyin(mu->mu_buf, kbuf, mu->mu_datasize); 1766 if (rv != 0) { 1767 DPRINTF(("mlx_user_command: copyin = %d\n", 1768 rv)); 1769 goto out; 1770 } 1771 } 1772 1773 /* Map the buffer so the controller can see it. */ 1774 rv = mlx_ccb_map(mlx, mc, kbuf, mu->mu_datasize, mu->mu_bufdir); 1775 if (rv != 0) { 1776 DPRINTF(("mlx_user_command: mlx_ccb_map = %d\n", rv)); 1777 goto out; 1778 } 1779 if (mc->mc_nsgent > 1) { 1780 DPRINTF(("mlx_user_command: too many s/g entries\n")); 1781 rv = EFBIG; 1782 goto out; 1783 } 1784 mapped = 1; 1785 /* 1786 * If this is a passthrough SCSI command, the DCDB is packed at 1787 * the beginning of the data area. Fix up the DCDB to point to 1788 * the correct physical address and override any bufptr 1789 * supplied by the caller since we know what it's meant to be. 1790 */ 1791 if (mc->mc_mbox[0] == MLX_CMD_DIRECT_CDB) { 1792 dcdb = (struct mlx_dcdb *)kbuf; 1793 dcdb->dcdb_physaddr = mc->mc_xfer_phys + sizeof(*dcdb); 1794 mu->mu_bufptr = 8; 1795 } 1796 } 1797 1798 1799 /* 1800 * If there's a data buffer, fix up the command's buffer pointer. 1801 */ 1802 if (mu->mu_datasize > 0) { 1803 /* Range check the pointer to physical buffer address. */ 1804 if (mu->mu_bufptr < 0 || 1805 mu->mu_bufptr > sizeof(mu->mu_command) - 4) { 1806 DPRINTF(("mlx_user_command: bufptr botch\n")); 1807 rv = EINVAL; 1808 goto out; 1809 } 1810 1811 mc->mc_mbox[mu->mu_bufptr] = mc->mc_xfer_phys; 1812 mc->mc_mbox[mu->mu_bufptr+1] = mc->mc_xfer_phys >> 8; 1813 mc->mc_mbox[mu->mu_bufptr+2] = mc->mc_xfer_phys >> 16; 1814 mc->mc_mbox[mu->mu_bufptr+3] = mc->mc_xfer_phys >> 24; 1815 } 1816 1817 /* Submit the command and wait. */ 1818 if ((rv = mlx_ccb_wait(mlx, mc)) != 0) { 1819 #ifdef DEBUG 1820 printf("mlx_user_command: mlx_ccb_wait = %d\n", rv); 1821 #endif 1822 } 1823 1824 out: 1825 if (mc != NULL) { 1826 /* Copy out status and data */ 1827 mu->mu_status = mc->mc_status; 1828 if (mapped) 1829 mlx_ccb_unmap(mlx, mc); 1830 mlx_ccb_free(mlx, mc); 1831 } 1832 1833 if (kbuf != NULL) { 1834 if (mu->mu_datasize > 0 && (mu->mu_bufdir & MU_XFER_IN) != 0) { 1835 rv = copyout(kbuf, mu->mu_buf, mu->mu_datasize); 1836 #ifdef DIAGNOSTIC 1837 if (rv != 0) 1838 printf("mlx_user_command: copyout = %d\n", rv); 1839 #endif 1840 } 1841 } 1842 if (kbuf != NULL) 1843 free(kbuf, M_DEVBUF); 1844 1845 return (rv); 1846 } 1847 1848 /* 1849 * Allocate and initialise a CCB. 1850 */ 1851 int 1852 mlx_ccb_alloc(struct mlx_softc *mlx, struct mlx_ccb **mcp, int control) 1853 { 1854 struct mlx_ccb *mc; 1855 int s; 1856 1857 s = splbio(); 1858 mc = SLIST_FIRST(&mlx->mlx_ccb_freelist); 1859 if (control) { 1860 if (mlx->mlx_nccbs_ctrl >= MLX_NCCBS_CONTROL) { 1861 splx(s); 1862 *mcp = NULL; 1863 return (EAGAIN); 1864 } 1865 mc->mc_flags |= MC_CONTROL; 1866 mlx->mlx_nccbs_ctrl++; 1867 } 1868 SLIST_REMOVE_HEAD(&mlx->mlx_ccb_freelist, mc_chain.slist); 1869 splx(s); 1870 1871 *mcp = mc; 1872 return (0); 1873 } 1874 1875 /* 1876 * Free a CCB. 1877 */ 1878 void 1879 mlx_ccb_free(struct mlx_softc *mlx, struct mlx_ccb *mc) 1880 { 1881 int s; 1882 1883 s = splbio(); 1884 if ((mc->mc_flags & MC_CONTROL) != 0) 1885 mlx->mlx_nccbs_ctrl--; 1886 mc->mc_flags = 0; 1887 SLIST_INSERT_HEAD(&mlx->mlx_ccb_freelist, mc, mc_chain.slist); 1888 splx(s); 1889 } 1890 1891 /* 1892 * If a CCB is specified, enqueue it. Pull CCBs off the software queue in 1893 * the order that they were enqueued and try to submit their mailboxes to 1894 * the controller for execution. 1895 */ 1896 void 1897 mlx_ccb_enqueue(struct mlx_softc *mlx, struct mlx_ccb *mc) 1898 { 1899 int s; 1900 1901 s = splbio(); 1902 1903 if (mc != NULL) 1904 SIMPLEQ_INSERT_TAIL(&mlx->mlx_ccb_queue, mc, mc_chain.simpleq); 1905 1906 while ((mc = SIMPLEQ_FIRST(&mlx->mlx_ccb_queue)) != NULL) { 1907 if (mlx_ccb_submit(mlx, mc) != 0) 1908 break; 1909 SIMPLEQ_REMOVE_HEAD(&mlx->mlx_ccb_queue, mc_chain.simpleq); 1910 TAILQ_INSERT_TAIL(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq); 1911 } 1912 1913 splx(s); 1914 } 1915 1916 /* 1917 * Map the specified CCB's data buffer onto the bus, and fill the 1918 * scatter-gather list. 1919 */ 1920 int 1921 mlx_ccb_map(struct mlx_softc *mlx, struct mlx_ccb *mc, void *data, int size, 1922 int dir) 1923 { 1924 struct mlx_sgentry *sge; 1925 int nsegs, i, rv, sgloff; 1926 bus_dmamap_t xfer; 1927 1928 xfer = mc->mc_xfer_map; 1929 1930 rv = bus_dmamap_load(mlx->mlx_dmat, xfer, data, size, NULL, 1931 BUS_DMA_NOWAIT | BUS_DMA_STREAMING | 1932 ((dir & MC_XFER_IN) ? BUS_DMA_READ : BUS_DMA_WRITE)); 1933 if (rv != 0) 1934 return (rv); 1935 1936 nsegs = xfer->dm_nsegs; 1937 mc->mc_xfer_size = size; 1938 mc->mc_flags |= dir; 1939 mc->mc_nsgent = nsegs; 1940 mc->mc_xfer_phys = xfer->dm_segs[0].ds_addr; 1941 1942 sgloff = MLX_SGL_SIZE * mc->mc_ident; 1943 sge = (struct mlx_sgentry *)((caddr_t)mlx->mlx_sgls + sgloff); 1944 1945 for (i = 0; i < nsegs; i++, sge++) { 1946 sge->sge_addr = htole32(xfer->dm_segs[i].ds_addr); 1947 sge->sge_count = htole32(xfer->dm_segs[i].ds_len); 1948 } 1949 1950 if ((dir & MC_XFER_OUT) != 0) 1951 i = BUS_DMASYNC_PREWRITE; 1952 else 1953 i = 0; 1954 if ((dir & MC_XFER_IN) != 0) 1955 i |= BUS_DMASYNC_PREREAD; 1956 1957 bus_dmamap_sync(mlx->mlx_dmat, xfer, 0, mc->mc_xfer_size, i); 1958 bus_dmamap_sync(mlx->mlx_dmat, mlx->mlx_dmamap, sgloff, 1959 MLX_SGL_SIZE, BUS_DMASYNC_PREWRITE); 1960 1961 return (0); 1962 } 1963 1964 /* 1965 * Unmap the specified CCB's data buffer. 1966 */ 1967 void 1968 mlx_ccb_unmap(struct mlx_softc *mlx, struct mlx_ccb *mc) 1969 { 1970 int i; 1971 1972 bus_dmamap_sync(mlx->mlx_dmat, mlx->mlx_dmamap, 1973 MLX_SGL_SIZE * mc->mc_ident, MLX_SGL_SIZE, 1974 BUS_DMASYNC_POSTWRITE); 1975 1976 if ((mc->mc_flags & MC_XFER_OUT) != 0) 1977 i = BUS_DMASYNC_POSTWRITE; 1978 else 1979 i = 0; 1980 if ((mc->mc_flags & MC_XFER_IN) != 0) 1981 i |= BUS_DMASYNC_POSTREAD; 1982 1983 bus_dmamap_sync(mlx->mlx_dmat, mc->mc_xfer_map, 0, mc->mc_xfer_size, i); 1984 bus_dmamap_unload(mlx->mlx_dmat, mc->mc_xfer_map); 1985 } 1986 1987 /* 1988 * Submit the CCB, and busy-wait for it to complete. Return non-zero on 1989 * timeout or submission error. Must be called with interrupts blocked. 1990 */ 1991 int 1992 mlx_ccb_poll(struct mlx_softc *mlx, struct mlx_ccb *mc, int timo) 1993 { 1994 int rv; 1995 1996 mc->mc_mx.mx_handler = NULL; 1997 1998 if ((rv = mlx_ccb_submit(mlx, mc)) != 0) 1999 return (rv); 2000 TAILQ_INSERT_TAIL(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq); 2001 2002 for (timo *= 10; timo != 0; timo--) { 2003 mlx_intr(mlx); 2004 if (mc->mc_status != MLX_STATUS_BUSY) 2005 break; 2006 DELAY(100); 2007 } 2008 2009 if (timo != 0) { 2010 if (mc->mc_status != 0) { 2011 printf("%s: command failed - %s\n", 2012 mlx->mlx_dv.dv_xname, mlx_ccb_diagnose(mc)); 2013 rv = EIO; 2014 } else 2015 rv = 0; 2016 } else { 2017 printf("%s: command timed out\n", mlx->mlx_dv.dv_xname); 2018 rv = EIO; 2019 } 2020 2021 return (rv); 2022 } 2023 2024 /* 2025 * Enqueue the CCB, and sleep until it completes. Return non-zero on 2026 * timeout or error. 2027 */ 2028 int 2029 mlx_ccb_wait(struct mlx_softc *mlx, struct mlx_ccb *mc) 2030 { 2031 int s; 2032 2033 mc->mc_flags |= MC_WAITING; 2034 mc->mc_mx.mx_handler = NULL; 2035 2036 s = splbio(); 2037 mlx_ccb_enqueue(mlx, mc); 2038 tsleep(mc, PRIBIO, "mlxwccb", 0); 2039 splx(s); 2040 2041 if (mc->mc_status != 0) { 2042 printf("%s: command failed - %s\n", mlx->mlx_dv.dv_xname, 2043 mlx_ccb_diagnose(mc)); 2044 return (EIO); 2045 } 2046 2047 return (0); 2048 } 2049 2050 /* 2051 * Try to submit a CCB's mailbox to the controller for execution. Return 2052 * non-zero on timeout or error. Must be called with interrupts blocked. 2053 */ 2054 static int 2055 mlx_ccb_submit(struct mlx_softc *mlx, struct mlx_ccb *mc) 2056 { 2057 int i, s, r; 2058 2059 /* Save the ident so we can handle this command when complete. */ 2060 mc->mc_mbox[1] = (u_int8_t)(mc->mc_ident + 1); 2061 2062 /* Mark the command as currently being processed. */ 2063 mc->mc_status = MLX_STATUS_BUSY; 2064 mc->mc_expiry = time_second + MLX_TIMEOUT; 2065 2066 /* Spin waiting for the mailbox. */ 2067 for (i = 100; i != 0; i--) { 2068 s = splbio(); 2069 r = (*mlx->mlx_submit)(mlx, mc); 2070 splx(s); 2071 if (r != 0) 2072 break; 2073 DELAY(100); 2074 } 2075 if (i != 0) 2076 return (0); 2077 2078 DPRINTF(("mlx_ccb_submit: rejected; queueing\n")); 2079 mc->mc_status = MLX_STATUS_WEDGED; 2080 return (EIO); 2081 } 2082 2083 /* 2084 * Return a string that describes why a command has failed. 2085 */ 2086 const char * 2087 mlx_ccb_diagnose(struct mlx_ccb *mc) 2088 { 2089 static char tbuf[80]; 2090 int i; 2091 2092 for (i = 0; i < sizeof(mlx_msgs) / sizeof(mlx_msgs[0]); i++) 2093 if ((mc->mc_mbox[0] == mlx_msgs[i].command || 2094 mlx_msgs[i].command == 0) && 2095 mc->mc_status == mlx_msgs[i].status) { 2096 snprintf(tbuf, sizeof(tbuf), "%s (0x%x)", 2097 mlx_status_msgs[mlx_msgs[i].msg], mc->mc_status); 2098 return (tbuf); 2099 } 2100 2101 snprintf(tbuf, sizeof(tbuf), "unknown response 0x%x for command 0x%x", 2102 (int)mc->mc_status, (int)mc->mc_mbox[0]); 2103 2104 return (tbuf); 2105 } 2106 2107 /* 2108 * Poll the controller for completed commands. Returns non-zero if one or 2109 * more commands were completed. Must be called with interrupts blocked. 2110 */ 2111 int 2112 mlx_intr(void *cookie) 2113 { 2114 struct mlx_softc *mlx; 2115 struct mlx_ccb *mc; 2116 int result; 2117 u_int ident, status; 2118 2119 mlx = cookie; 2120 result = 0; 2121 2122 while ((*mlx->mlx_findcomplete)(mlx, &ident, &status) != 0) { 2123 result = 1; 2124 ident--; 2125 2126 if (ident >= MLX_MAX_QUEUECNT) { 2127 printf("%s: bad completion returned\n", 2128 mlx->mlx_dv.dv_xname); 2129 continue; 2130 } 2131 2132 mc = mlx->mlx_ccbs + ident; 2133 2134 if (mc->mc_status != MLX_STATUS_BUSY) { 2135 printf("%s: bad completion returned\n", 2136 mlx->mlx_dv.dv_xname); 2137 continue; 2138 } 2139 2140 TAILQ_REMOVE(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq); 2141 2142 /* Record status and notify the initiator, if requested. */ 2143 mc->mc_status = status; 2144 if (mc->mc_mx.mx_handler != NULL) 2145 (*mc->mc_mx.mx_handler)(mc); 2146 else if ((mc->mc_flags & MC_WAITING) != 0) 2147 wakeup(mc); 2148 } 2149 2150 /* If we've completed any commands, try posting some more. */ 2151 if (result) 2152 mlx_ccb_enqueue(mlx, NULL); 2153 2154 return (result); 2155 } 2156 2157 /* 2158 * Emit a string describing the firmware handshake status code, and return a 2159 * flag indicating whether the code represents a fatal error. 2160 * 2161 * Error code interpretations are from the Linux driver, and don't directly 2162 * match the messages printed by Mylex's BIOS. This may change if 2163 * documentation on the codes is forthcoming. 2164 */ 2165 static int 2166 mlx_fw_message(struct mlx_softc *mlx, int error, int param1, int param2) 2167 { 2168 const char *fmt; 2169 2170 switch (error) { 2171 case 0x00: 2172 fmt = "physical drive %d:%d not responding"; 2173 break; 2174 2175 case 0x08: 2176 /* 2177 * We could be neater about this and give some indication 2178 * when we receive more of them. 2179 */ 2180 if ((mlx->mlx_flags & MLXF_SPINUP_REPORTED) == 0) { 2181 printf("%s: spinning up drives...\n", 2182 mlx->mlx_dv.dv_xname); 2183 mlx->mlx_flags |= MLXF_SPINUP_REPORTED; 2184 } 2185 return (0); 2186 2187 case 0x30: 2188 fmt = "configuration checksum error"; 2189 break; 2190 2191 case 0x60: 2192 fmt = "mirror race recovery failed"; 2193 break; 2194 2195 case 0x70: 2196 fmt = "mirror race recovery in progress"; 2197 break; 2198 2199 case 0x90: 2200 fmt = "physical drive %d:%d COD mismatch"; 2201 break; 2202 2203 case 0xa0: 2204 fmt = "logical drive installation aborted"; 2205 break; 2206 2207 case 0xb0: 2208 fmt = "mirror race on a critical system drive"; 2209 break; 2210 2211 case 0xd0: 2212 fmt = "new controller configuration found"; 2213 break; 2214 2215 case 0xf0: 2216 printf("%s: FATAL MEMORY PARITY ERROR\n", 2217 mlx->mlx_dv.dv_xname); 2218 return (1); 2219 2220 default: 2221 printf("%s: unknown firmware init error %02x:%02x:%02x\n", 2222 mlx->mlx_dv.dv_xname, error, param1, param2); 2223 return (0); 2224 } 2225 2226 printf("%s: ", mlx->mlx_dv.dv_xname); 2227 printf(fmt, param2, param1); 2228 printf("\n"); 2229 2230 return (0); 2231 } 2232