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