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