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