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