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