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