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