1/*- 2 * Copyright (c) 1999 Michael Smith 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 *
|
26 * $FreeBSD: head/sys/dev/mlx/mlx.c 59136 2000-04-11 02:52:46Z msmith $
|
26 * $FreeBSD: head/sys/dev/mlx/mlx.c 59249 2000-04-15 05:54:02Z phk $ |
27 */ 28 29/* 30 * Driver for the Mylex DAC960 family of RAID controllers. 31 */ 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/malloc.h> 36#include <sys/kernel.h> 37 38#include <sys/buf.h> 39#include <sys/bus.h> 40#include <sys/conf.h> 41#include <sys/devicestat.h> 42#include <sys/disk.h> 43#include <sys/stat.h> 44 45#include <machine/resource.h> 46#include <machine/bus.h> 47#include <machine/clock.h> 48#include <sys/rman.h> 49 50#include <dev/mlx/mlxio.h> 51#include <dev/mlx/mlxvar.h> 52#include <dev/mlx/mlxreg.h> 53 54#define MLX_CDEV_MAJOR 130 55 56static struct cdevsw mlx_cdevsw = { 57 /* open */ mlx_open, 58 /* close */ mlx_close, 59 /* read */ noread, 60 /* write */ nowrite, 61 /* ioctl */ mlx_ioctl, 62 /* poll */ nopoll, 63 /* mmap */ nommap, 64 /* strategy */ nostrategy, 65 /* name */ "mlx", 66 /* maj */ MLX_CDEV_MAJOR, 67 /* dump */ nodump, 68 /* psize */ nopsize, 69 /* flags */ 0, 70 /* bmaj */ -1 71}; 72 73devclass_t mlx_devclass; 74 75/* 76 * Per-interface accessor methods 77 */ 78static int mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 79static int mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 80static void mlx_v3_intaction(struct mlx_softc *sc, int action); 81static int mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2); 82 83static int mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 84static int mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 85static void mlx_v4_intaction(struct mlx_softc *sc, int action); 86static int mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2); 87 88static int mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc); 89static int mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status); 90static void mlx_v5_intaction(struct mlx_softc *sc, int action); 91static int mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2); 92 93/* 94 * Status monitoring 95 */ 96static void mlx_periodic(void *data); 97static void mlx_periodic_enquiry(struct mlx_command *mc); 98static void mlx_periodic_eventlog_poll(struct mlx_softc *sc); 99static void mlx_periodic_eventlog_respond(struct mlx_command *mc); 100static void mlx_periodic_rebuild(struct mlx_command *mc); 101 102/* 103 * Channel Pause 104 */ 105static void mlx_pause_action(struct mlx_softc *sc); 106static void mlx_pause_done(struct mlx_command *mc); 107 108/* 109 * Command submission. 110 */ 111static void *mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, 112 void (*complete)(struct mlx_command *mc)); 113static int mlx_flush(struct mlx_softc *sc); 114static int mlx_check(struct mlx_softc *sc, int drive); 115static int mlx_rebuild(struct mlx_softc *sc, int channel, int target); 116static int mlx_wait_command(struct mlx_command *mc); 117static int mlx_poll_command(struct mlx_command *mc); 118static void mlx_startio(struct mlx_softc *sc); 119static void mlx_completeio(struct mlx_command *mc); 120static int mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu); 121 122/* 123 * Command buffer allocation. 124 */ 125static struct mlx_command *mlx_alloccmd(struct mlx_softc *sc); 126static void mlx_releasecmd(struct mlx_command *mc); 127static void mlx_freecmd(struct mlx_command *mc); 128 129/* 130 * Command management. 131 */ 132static int mlx_getslot(struct mlx_command *mc); 133static void mlx_mapcmd(struct mlx_command *mc); 134static void mlx_unmapcmd(struct mlx_command *mc); 135static int mlx_start(struct mlx_command *mc); 136static int mlx_done(struct mlx_softc *sc); 137static void mlx_complete(struct mlx_softc *sc); 138 139/* 140 * Debugging. 141 */ 142static char *mlx_diagnose_command(struct mlx_command *mc); 143static void mlx_describe_controller(struct mlx_softc *sc); 144static int mlx_fw_message(struct mlx_softc *sc, int status, int param1, int param2); 145 146/* 147 * Utility functions. 148 */ 149static struct mlx_sysdrive *mlx_findunit(struct mlx_softc *sc, int unit); 150 151/******************************************************************************** 152 ******************************************************************************** 153 Public Interfaces 154 ******************************************************************************** 155 ********************************************************************************/ 156 157/******************************************************************************** 158 * Free all of the resources associated with (sc) 159 * 160 * Should not be called if the controller is active. 161 */ 162void 163mlx_free(struct mlx_softc *sc) 164{ 165 struct mlx_command *mc; 166 167 debug_called(1); 168 169 /* cancel status timeout */ 170 untimeout(mlx_periodic, sc, sc->mlx_timeout); 171 172 /* throw away any command buffers */ 173 while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) { 174 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link); 175 mlx_freecmd(mc); 176 } 177 178 /* destroy data-transfer DMA tag */ 179 if (sc->mlx_buffer_dmat) 180 bus_dma_tag_destroy(sc->mlx_buffer_dmat); 181 182 /* free and destroy DMA memory and tag for s/g lists */ 183 if (sc->mlx_sgtable) 184 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap); 185 if (sc->mlx_sg_dmat) 186 bus_dma_tag_destroy(sc->mlx_sg_dmat); 187 188 /* disconnect the interrupt handler */ 189 if (sc->mlx_intr) 190 bus_teardown_intr(sc->mlx_dev, sc->mlx_irq, sc->mlx_intr); 191 if (sc->mlx_irq != NULL) 192 bus_release_resource(sc->mlx_dev, SYS_RES_IRQ, 0, sc->mlx_irq); 193 194 /* destroy the parent DMA tag */ 195 if (sc->mlx_parent_dmat) 196 bus_dma_tag_destroy(sc->mlx_parent_dmat); 197 198 /* release the register window mapping */ 199 if (sc->mlx_mem != NULL) 200 bus_release_resource(sc->mlx_dev, SYS_RES_MEMORY, 201 (sc->mlx_iftype == MLX_IFTYPE_3) ? MLX_CFG_BASE1 : MLX_CFG_BASE0, sc->mlx_mem); 202 203 /* free controller enquiry data */ 204 if (sc->mlx_enq2 != NULL) 205 free(sc->mlx_enq2, M_DEVBUF); 206 207 /* destroy control device */ 208 if (sc->mlx_dev_t != (dev_t)NULL) 209 destroy_dev(sc->mlx_dev_t); 210} 211 212/******************************************************************************** 213 * Map the scatter/gather table into bus space 214 */ 215static void 216mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) 217{ 218 struct mlx_softc *sc = (struct mlx_softc *)arg; 219 220 debug_called(1); 221 222 /* save base of s/g table's address in bus space */ 223 sc->mlx_sgbusaddr = segs->ds_addr; 224} 225 226static int 227mlx_sglist_map(struct mlx_softc *sc) 228{ 229 size_t segsize; 230 int error; 231 232 debug_called(1); 233 234 /* destroy any existing mappings */ 235 if (sc->mlx_sgtable) 236 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap); 237 if (sc->mlx_sg_dmat) 238 bus_dma_tag_destroy(sc->mlx_sg_dmat); 239 240 /* 241 * Create a single tag describing a region large enough to hold all of 242 * the s/g lists we will need. 243 */ 244 segsize = sizeof(struct mlx_sgentry) * sc->mlx_sg_nseg * sc->mlx_maxiop; 245 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */ 246 1, 0, /* alignment, boundary */ 247 BUS_SPACE_MAXADDR, /* lowaddr */ 248 BUS_SPACE_MAXADDR, /* highaddr */ 249 NULL, NULL, /* filter, filterarg */ 250 segsize, 1, /* maxsize, nsegments */ 251 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 252 0, /* flags */ 253 &sc->mlx_sg_dmat); 254 if (error != 0) { 255 device_printf(sc->mlx_dev, "can't allocate scatter/gather DMA tag\n"); 256 return(ENOMEM); 257 } 258 259 /* 260 * Allocate enough s/g maps for all commands and permanently map them into 261 * controller-visible space. 262 * 263 * XXX this assumes we can get enough space for all the s/g maps in one 264 * contiguous slab. We may need to switch to a more complex arrangement where 265 * we allocate in smaller chunks and keep a lookup table from slot to bus address. 266 */ 267 error = bus_dmamem_alloc(sc->mlx_sg_dmat, (void **)&sc->mlx_sgtable, BUS_DMA_NOWAIT, &sc->mlx_sg_dmamap); 268 if (error) { 269 device_printf(sc->mlx_dev, "can't allocate s/g table\n"); 270 return(ENOMEM); 271 } 272 bus_dmamap_load(sc->mlx_sg_dmat, sc->mlx_sg_dmamap, sc->mlx_sgtable, segsize, mlx_dma_map_sg, sc, 0); 273 return(0); 274} 275 276/******************************************************************************** 277 * Initialise the controller and softc 278 */ 279int 280mlx_attach(struct mlx_softc *sc) 281{ 282 struct mlx_enquiry_old *meo; 283 int rid, error, fwminor, hscode, hserror, hsparam1, hsparam2, hsmsg; 284 285 debug_called(1); 286 287 /* 288 * Initialise per-controller queues. 289 */ 290 TAILQ_INIT(&sc->mlx_work); 291 TAILQ_INIT(&sc->mlx_freecmds);
|
292 bufq_init(&sc->mlx_bufq);
|
292 bioq_init(&sc->mlx_bioq); |
293 294 /* 295 * Select accessor methods based on controller interface type. 296 */ 297 switch(sc->mlx_iftype) { 298 case MLX_IFTYPE_2: 299 case MLX_IFTYPE_3: 300 sc->mlx_tryqueue = mlx_v3_tryqueue; 301 sc->mlx_findcomplete = mlx_v3_findcomplete; 302 sc->mlx_intaction = mlx_v3_intaction; 303 sc->mlx_fw_handshake = mlx_v3_fw_handshake; 304 sc->mlx_sg_nseg = MLX_NSEG_OLD; 305 break; 306 case MLX_IFTYPE_4: 307 sc->mlx_tryqueue = mlx_v4_tryqueue; 308 sc->mlx_findcomplete = mlx_v4_findcomplete; 309 sc->mlx_intaction = mlx_v4_intaction; 310 sc->mlx_fw_handshake = mlx_v4_fw_handshake; 311 sc->mlx_sg_nseg = MLX_NSEG_NEW; 312 break; 313 case MLX_IFTYPE_5: 314 sc->mlx_tryqueue = mlx_v5_tryqueue; 315 sc->mlx_findcomplete = mlx_v5_findcomplete; 316 sc->mlx_intaction = mlx_v5_intaction; 317 sc->mlx_fw_handshake = mlx_v5_fw_handshake; 318 sc->mlx_sg_nseg = MLX_NSEG_NEW; 319 break; 320 default: 321 return(ENXIO); /* should never happen */ 322 } 323 324 /* disable interrupts before we start talking to the controller */ 325 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); 326 327 /* 328 * Wait for the controller to come ready, handshake with the firmware if required. 329 * This is typically only necessary on platforms where the controller BIOS does not 330 * run. 331 */ 332 hsmsg = 0; 333 DELAY(1000); 334 while ((hscode = sc->mlx_fw_handshake(sc, &hserror, &hsparam1, &hsparam2)) != 0) { 335 /* report first time around... */ 336 if (hsmsg == 0) { 337 device_printf(sc->mlx_dev, "controller initialisation in progress...\n"); 338 hsmsg = 1; 339 } 340 /* did we get a real message? */ 341 if (hscode == 2) { 342 hscode = mlx_fw_message(sc, hserror, hsparam1, hsparam2); 343 /* fatal initialisation error? */ 344 if (hscode != 0) { 345 mlx_free(sc); 346 return(ENXIO); 347 } 348 } 349 } 350 if (hsmsg == 1) 351 device_printf(sc->mlx_dev, "initialisation complete.\n"); 352 353 /* 354 * Allocate and connect our interrupt. 355 */ 356 rid = 0; 357 sc->mlx_irq = bus_alloc_resource(sc->mlx_dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 358 if (sc->mlx_irq == NULL) { 359 device_printf(sc->mlx_dev, "can't allocate interrupt\n"); 360 mlx_free(sc); 361 return(ENXIO); 362 } 363 error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO, mlx_intr, sc, &sc->mlx_intr); 364 if (error) { 365 device_printf(sc->mlx_dev, "can't set up interrupt\n"); 366 mlx_free(sc); 367 return(ENXIO); 368 } 369 370 /* 371 * Create DMA tag for mapping buffers into controller-addressable space. 372 */ 373 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */ 374 1, 0, /* alignment, boundary */ 375 BUS_SPACE_MAXADDR, /* lowaddr */ 376 BUS_SPACE_MAXADDR, /* highaddr */ 377 NULL, NULL, /* filter, filterarg */ 378 MAXBSIZE, sc->mlx_sg_nseg, /* maxsize, nsegments */ 379 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 380 0, /* flags */ 381 &sc->mlx_buffer_dmat); 382 if (error != 0) { 383 device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n"); 384 return(ENOMEM); 385 } 386 387 /* 388 * Create an initial set of s/g mappings. 389 */ 390 sc->mlx_maxiop = 8; 391 error = mlx_sglist_map(sc); 392 if (error != 0) { 393 device_printf(sc->mlx_dev, "can't make initial s/g list mapping\n"); 394 return(error); 395 } 396 397 /* send an ENQUIRY2 to the controller */ 398 if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) { 399 device_printf(sc->mlx_dev, "ENQUIRY2 failed\n"); 400 return(ENXIO); 401 } 402 403 /* 404 * We don't (yet) know where the event log is up to. 405 */ 406 sc->mlx_currevent = -1; 407 408 /* 409 * Do quirk/feature related things. 410 */ 411 fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff; 412 switch(sc->mlx_iftype) { 413 case MLX_IFTYPE_2: 414 /* These controllers don't report the firmware version in the ENQUIRY2 response */ 415 if ((meo = mlx_enquire(sc, MLX_CMD_ENQUIRY_OLD, sizeof(struct mlx_enquiry_old), NULL)) == NULL) { 416 device_printf(sc->mlx_dev, "ENQUIRY_OLD failed\n"); 417 return(ENXIO); 418 } 419 sc->mlx_enq2->me_firmware_id = ('0' << 24) | (0 << 16) | (meo->me_fwminor << 8) | meo->me_fwmajor; 420 free(meo, M_DEVBUF); 421 422 /* XXX require 2.42 or better (PCI) or 2.14 or better (EISA) */ 423 if (meo->me_fwminor < 42) { 424 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n"); 425 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 2.42 or later\n"); 426 } 427 break; 428 case MLX_IFTYPE_3: 429 /* XXX certify 3.52? */ 430 if (fwminor < 51) { 431 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n"); 432 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n"); 433 } 434 break; 435 case MLX_IFTYPE_4: 436 /* XXX certify firmware versions? */ 437 if (fwminor < 6) { 438 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n"); 439 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n"); 440 } 441 break; 442 case MLX_IFTYPE_5: 443 if (fwminor < 7) { 444 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n"); 445 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 5.07 or later\n"); 446 } 447 break; 448 default: 449 return(ENXIO); /* should never happen */ 450 } 451 452 /* 453 * Create the final set of s/g mappings now that we know how many commands 454 * the controller actually supports. 455 */ 456 sc->mlx_maxiop = sc->mlx_enq2->me_max_commands; 457 error = mlx_sglist_map(sc); 458 if (error != 0) { 459 device_printf(sc->mlx_dev, "can't make permanent s/g list mapping\n"); 460 return(error); 461 } 462 463 /* 464 * No user-requested background operation is in progress. 465 */ 466 sc->mlx_background = 0; 467 sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE; 468 469 /* 470 * Create the control device. 471 */ 472 sc->mlx_dev_t = make_dev(&mlx_cdevsw, device_get_unit(sc->mlx_dev), UID_ROOT, GID_OPERATOR, 473 S_IRUSR | S_IWUSR, "mlx%d", device_get_unit(sc->mlx_dev)); 474 475 /* 476 * Start the timeout routine. 477 */ 478 sc->mlx_timeout = timeout(mlx_periodic, sc, hz); 479 480 /* print a little information about the controller */ 481 mlx_describe_controller(sc); 482 483 return(0); 484} 485 486/******************************************************************************** 487 * Locate disk resources and attach children to them. 488 */ 489void 490mlx_startup(struct mlx_softc *sc) 491{ 492 struct mlx_enq_sys_drive *mes; 493 struct mlx_sysdrive *dr; 494 int i, error; 495 496 debug_called(1); 497 498 /* 499 * Scan all the system drives and attach children for those that 500 * don't currently have them. 501 */ 502 mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL); 503 if (mes == NULL) { 504 device_printf(sc->mlx_dev, "error fetching drive status\n"); 505 return; 506 } 507 508 /* iterate over drives returned */ 509 for (i = 0, dr = &sc->mlx_sysdrive[0]; 510 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff); 511 i++, dr++) { 512 /* are we already attached to this drive? */ 513 if (dr->ms_disk == 0) { 514 /* pick up drive information */ 515 dr->ms_size = mes[i].sd_size; 516 dr->ms_raidlevel = mes[i].sd_raidlevel & 0xf; 517 dr->ms_state = mes[i].sd_state; 518 519 /* generate geometry information */ 520 if (sc->mlx_geom == MLX_GEOM_128_32) { 521 dr->ms_heads = 128; 522 dr->ms_sectors = 32; 523 dr->ms_cylinders = dr->ms_size / (128 * 32); 524 } else { /* MLX_GEOM_255/63 */ 525 dr->ms_heads = 255; 526 dr->ms_sectors = 63; 527 dr->ms_cylinders = dr->ms_size / (255 * 63); 528 } 529 dr->ms_disk = device_add_child(sc->mlx_dev, /*"mlxd"*/NULL, -1); 530 if (dr->ms_disk == 0) 531 device_printf(sc->mlx_dev, "device_add_child failed\n"); 532 device_set_ivars(dr->ms_disk, dr); 533 } 534 } 535 free(mes, M_DEVBUF); 536 if ((error = bus_generic_attach(sc->mlx_dev)) != 0) 537 device_printf(sc->mlx_dev, "bus_generic_attach returned %d", error); 538 539 /* mark controller back up */ 540 sc->mlx_state &= ~MLX_STATE_SHUTDOWN; 541 542 /* enable interrupts */ 543 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE); 544} 545 546/******************************************************************************** 547 * Disconnect from the controller completely, in preparation for unload. 548 */ 549int 550mlx_detach(device_t dev) 551{ 552 struct mlx_softc *sc = device_get_softc(dev); 553 struct mlxd_softc *mlxd; 554 int i, s, error; 555 556 debug_called(1); 557 558 error = EBUSY; 559 s = splbio(); 560 if (sc->mlx_state & MLX_STATE_OPEN) 561 goto out; 562 563 for (i = 0; i < MLX_MAXDRIVES; i++) { 564 if (sc->mlx_sysdrive[i].ms_disk != 0) { 565 mlxd = device_get_softc(sc->mlx_sysdrive[i].ms_disk); 566 if (mlxd->mlxd_flags & MLXD_OPEN) { /* drive is mounted, abort detach */ 567 device_printf(sc->mlx_sysdrive[i].ms_disk, "still open, can't detach\n"); 568 goto out; 569 } 570 } 571 } 572 if ((error = mlx_shutdown(dev))) 573 goto out; 574 575 mlx_free(sc); 576 577 error = 0; 578 out: 579 splx(s); 580 return(error); 581} 582 583/******************************************************************************** 584 * Bring the controller down to a dormant state and detach all child devices. 585 * 586 * This function is called before detach, system shutdown, or before performing 587 * an operation which may add or delete system disks. (Call mlx_startup to 588 * resume normal operation.) 589 *
|
590 * Note that we can assume that the bufq on the controller is empty, as we won't
|
590 * Note that we can assume that the bioq on the controller is empty, as we won't |
591 * allow shutdown if any device is open. 592 */ 593int 594mlx_shutdown(device_t dev) 595{ 596 struct mlx_softc *sc = device_get_softc(dev); 597 int i, s, error; 598 599 debug_called(1); 600 601 s = splbio(); 602 error = 0; 603 604 sc->mlx_state |= MLX_STATE_SHUTDOWN; 605 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); 606 607 /* flush controller */ 608 device_printf(sc->mlx_dev, "flushing cache..."); 609 if (mlx_flush(sc)) { 610 printf("failed\n"); 611 } else { 612 printf("done\n"); 613 } 614 615 /* delete all our child devices */ 616 for (i = 0; i < MLX_MAXDRIVES; i++) { 617 if (sc->mlx_sysdrive[i].ms_disk != 0) { 618 if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0) 619 goto out; 620 sc->mlx_sysdrive[i].ms_disk = 0; 621 } 622 } 623 624 out: 625 splx(s); 626 return(error); 627} 628 629/******************************************************************************** 630 * Bring the controller to a quiescent state, ready for system suspend. 631 */ 632int 633mlx_suspend(device_t dev) 634{ 635 struct mlx_softc *sc = device_get_softc(dev); 636 int s; 637 638 debug_called(1); 639 640 s = splbio(); 641 sc->mlx_state |= MLX_STATE_SUSPEND; 642 643 /* flush controller */ 644 device_printf(sc->mlx_dev, "flushing cache..."); 645 printf("%s\n", mlx_flush(sc) ? "failed" : "done"); 646 647 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE); 648 splx(s); 649 650 return(0); 651} 652 653/******************************************************************************** 654 * Bring the controller back to a state ready for operation. 655 */ 656int 657mlx_resume(device_t dev) 658{ 659 struct mlx_softc *sc = device_get_softc(dev); 660 661 debug_called(1); 662 663 sc->mlx_state &= ~MLX_STATE_SUSPEND; 664 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE); 665 666 return(0); 667} 668 669/******************************************************************************* 670 * Take an interrupt, or be poked by other code to look for interrupt-worthy 671 * status. 672 */ 673void 674mlx_intr(void *arg) 675{ 676 struct mlx_softc *sc = (struct mlx_softc *)arg; 677 678 debug_called(1); 679 680 /* collect finished commands, queue anything waiting */ 681 mlx_done(sc); 682}; 683 684/******************************************************************************* 685 * Receive a buf structure from a child device and queue it on a particular 686 * disk resource, then poke the disk resource to start as much work as it can. 687 */ 688int
|
689mlx_submit_buf(struct mlx_softc *sc, struct buf *bp)
|
689mlx_submit_buf(struct mlx_softc *sc, struct bio *bp) |
690{ 691 int s; 692 693 debug_called(1); 694 695 s = splbio();
|
696 bufq_insert_tail(&sc->mlx_bufq, bp);
|
696 bioq_insert_tail(&sc->mlx_bioq, bp); |
697 sc->mlx_waitbufs++; 698 splx(s); 699 mlx_startio(sc); 700 return(0); 701} 702 703/******************************************************************************** 704 * Accept an open operation on the control device. 705 */ 706int 707mlx_open(dev_t dev, int flags, int fmt, struct proc *p) 708{ 709 int unit = minor(dev); 710 struct mlx_softc *sc = devclass_get_softc(mlx_devclass, unit); 711 712 sc->mlx_state |= MLX_STATE_OPEN; 713 return(0); 714} 715 716/******************************************************************************** 717 * Accept the last close on the control device. 718 */ 719int 720mlx_close(dev_t dev, int flags, int fmt, struct proc *p) 721{ 722 int unit = minor(dev); 723 struct mlx_softc *sc = devclass_get_softc(mlx_devclass, unit); 724 725 sc->mlx_state &= ~MLX_STATE_OPEN; 726 return (0); 727} 728 729/******************************************************************************** 730 * Handle controller-specific control operations. 731 */ 732int 733mlx_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) 734{ 735 int unit = minor(dev); 736 struct mlx_softc *sc = devclass_get_softc(mlx_devclass, unit); 737 struct mlx_rebuild_request *rb = (struct mlx_rebuild_request *)addr; 738 struct mlx_rebuild_status *rs = (struct mlx_rebuild_status *)addr; 739 int *arg = (int *)addr; 740 struct mlx_pause *mp; 741 struct mlx_sysdrive *dr; 742 struct mlxd_softc *mlxd; 743 int i, error; 744 745 switch(cmd) { 746 /* 747 * Enumerate connected system drives; returns the first system drive's 748 * unit number if *arg is -1, or the next unit after *arg if it's 749 * a valid unit on this controller. 750 */ 751 case MLX_NEXT_CHILD: 752 /* search system drives */ 753 for (i = 0; i < MLX_MAXDRIVES; i++) { 754 /* is this one attached? */ 755 if (sc->mlx_sysdrive[i].ms_disk != 0) { 756 /* looking for the next one we come across? */ 757 if (*arg == -1) { 758 *arg = device_get_unit(sc->mlx_sysdrive[0].ms_disk); 759 return(0); 760 } 761 /* we want the one after this one */ 762 if (*arg == device_get_unit(sc->mlx_sysdrive[i].ms_disk)) 763 *arg = -1; 764 } 765 } 766 return(ENOENT); 767 768 /* 769 * Scan the controller to see whether new drives have appeared. 770 */ 771 case MLX_RESCAN_DRIVES: 772 mlx_startup(sc); 773 return(0); 774 775 /* 776 * Disconnect from the specified drive; it may be about to go 777 * away. 778 */ 779 case MLX_DETACH_DRIVE: /* detach one drive */ 780 781 if (((dr = mlx_findunit(sc, *arg)) == NULL) || 782 ((mlxd = device_get_softc(dr->ms_disk)) == NULL)) 783 return(ENOENT); 784 785 device_printf(dr->ms_disk, "detaching..."); 786 error = 0; 787 if (mlxd->mlxd_flags & MLXD_OPEN) { 788 error = EBUSY; 789 goto detach_out; 790 } 791 792 /* flush controller */ 793 if (mlx_flush(sc)) { 794 error = EBUSY; 795 goto detach_out; 796 } 797 798 /* nuke drive */ 799 if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0) 800 goto detach_out; 801 dr->ms_disk = 0; 802 803 detach_out: 804 if (error) { 805 printf("failed\n"); 806 } else { 807 printf("done\n"); 808 } 809 return(error); 810 811 /* 812 * Pause one or more SCSI channels for a period of time, to assist 813 * in the process of hot-swapping devices. 814 * 815 * Note that at least the 3.51 firmware on the DAC960PL doesn't seem 816 * to do this right. 817 */ 818 case MLX_PAUSE_CHANNEL: /* schedule a channel pause */ 819 /* Does this command work on this firmware? */ 820 if (!(sc->mlx_feature & MLX_FEAT_PAUSEWORKS)) 821 return(EOPNOTSUPP); 822 823 mp = (struct mlx_pause *)addr; 824 if ((mp->mp_which == MLX_PAUSE_CANCEL) && (sc->mlx_pause.mp_when != 0)) { 825 /* cancel a pending pause operation */ 826 sc->mlx_pause.mp_which = 0; 827 } else { 828 /* fix for legal channels */ 829 mp->mp_which &= ((1 << sc->mlx_enq2->me_actual_channels) -1); 830 /* check time values */ 831 if ((mp->mp_when < 0) || (mp->mp_when > 3600)) 832 return(EINVAL); 833 if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30))) 834 return(EINVAL); 835 836 /* check for a pause currently running */ 837 if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0)) 838 return(EBUSY); 839 840 /* looks ok, go with it */ 841 sc->mlx_pause.mp_which = mp->mp_which; 842 sc->mlx_pause.mp_when = time_second + mp->mp_when; 843 sc->mlx_pause.mp_howlong = sc->mlx_pause.mp_when + mp->mp_howlong; 844 } 845 return(0); 846 847 /* 848 * Accept a command passthrough-style. 849 */ 850 case MLX_COMMAND: 851 return(mlx_user_command(sc, (struct mlx_usercommand *)addr)); 852 853 /* 854 * Start a rebuild on a given SCSI disk 855 */ 856 case MLX_REBUILDASYNC: 857 if (sc->mlx_background != 0) { 858 rb->rr_status = 0x0106; 859 return(EBUSY); 860 } 861 rb->rr_status = mlx_rebuild(sc, rb->rr_channel, rb->rr_target); 862 switch (rb->rr_status) { 863 case 0: 864 error = 0; 865 break; 866 case 0x10000: 867 error = ENOMEM; /* couldn't set up the command */ 868 break; 869 case 0x0002: 870 error = EBUSY; 871 break; 872 case 0x0104: 873 error = EIO; 874 break; 875 case 0x0105: 876 error = ERANGE; 877 break; 878 case 0x0106: 879 error = EBUSY; 880 break; 881 default: 882 error = EINVAL; 883 break; 884 } 885 if (error == 0) 886 sc->mlx_background = MLX_BACKGROUND_REBUILD; 887 return(error); 888 889 /* 890 * Get the status of the current rebuild or consistency check. 891 */ 892 case MLX_REBUILDSTAT: 893 *rs = sc->mlx_rebuildstat; 894 return(0); 895 896 /* 897 * Return the per-controller system drive number matching the 898 * disk device number in (arg), if it happens to belong to us. 899 */ 900 case MLX_GET_SYSDRIVE: 901 error = ENOENT; 902 mlxd = (struct mlxd_softc *)devclass_get_softc(mlxd_devclass, *arg); 903 if ((mlxd != NULL) && (mlxd->mlxd_drive >= sc->mlx_sysdrive) && 904 (mlxd->mlxd_drive < (sc->mlx_sysdrive + MLX_MAXDRIVES))) { 905 error = 0; 906 *arg = mlxd->mlxd_drive - sc->mlx_sysdrive; 907 } 908 return(error); 909 910 default: 911 return(ENOTTY); 912 } 913} 914 915/******************************************************************************** 916 * Handle operations requested by a System Drive connected to this controller. 917 */ 918int 919mlx_submit_ioctl(struct mlx_softc *sc, struct mlx_sysdrive *drive, u_long cmd, 920 caddr_t addr, int32_t flag, struct proc *p) 921{ 922 int *arg = (int *)addr; 923 int error, result; 924 925 switch(cmd) { 926 /* 927 * Return the current status of this drive. 928 */ 929 case MLXD_STATUS: 930 *arg = drive->ms_state; 931 return(0); 932 933 /* 934 * Start a background consistency check on this drive. 935 */ 936 case MLXD_CHECKASYNC: /* start a background consistency check */ 937 if (sc->mlx_background != 0) { 938 *arg = 0x0106; 939 return(EBUSY); 940 } 941 result = mlx_check(sc, drive - &sc->mlx_sysdrive[0]); 942 switch (result) { 943 case 0: 944 error = 0; 945 break; 946 case 0x10000: 947 error = ENOMEM; /* couldn't set up the command */ 948 break; 949 case 0x0002: 950 error = EIO; 951 break; 952 case 0x0105: 953 error = ERANGE; 954 break; 955 case 0x0106: 956 error = EBUSY; 957 break; 958 default: 959 error = EINVAL; 960 break; 961 } 962 if (error == 0) 963 sc->mlx_background = MLX_BACKGROUND_CHECK; 964 *arg = result; 965 return(error); 966 967 } 968 return(ENOIOCTL); 969} 970 971 972/******************************************************************************** 973 ******************************************************************************** 974 Status Monitoring 975 ******************************************************************************** 976 ********************************************************************************/ 977 978/******************************************************************************** 979 * Fire off commands to periodically check the status of connected drives. 980 */ 981static void 982mlx_periodic(void *data) 983{ 984 struct mlx_softc *sc = (struct mlx_softc *)data; 985 986 debug_called(1); 987 988 /* 989 * Run a bus pause? 990 */ 991 if ((sc->mlx_pause.mp_which != 0) && 992 (sc->mlx_pause.mp_when > 0) && 993 (time_second >= sc->mlx_pause.mp_when)){ 994 995 mlx_pause_action(sc); /* pause is running */ 996 sc->mlx_pause.mp_when = 0; 997 sysbeep(500, hz); 998 999 /* 1000 * Bus pause still running? 1001 */ 1002 } else if ((sc->mlx_pause.mp_which != 0) && 1003 (sc->mlx_pause.mp_when == 0)) { 1004 1005 /* time to stop bus pause? */ 1006 if (time_second >= sc->mlx_pause.mp_howlong) { 1007 mlx_pause_action(sc); 1008 sc->mlx_pause.mp_which = 0; /* pause is complete */ 1009 sysbeep(500, hz); 1010 } else { 1011 sysbeep((time_second % 5) * 100 + 500, hz/8); 1012 } 1013 1014 /* 1015 * Run normal periodic activities? 1016 */ 1017 } else if (time_second > (sc->mlx_lastpoll + 10)) { 1018 sc->mlx_lastpoll = time_second; 1019 1020 /* 1021 * Check controller status. 1022 * 1023 * XXX Note that this may not actually launch a command in situations of high load. 1024 */ 1025 mlx_enquire(sc, (sc->mlx_iftype == MLX_IFTYPE_2) ? MLX_CMD_ENQUIRY_OLD : MLX_CMD_ENQUIRY, 1026 imax(sizeof(struct mlx_enquiry), sizeof(struct mlx_enquiry_old)), mlx_periodic_enquiry); 1027 1028 /* 1029 * Check system drive status. 1030 * 1031 * XXX This might be better left to event-driven detection, eg. I/O to an offline 1032 * drive will detect it's offline, rebuilds etc. should detect the drive is back 1033 * online. 1034 */ 1035 mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(struct mlx_enq_sys_drive) * MLX_MAXDRIVES, 1036 mlx_periodic_enquiry); 1037 1038 } 1039 1040 /* get drive rebuild/check status */ 1041 /* XXX should check sc->mlx_background if this is only valid while in progress */ 1042 mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild); 1043 1044 /* deal with possibly-missed interrupts and timed-out commands */ 1045 mlx_done(sc); 1046 1047 /* reschedule another poll next second or so */ 1048 sc->mlx_timeout = timeout(mlx_periodic, sc, hz); 1049} 1050 1051/******************************************************************************** 1052 * Handle the result of an ENQUIRY command instigated by periodic status polling. 1053 */ 1054static void 1055mlx_periodic_enquiry(struct mlx_command *mc) 1056{ 1057 struct mlx_softc *sc = mc->mc_sc; 1058 1059 debug_called(1); 1060 1061 /* Command completed OK? */ 1062 if (mc->mc_status != 0) { 1063 device_printf(sc->mlx_dev, "periodic enquiry failed - %s\n", mlx_diagnose_command(mc)); 1064 goto out; 1065 } 1066 1067 /* respond to command */ 1068 switch(mc->mc_mailbox[0]) { 1069 /* 1070 * This is currently a bit fruitless, as we don't know how to extract the eventlog 1071 * pointer yet. 1072 */ 1073 case MLX_CMD_ENQUIRY_OLD: 1074 { 1075 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data; 1076 struct mlx_enquiry_old *meo = (struct mlx_enquiry_old *)mc->mc_data; 1077 int i; 1078 1079 /* convert data in-place to new format */ 1080 for (i = (sizeof(me->me_dead) / sizeof(me->me_dead[0])) - 1; i >= 0; i--) { 1081 me->me_dead[i].dd_chan = meo->me_dead[i].dd_chan; 1082 me->me_dead[i].dd_targ = meo->me_dead[i].dd_targ; 1083 } 1084 me->me_misc_flags = 0; 1085 me->me_rebuild_count = meo->me_rebuild_count; 1086 me->me_dead_count = meo->me_dead_count; 1087 me->me_critical_sd_count = meo->me_critical_sd_count; 1088 me->me_event_log_seq_num = 0; 1089 me->me_offline_sd_count = meo->me_offline_sd_count; 1090 me->me_max_commands = meo->me_max_commands; 1091 me->me_rebuild_flag = meo->me_rebuild_flag; 1092 me->me_fwmajor = meo->me_fwmajor; 1093 me->me_fwminor = meo->me_fwminor; 1094 me->me_status_flags = meo->me_status_flags; 1095 me->me_flash_age = meo->me_flash_age; 1096 for (i = (sizeof(me->me_drvsize) / sizeof(me->me_drvsize[0])) - 1; i >= 0; i--) { 1097 if (i > ((sizeof(meo->me_drvsize) / sizeof(meo->me_drvsize[0])) - 1)) { 1098 me->me_drvsize[i] = 0; /* drive beyond supported range */ 1099 } else { 1100 me->me_drvsize[i] = meo->me_drvsize[i]; 1101 } 1102 } 1103 me->me_num_sys_drvs = meo->me_num_sys_drvs; 1104 } 1105 /* FALLTHROUGH */ 1106 1107 /* 1108 * Generic controller status update. We could do more with this than just 1109 * checking the event log. 1110 */ 1111 case MLX_CMD_ENQUIRY: 1112 { 1113 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data; 1114 1115 if (sc->mlx_currevent == -1) { 1116 /* initialise our view of the event log */ 1117 sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num; 1118 } else if (me->me_event_log_seq_num != sc->mlx_lastevent) { 1119 /* record where current events are up to */ 1120 sc->mlx_currevent = me->me_event_log_seq_num; 1121 debug(1, "event log pointer was %d, now %d\n", sc->mlx_lastevent, sc->mlx_currevent); 1122 1123 /* drain new eventlog entries */ 1124 mlx_periodic_eventlog_poll(sc); 1125 } 1126 break; 1127 } 1128 case MLX_CMD_ENQSYSDRIVE: 1129 { 1130 struct mlx_enq_sys_drive *mes = (struct mlx_enq_sys_drive *)mc->mc_data; 1131 struct mlx_sysdrive *dr; 1132 int i; 1133 1134 for (i = 0, dr = &sc->mlx_sysdrive[0]; 1135 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff); 1136 i++) { 1137 1138 /* has state been changed by controller? */ 1139 if (dr->ms_state != mes[i].sd_state) { 1140 switch(mes[i].sd_state) { 1141 case MLX_SYSD_OFFLINE: 1142 device_printf(dr->ms_disk, "drive offline\n"); 1143 break; 1144 case MLX_SYSD_ONLINE: 1145 device_printf(dr->ms_disk, "drive online\n"); 1146 break; 1147 case MLX_SYSD_CRITICAL: 1148 device_printf(dr->ms_disk, "drive critical\n"); 1149 break; 1150 } 1151 /* save new state */ 1152 dr->ms_state = mes[i].sd_state; 1153 } 1154 } 1155 break; 1156 } 1157 default: 1158 device_printf(sc->mlx_dev, "%s: unknown command 0x%x", __FUNCTION__, mc->mc_mailbox[0]); 1159 break; 1160 } 1161 1162 out: 1163 free(mc->mc_data, M_DEVBUF); 1164 mlx_releasecmd(mc); 1165} 1166 1167/******************************************************************************** 1168 * Instigate a poll for one event log message on (sc). 1169 * We only poll for one message at a time, to keep our command usage down. 1170 */ 1171static void 1172mlx_periodic_eventlog_poll(struct mlx_softc *sc) 1173{ 1174 struct mlx_command *mc; 1175 void *result = NULL; 1176 int error; 1177 1178 debug_called(1); 1179 1180 /* get ourselves a command buffer */ 1181 error = 1; 1182 if ((mc = mlx_alloccmd(sc)) == NULL) 1183 goto out; 1184 /* allocate the response structure */ 1185 if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL) 1186 goto out; 1187 /* get a command slot */ 1188 if (mlx_getslot(mc)) 1189 goto out; 1190 1191 /* map the command so the controller can see it */ 1192 mc->mc_data = result; 1193 mc->mc_length = /*sizeof(struct mlx_eventlog_entry)*/1024; 1194 mlx_mapcmd(mc); 1195 1196 /* build the command to get one entry */ 1197 mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1, sc->mlx_lastevent, 0, 0, mc->mc_dataphys, 0); 1198 mc->mc_complete = mlx_periodic_eventlog_respond; 1199 mc->mc_private = mc; 1200 1201 /* start the command */ 1202 if ((error = mlx_start(mc)) != 0) 1203 goto out; 1204 1205 error = 0; /* success */ 1206 out: 1207 if (error != 0) { 1208 if (mc != NULL) 1209 mlx_releasecmd(mc); 1210 if (result != NULL) 1211 free(result, M_DEVBUF); 1212 } 1213} 1214 1215/******************************************************************************** 1216 * Handle the result of polling for a log message, generate diagnostic output. 1217 * If this wasn't the last message waiting for us, we'll go collect another. 1218 */ 1219static char *mlx_sense_messages[] = { 1220 "because write recovery failed", 1221 "because of SCSI bus reset failure", 1222 "because of double check condition", 1223 "because it was removed", 1224 "because of gross error on SCSI chip", 1225 "because of bad tag returned from drive", 1226 "because of timeout on SCSI command", 1227 "because of reset SCSI command issued from system", 1228 "because busy or parity error count exceeded limit", 1229 "because of 'kill drive' command from system", 1230 "because of selection timeout", 1231 "due to SCSI phase sequence error", 1232 "due to unknown status" 1233}; 1234 1235static void 1236mlx_periodic_eventlog_respond(struct mlx_command *mc) 1237{ 1238 struct mlx_softc *sc = mc->mc_sc; 1239 struct mlx_eventlog_entry *el = (struct mlx_eventlog_entry *)mc->mc_data; 1240 char *reason; 1241 1242 debug_called(1); 1243 1244 sc->mlx_lastevent++; /* next message... */ 1245 if (mc->mc_status == 0) { 1246 1247 /* handle event log message */ 1248 switch(el->el_type) { 1249 /* 1250 * This is the only sort of message we understand at the moment. 1251 * The tests here are probably incomplete. 1252 */ 1253 case MLX_LOGMSG_SENSE: /* sense data */ 1254 /* Mylex vendor-specific message indicating a drive was killed? */ 1255 if ((el->el_sensekey == 9) && 1256 (el->el_asc == 0x80)) { 1257 if (el->el_asq < (sizeof(mlx_sense_messages) / sizeof(mlx_sense_messages[0]))) { 1258 reason = mlx_sense_messages[el->el_asq]; 1259 } else { 1260 reason = "for unknown reason"; 1261 } 1262 device_printf(sc->mlx_dev, "physical drive %d:%d killed %s\n", 1263 el->el_channel, el->el_target, reason); 1264 } 1265 /* SCSI drive was reset? */ 1266 if ((el->el_sensekey == 6) && (el->el_asc == 0x29)) { 1267 device_printf(sc->mlx_dev, "physical drive %d:%d reset\n", 1268 el->el_channel, el->el_target); 1269 } 1270 /* SCSI drive error? */ 1271 if (!((el->el_sensekey == 0) || 1272 ((el->el_sensekey == 2) && 1273 (el->el_asc == 0x04) && 1274 ((el->el_asq == 0x01) || 1275 (el->el_asq == 0x02))))) { 1276 device_printf(sc->mlx_dev, "physical drive %d:%d error log: sense = %d asc = %x asq = %x\n", 1277 el->el_channel, el->el_target, el->el_sensekey, el->el_asc, el->el_asq); 1278 device_printf(sc->mlx_dev, " info %4D csi %4D\n", el->el_information, ":", el->el_csi, ":"); 1279 } 1280 break; 1281 1282 default: 1283 device_printf(sc->mlx_dev, "unknown log message type 0x%x\n", el->el_type); 1284 break; 1285 } 1286 } else { 1287 device_printf(sc->mlx_dev, "error reading message log - %s\n", mlx_diagnose_command(mc)); 1288 panic("log operation failed: lastevent = %d, currevent = %d", 1289 sc->mlx_lastevent, sc->mlx_currevent); 1290 } 1291 1292 /* dispose of command and data */ 1293 free(mc->mc_data, M_DEVBUF); 1294 mlx_releasecmd(mc); 1295 1296 /* is there another message to obtain? */ 1297 if (sc->mlx_lastevent != sc->mlx_currevent) 1298 mlx_periodic_eventlog_poll(sc); 1299} 1300 1301/******************************************************************************** 1302 * Handle check/rebuild operations in progress. 1303 */ 1304static void 1305mlx_periodic_rebuild(struct mlx_command *mc) 1306{ 1307 struct mlx_softc *sc = mc->mc_sc; 1308 struct mlx_rebuild_status *mr = (struct mlx_rebuild_status *)mc->mc_data; 1309 1310 switch(mc->mc_status) { 1311 case 0: /* operation running, update stats */ 1312 sc->mlx_rebuildstat = *mr; 1313 1314 /* spontaneous rebuild/check? */ 1315 if (sc->mlx_background == 0) { 1316 sc->mlx_background = MLX_BACKGROUND_SPONTANEOUS; 1317 device_printf(sc->mlx_dev, "background check/rebuild operation started\n"); 1318 } 1319 break; 1320 1321 case 0x0105: /* nothing running, finalise stats and report */ 1322 switch(sc->mlx_background) { 1323 case MLX_BACKGROUND_CHECK: 1324 device_printf(sc->mlx_dev, "consistency check completed\n"); /* XXX print drive? */ 1325 break; 1326 case MLX_BACKGROUND_REBUILD: 1327 device_printf(sc->mlx_dev, "drive rebuild completed\n"); /* XXX print channel/target? */ 1328 break; 1329 case MLX_BACKGROUND_SPONTANEOUS: 1330 default: 1331 /* if we have previously been non-idle, report the transition */ 1332 if (sc->mlx_rebuildstat.rs_code != MLX_REBUILDSTAT_IDLE) { 1333 device_printf(sc->mlx_dev, "background check/rebuild operation completed\n"); 1334 } 1335 } 1336 sc->mlx_background = 0; 1337 sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE; 1338 break; 1339 } 1340 free(mc->mc_data, M_DEVBUF); 1341 mlx_releasecmd(mc); 1342} 1343 1344/******************************************************************************** 1345 ******************************************************************************** 1346 Channel Pause 1347 ******************************************************************************** 1348 ********************************************************************************/ 1349 1350/******************************************************************************** 1351 * It's time to perform a channel pause action for (sc), either start or stop 1352 * the pause. 1353 */ 1354static void 1355mlx_pause_action(struct mlx_softc *sc) 1356{ 1357 struct mlx_command *mc; 1358 int failsafe, i, command; 1359 1360 /* What are we doing here? */ 1361 if (sc->mlx_pause.mp_when == 0) { 1362 command = MLX_CMD_STARTCHANNEL; 1363 failsafe = 0; 1364 1365 } else { 1366 command = MLX_CMD_STOPCHANNEL; 1367 1368 /* 1369 * Channels will always start again after the failsafe period, 1370 * which is specified in multiples of 30 seconds. 1371 * This constrains us to a maximum pause of 450 seconds. 1372 */ 1373 failsafe = ((sc->mlx_pause.mp_howlong - time_second) + 5) / 30; 1374 if (failsafe > 0xf) { 1375 failsafe = 0xf; 1376 sc->mlx_pause.mp_howlong = time_second + (0xf * 30) - 5; 1377 } 1378 } 1379 1380 /* build commands for every channel requested */ 1381 for (i = 0; i < sc->mlx_enq2->me_actual_channels; i++) { 1382 if ((1 << i) & sc->mlx_pause.mp_which) { 1383 1384 /* get ourselves a command buffer */ 1385 if ((mc = mlx_alloccmd(sc)) == NULL) 1386 goto fail; 1387 /* get a command slot */ 1388 mc->mc_flags |= MLX_CMD_PRIORITY; 1389 if (mlx_getslot(mc)) 1390 goto fail; 1391 1392 /* build the command */ 1393 mlx_make_type2(mc, command, (failsafe << 4) | i, 0, 0, 0, 0, 0, 0, 0); 1394 mc->mc_complete = mlx_pause_done; 1395 mc->mc_private = sc; /* XXX not needed */ 1396 if (mlx_start(mc)) 1397 goto fail; 1398 /* command submitted OK */ 1399 return; 1400 1401 fail: 1402 device_printf(sc->mlx_dev, "%s failed for channel %d\n", 1403 command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", i); 1404 if (mc != NULL) 1405 mlx_releasecmd(mc); 1406 } 1407 } 1408} 1409 1410static void 1411mlx_pause_done(struct mlx_command *mc) 1412{ 1413 struct mlx_softc *sc = mc->mc_sc; 1414 int command = mc->mc_mailbox[0]; 1415 int channel = mc->mc_mailbox[2] & 0xf; 1416 1417 if (mc->mc_status != 0) { 1418 device_printf(sc->mlx_dev, "%s command failed - %s\n", 1419 command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc)); 1420 } else if (command == MLX_CMD_STOPCHANNEL) { 1421 device_printf(sc->mlx_dev, "channel %d pausing for %ld seconds\n", 1422 channel, (long)(sc->mlx_pause.mp_howlong - time_second)); 1423 } else { 1424 device_printf(sc->mlx_dev, "channel %d resuming\n", channel); 1425 } 1426 mlx_releasecmd(mc); 1427} 1428 1429/******************************************************************************** 1430 ******************************************************************************** 1431 Command Submission 1432 ******************************************************************************** 1433 ********************************************************************************/ 1434 1435/******************************************************************************** 1436 * Perform an Enquiry command using a type-3 command buffer and a return a single 1437 * linear result buffer. If the completion function is specified, it will 1438 * be called with the completed command (and the result response will not be 1439 * valid until that point). Otherwise, the command will either be busy-waited 1440 * for (interrupts not enabled), or slept for. 1441 */ 1442static void * 1443mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc)) 1444{ 1445 struct mlx_command *mc; 1446 void *result; 1447 int error; 1448 1449 debug_called(1); 1450 1451 /* get ourselves a command buffer */ 1452 error = 1; 1453 result = NULL; 1454 if ((mc = mlx_alloccmd(sc)) == NULL) 1455 goto out; 1456 /* allocate the response structure */ 1457 if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL) 1458 goto out; 1459 /* get a command slot */ 1460 mc->mc_flags |= MLX_CMD_PRIORITY | MLX_CMD_DATAOUT; 1461 if (mlx_getslot(mc)) 1462 goto out; 1463 1464 /* map the command so the controller can see it */ 1465 mc->mc_data = result; 1466 mc->mc_length = bufsize; 1467 mlx_mapcmd(mc); 1468 1469 /* build an enquiry command */ 1470 mlx_make_type2(mc, command, 0, 0, 0, 0, 0, 0, mc->mc_dataphys, 0); 1471 1472 /* do we want a completion callback? */ 1473 if (complete != NULL) { 1474 mc->mc_complete = complete; 1475 mc->mc_private = mc; 1476 if ((error = mlx_start(mc)) != 0) 1477 goto out; 1478 } else { 1479 /* run the command in either polled or wait mode */ 1480 if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc)) 1481 goto out; 1482 1483 /* command completed OK? */ 1484 if (mc->mc_status != 0) { 1485 device_printf(sc->mlx_dev, "ENQUIRY failed - %s\n", mlx_diagnose_command(mc)); 1486 goto out; 1487 } 1488 } 1489 error = 0; /* success */ 1490 out: 1491 /* we got a command, but nobody else will free it */ 1492 if ((complete == NULL) && (mc != NULL)) 1493 mlx_releasecmd(mc); 1494 /* we got an error, and we allocated a result */ 1495 if ((error != 0) && (result != NULL)) { 1496 free(result, M_DEVBUF); 1497 result = NULL; 1498 } 1499 return(result); 1500} 1501 1502 1503/******************************************************************************** 1504 * Perform a Flush command on the nominated controller. 1505 * 1506 * May be called with interrupts enabled or disabled; will not return until 1507 * the flush operation completes or fails. 1508 */ 1509static int 1510mlx_flush(struct mlx_softc *sc) 1511{ 1512 struct mlx_command *mc; 1513 int error; 1514 1515 debug_called(1); 1516 1517 /* get ourselves a command buffer */ 1518 error = 1; 1519 if ((mc = mlx_alloccmd(sc)) == NULL) 1520 goto out; 1521 /* get a command slot */ 1522 if (mlx_getslot(mc)) 1523 goto out; 1524 1525 /* build a flush command */ 1526 mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0); 1527 1528 /* can't assume that interrupts are going to work here, so play it safe */ 1529 if (mlx_poll_command(mc)) 1530 goto out; 1531 1532 /* command completed OK? */ 1533 if (mc->mc_status != 0) { 1534 device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc)); 1535 goto out; 1536 } 1537 1538 error = 0; /* success */ 1539 out: 1540 if (mc != NULL) 1541 mlx_releasecmd(mc); 1542 return(error); 1543} 1544 1545/******************************************************************************** 1546 * Start a background consistency check on (drive). 1547 * 1548 * May be called with interrupts enabled or disabled; will return as soon as the 1549 * operation has started or been refused. 1550 */ 1551static int 1552mlx_check(struct mlx_softc *sc, int drive) 1553{ 1554 struct mlx_command *mc; 1555 int error; 1556 1557 debug_called(1); 1558 1559 /* get ourselves a command buffer */ 1560 error = 0x10000; 1561 if ((mc = mlx_alloccmd(sc)) == NULL) 1562 goto out; 1563 /* get a command slot */ 1564 if (mlx_getslot(mc)) 1565 goto out; 1566 1567 /* build a checkasync command, set the "fix it" flag */ 1568 mlx_make_type2(mc, MLX_CMD_CHECKASYNC, 0, 0, 0, 0, 0, drive | 0x80, 0, 0); 1569 1570 /* start the command and wait for it to be returned */ 1571 if (mlx_wait_command(mc)) 1572 goto out; 1573 1574 /* command completed OK? */ 1575 if (mc->mc_status != 0) { 1576 device_printf(sc->mlx_dev, "CHECK ASYNC failed - %s\n", mlx_diagnose_command(mc)); 1577 } else { 1578 device_printf(sc->mlx_sysdrive[drive].ms_disk, "consistency check started"); 1579 } 1580 error = mc->mc_status; 1581 1582 out: 1583 if (mc != NULL) 1584 mlx_releasecmd(mc); 1585 return(error); 1586} 1587 1588/******************************************************************************** 1589 * Start a background rebuild of the physical drive at (channel),(target). 1590 * 1591 * May be called with interrupts enabled or disabled; will return as soon as the 1592 * operation has started or been refused. 1593 */ 1594static int 1595mlx_rebuild(struct mlx_softc *sc, int channel, int target) 1596{ 1597 struct mlx_command *mc; 1598 int error; 1599 1600 debug_called(1); 1601 1602 /* get ourselves a command buffer */ 1603 error = 0x10000; 1604 if ((mc = mlx_alloccmd(sc)) == NULL) 1605 goto out; 1606 /* get a command slot */ 1607 if (mlx_getslot(mc)) 1608 goto out; 1609 1610 /* build a checkasync command, set the "fix it" flag */ 1611 mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0, 0, 0); 1612 1613 /* start the command and wait for it to be returned */ 1614 if (mlx_wait_command(mc)) 1615 goto out; 1616 1617 /* command completed OK? */ 1618 if (mc->mc_status != 0) { 1619 device_printf(sc->mlx_dev, "REBUILD ASYNC failed - %s\n", mlx_diagnose_command(mc)); 1620 } else { 1621 device_printf(sc->mlx_dev, "drive rebuild started for %d:%d\n", channel, target); 1622 } 1623 error = mc->mc_status; 1624 1625 out: 1626 if (mc != NULL) 1627 mlx_releasecmd(mc); 1628 return(error); 1629} 1630 1631/******************************************************************************** 1632 * Run the command (mc) and return when it completes. 1633 * 1634 * Interrupts need to be enabled; returns nonzero on error. 1635 */ 1636static int 1637mlx_wait_command(struct mlx_command *mc) 1638{ 1639 struct mlx_softc *sc = mc->mc_sc; 1640 int error, count; 1641 1642 debug_called(1); 1643 1644 mc->mc_complete = NULL; 1645 mc->mc_private = mc; /* wake us when you're done */ 1646 if ((error = mlx_start(mc)) != 0) 1647 return(error); 1648 1649 count = 0; 1650 /* XXX better timeout? */ 1651 while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) { 1652 tsleep(mc->mc_private, PRIBIO | PCATCH, "mlxwcmd", hz); 1653 } 1654 1655 if (mc->mc_status != 0) { 1656 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc)); 1657 return(EIO); 1658 } 1659 return(0); 1660} 1661 1662 1663/******************************************************************************** 1664 * Start the command (mc) and busy-wait for it to complete. 1665 * 1666 * Should only be used when interrupts can't be relied upon. Returns 0 on 1667 * success, nonzero on error. 1668 * Successfully completed commands are dequeued. 1669 */ 1670static int 1671mlx_poll_command(struct mlx_command *mc) 1672{ 1673 struct mlx_softc *sc = mc->mc_sc; 1674 int error, count, s; 1675 1676 debug_called(1); 1677 1678 mc->mc_complete = NULL; 1679 mc->mc_private = NULL; /* we will poll for it */ 1680 if ((error = mlx_start(mc)) != 0) 1681 return(error); 1682 1683 count = 0; 1684 do { 1685 /* poll for completion */ 1686 mlx_done(mc->mc_sc); 1687 1688 } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000)); 1689 if (mc->mc_status != MLX_STATUS_BUSY) { 1690 s = splbio(); 1691 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link); 1692 splx(s); 1693 return(0); 1694 } 1695 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc)); 1696 return(EIO); 1697} 1698 1699/******************************************************************************** 1700 * Pull as much work off the softc's work queue as possible and give it to the 1701 * controller. Leave a couple of slots free for emergencies. 1702 * 1703 * Must be called at splbio or in an equivalent fashion that prevents
|
1704 * reentry or activity on the bufq.
|
1704 * reentry or activity on the bioq. |
1705 */ 1706static void 1707mlx_startio(struct mlx_softc *sc) 1708{ 1709 struct mlx_command *mc; 1710 struct mlxd_softc *mlxd;
|
1711 struct buf *bp;
|
1711 struct bio *bp; |
1712 int blkcount; 1713 int driveno; 1714 int cmd; 1715 int s; 1716 1717 /* avoid reentrancy */ 1718 if (mlx_lock_tas(sc, MLX_LOCK_STARTING)) 1719 return; 1720 1721 /* spin until something prevents us from doing any work */ 1722 s = splbio(); 1723 for (;;) { 1724 1725 /* see if there's work to be done */
|
1726 if ((bp = bufq_first(&sc->mlx_bufq)) == NULL)
|
1726 if ((bp = bioq_first(&sc->mlx_bioq)) == NULL) |
1727 break; 1728 /* get a command */ 1729 if ((mc = mlx_alloccmd(sc)) == NULL) 1730 break; 1731 /* get a slot for the command */ 1732 if (mlx_getslot(mc) != 0) { 1733 mlx_releasecmd(mc); 1734 break; 1735 } 1736 /* get the buf containing our work */
|
1737 bufq_remove(&sc->mlx_bufq, bp);
|
1737 bioq_remove(&sc->mlx_bioq, bp); |
1738 sc->mlx_waitbufs--; 1739 splx(s); 1740 1741 /* connect the buf to the command */ 1742 mc->mc_complete = mlx_completeio; 1743 mc->mc_private = bp;
|
1744 mc->mc_data = bp->b_data;
1745 mc->mc_length = bp->b_bcount;
1746 if (bp->b_iocmd == BIO_READ) {
|
1744 mc->mc_data = bp->bio_data; 1745 mc->mc_length = bp->bio_bcount; 1746 if (bp->bio_cmd == BIO_READ) { |
1747 mc->mc_flags |= MLX_CMD_DATAIN; 1748 cmd = MLX_CMD_READSG; 1749 } else { 1750 mc->mc_flags |= MLX_CMD_DATAOUT; 1751 cmd = MLX_CMD_WRITESG; 1752 } 1753 1754 /* map the command so the controller can work with it */ 1755 mlx_mapcmd(mc); 1756 1757 /* build a suitable I/O command (assumes 512-byte rounded transfers) */
|
1758 mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
|
1758 mlxd = (struct mlxd_softc *)bp->bio_dev->si_drv1; |
1759 driveno = mlxd->mlxd_drive - sc->mlx_sysdrive;
|
1760 blkcount = (bp->b_bcount + MLX_BLKSIZE - 1) / MLX_BLKSIZE;
|
1760 blkcount = (bp->bio_bcount + MLX_BLKSIZE - 1) / MLX_BLKSIZE; |
1761
|
1762 if ((bp->b_pblkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
|
1762 if ((bp->bio_pblkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size) |
1763 device_printf(sc->mlx_dev, "I/O beyond end of unit (%u,%d > %u)\n",
|
1764 bp->b_pblkno, blkcount, sc->mlx_sysdrive[driveno].ms_size);
|
1764 bp->bio_pblkno, blkcount, sc->mlx_sysdrive[driveno].ms_size); |
1765 1766 /* 1767 * Build the I/O command. Note that the SG list type bits are set to zero, 1768 * denoting the format of SG list that we are using. 1769 */ 1770 if (sc->mlx_iftype == MLX_IFTYPE_2) { 1771 mlx_make_type1(mc, (cmd == MLX_CMD_WRITESG) ? MLX_CMD_WRITESG_OLD : MLX_CMD_READSG_OLD, 1772 blkcount & 0xff, /* xfer length low byte */
|
1773 bp->b_pblkno, /* physical block number */
|
1773 bp->bio_pblkno, /* physical block number */ |
1774 driveno, /* target drive number */ 1775 mc->mc_sgphys, /* location of SG list */ 1776 mc->mc_nsgent & 0x3f); /* size of SG list (top 3 bits clear) */ 1777 } else { 1778 mlx_make_type5(mc, cmd, 1779 blkcount & 0xff, /* xfer length low byte */ 1780 (driveno << 3) | ((blkcount >> 8) & 0x07), /* target and length high 3 bits */
|
1781 bp->b_pblkno, /* physical block number */
|
1781 bp->bio_pblkno, /* physical block number */ |
1782 mc->mc_sgphys, /* location of SG list */ 1783 mc->mc_nsgent & 0x3f); /* size of SG list (top 3 bits clear) */ 1784 } 1785 1786 /* try to give command to controller */ 1787 if (mlx_start(mc) != 0) { 1788 /* fail the command */ 1789 mc->mc_status = MLX_STATUS_WEDGED; 1790 mlx_completeio(mc); 1791 } 1792 s = splbio(); 1793 } 1794 splx(s); 1795 mlx_lock_clr(sc, MLX_LOCK_STARTING); 1796} 1797 1798/******************************************************************************** 1799 * Handle completion of an I/O command. 1800 */ 1801static void 1802mlx_completeio(struct mlx_command *mc) 1803{ 1804 struct mlx_softc *sc = mc->mc_sc;
|
1805 struct buf *bp = (struct buf *)mc->mc_private;
1806 struct mlxd_softc *mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
|
1805 struct bio *bp = (struct bio *)mc->mc_private; 1806 struct mlxd_softc *mlxd = (struct mlxd_softc *)bp->bio_dev->si_drv1; |
1807 1808 if (mc->mc_status != MLX_STATUS_OK) { /* could be more verbose here? */
|
1809 bp->b_error = EIO;
1810 bp->b_ioflags |= BIO_ERROR;
|
1809 bp->bio_error = EIO; 1810 bp->bio_flags |= BIO_ERROR; |
1811 1812 switch(mc->mc_status) { 1813 case MLX_STATUS_RDWROFFLINE: /* system drive has gone offline */ 1814 device_printf(mlxd->mlxd_dev, "drive offline\n"); 1815 /* should signal this with a return code */ 1816 mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE; 1817 break; 1818 1819 default: /* other I/O error */ 1820 device_printf(sc->mlx_dev, "I/O error - %s\n", mlx_diagnose_command(mc)); 1821#if 0 1822 device_printf(sc->mlx_dev, " b_bcount %ld blkcount %ld b_pblkno %d\n",
|
1823 bp->b_bcount, bp->b_bcount / MLX_BLKSIZE, bp->b_pblkno);
|
1823 bp->bio_bcount, bp->bio_bcount / MLX_BLKSIZE, bp->bio_pblkno); |
1824 device_printf(sc->mlx_dev, " %13D\n", mc->mc_mailbox, " "); 1825#endif 1826 break; 1827 } 1828 } 1829 mlx_releasecmd(mc); 1830 mlxd_intr(bp); 1831} 1832 1833/******************************************************************************** 1834 * Take a command from user-space and try to run it. 1835 * 1836 * XXX Note that this can't perform very much in the way of error checking, and 1837 * as such, applications _must_ be considered trustworthy. 1838 * XXX Commands using S/G for data are not supported. 1839 */ 1840static int 1841mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu) 1842{ 1843 struct mlx_command *mc; 1844 struct mlx_dcdb *dcdb; 1845 void *kbuf; 1846 int error; 1847 1848 debug_called(0); 1849 1850 kbuf = NULL; 1851 mc = NULL; 1852 dcdb = NULL; 1853 error = ENOMEM; 1854 1855 /* get ourselves a command and copy in from user space */ 1856 if ((mc = mlx_alloccmd(sc)) == NULL) 1857 goto out; 1858 bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox)); 1859 debug(0, "got command buffer"); 1860 1861 /* if we need a buffer for data transfer, allocate one and copy in its initial contents */ 1862 if (mu->mu_datasize > 0) { 1863 if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) || 1864 (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize))) 1865 goto out; 1866 debug(0, "got kernel buffer"); 1867 } 1868 1869 /* get a command slot */ 1870 if (mlx_getslot(mc)) 1871 goto out; 1872 debug(0, "got a slot"); 1873 1874 /* map the command so the controller can see it */ 1875 mc->mc_data = kbuf; 1876 mc->mc_length = mu->mu_datasize; 1877 mlx_mapcmd(mc); 1878 debug(0, "mapped"); 1879 1880 /* 1881 * If this is a passthrough SCSI command, the DCDB is packed at the 1882 * beginning of the data area. Fix up the DCDB to point to the correct physical 1883 * address and override any bufptr supplied by the caller since we know 1884 * what it's meant to be. 1885 */ 1886 if (mc->mc_mailbox[0] == MLX_CMD_DIRECT_CDB) { 1887 dcdb = (struct mlx_dcdb *)kbuf; 1888 dcdb->dcdb_physaddr = mc->mc_dataphys + sizeof(*dcdb); 1889 mu->mu_bufptr = 8; 1890 } 1891 1892 /* 1893 * If there's a data buffer, fix up the command's buffer pointer. 1894 */ 1895 if (mu->mu_datasize > 0) { 1896 1897 /* range check the pointer to physical buffer address */ 1898 if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) - sizeof(u_int32_t)))) { 1899 error = EINVAL; 1900 goto out; 1901 } 1902 mc->mc_mailbox[mu->mu_bufptr ] = mc->mc_dataphys & 0xff; 1903 mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_dataphys >> 8) & 0xff; 1904 mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_dataphys >> 16) & 0xff; 1905 mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_dataphys >> 24) & 0xff; 1906 } 1907 debug(0, "command fixup"); 1908 1909 /* submit the command and wait */ 1910 if ((error = mlx_wait_command(mc)) != 0) 1911 goto out; 1912 1913 /* copy out status and data */ 1914 mu->mu_status = mc->mc_status; 1915 if ((mu->mu_datasize > 0) && ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize)))) 1916 goto out; 1917 error = 0; 1918 1919 out: 1920 mlx_releasecmd(mc); 1921 if (kbuf != NULL) 1922 free(kbuf, M_DEVBUF); 1923 return(error); 1924} 1925 1926/******************************************************************************** 1927 ******************************************************************************** 1928 Command I/O to Controller 1929 ******************************************************************************** 1930 ********************************************************************************/ 1931 1932/******************************************************************************** 1933 * Find a free command slot for (mc). 1934 * 1935 * Don't hand out a slot to a normal-priority command unless there are at least 1936 * 4 slots free for priority commands. 1937 */ 1938static int 1939mlx_getslot(struct mlx_command *mc) 1940{ 1941 struct mlx_softc *sc = mc->mc_sc; 1942 int s, slot; 1943 1944 debug_called(1); 1945 1946 /* enforce slot-usage limit */ 1947 if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ? 1948 sc->mlx_maxiop : sc->mlx_maxiop - 4)) 1949 return(EBUSY); 1950 1951 /* 1952 * Allocate an outstanding command slot 1953 * 1954 * XXX linear search is slow 1955 */ 1956 s = splbio(); 1957 for (slot = 0; slot < sc->mlx_maxiop; slot++) { 1958 debug(2, "try slot %d", slot); 1959 if (sc->mlx_busycmd[slot] == NULL) 1960 break; 1961 } 1962 if (slot < sc->mlx_maxiop) { 1963 sc->mlx_busycmd[slot] = mc; 1964 sc->mlx_busycmds++; 1965 } 1966 splx(s); 1967 1968 /* out of slots? */ 1969 if (slot >= sc->mlx_maxiop) 1970 return(EBUSY); 1971 1972 debug(2, "got slot %d", slot); 1973 mc->mc_slot = slot; 1974 return(0); 1975} 1976 1977/******************************************************************************** 1978 * Map/unmap (mc)'s data in the controller's addressable space. 1979 */ 1980static void 1981mlx_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error) 1982{ 1983 struct mlx_command *mc = (struct mlx_command *)arg; 1984 struct mlx_softc *sc = mc->mc_sc; 1985 struct mlx_sgentry *sg; 1986 int i; 1987 1988 debug_called(1); 1989 1990 /* get base address of s/g table */ 1991 sg = sc->mlx_sgtable + (mc->mc_slot * sc->mlx_sg_nseg); 1992 1993 /* save s/g table information in command */ 1994 mc->mc_nsgent = nsegments; 1995 mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * sc->mlx_sg_nseg * sizeof(struct mlx_sgentry)); 1996 mc->mc_dataphys = segs[0].ds_addr; 1997 1998 /* populate s/g table */ 1999 for (i = 0; i < nsegments; i++, sg++) { 2000 sg->sg_addr = segs[i].ds_addr; 2001 sg->sg_count = segs[i].ds_len; 2002 } 2003} 2004 2005static void 2006mlx_mapcmd(struct mlx_command *mc) 2007{ 2008 struct mlx_softc *sc = mc->mc_sc; 2009 2010 debug_called(1); 2011 2012 /* if the command involves data at all */ 2013 if (mc->mc_data != NULL) { 2014 2015 /* map the data buffer into bus space and build the s/g list */ 2016 bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length, 2017 mlx_setup_dmamap, mc, 0); 2018 if (mc->mc_flags & MLX_CMD_DATAIN) 2019 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREREAD); 2020 if (mc->mc_flags & MLX_CMD_DATAOUT) 2021 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREWRITE); 2022 } 2023} 2024 2025static void 2026mlx_unmapcmd(struct mlx_command *mc) 2027{ 2028 struct mlx_softc *sc = mc->mc_sc; 2029 2030 debug_called(1); 2031 2032 /* if the command involved data at all */ 2033 if (mc->mc_data != NULL) { 2034 2035 if (mc->mc_flags & MLX_CMD_DATAIN) 2036 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD); 2037 if (mc->mc_flags & MLX_CMD_DATAOUT) 2038 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE); 2039 2040 bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap); 2041 } 2042} 2043 2044/******************************************************************************** 2045 * Try to deliver (mc) to the controller. 2046 * 2047 * Can be called at any interrupt level, with or without interrupts enabled. 2048 */ 2049static int 2050mlx_start(struct mlx_command *mc) 2051{ 2052 struct mlx_softc *sc = mc->mc_sc; 2053 int i, s, done; 2054 2055 debug_called(1); 2056 2057 /* save the slot number as ident so we can handle this command when complete */ 2058 mc->mc_mailbox[0x1] = mc->mc_slot; 2059 2060 /* mark the command as currently being processed */ 2061 mc->mc_status = MLX_STATUS_BUSY; 2062 2063 /* set a default 60-second timeout XXX tunable? XXX not currently used */ 2064 mc->mc_timeout = time_second + 60; 2065 2066 /* spin waiting for the mailbox */ 2067 for (i = 100000, done = 0; (i > 0) && !done; i--) { 2068 s = splbio(); 2069 if (sc->mlx_tryqueue(sc, mc)) { 2070 done = 1; 2071 /* move command to work queue */ 2072 TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link); 2073 } 2074 splx(s); /* drop spl to allow completion interrupts */ 2075 } 2076 2077 /* command is enqueued */ 2078 if (done) 2079 return(0); 2080 2081 /* 2082 * We couldn't get the controller to take the command. Revoke the slot 2083 * that the command was given and return it with a bad status. 2084 */ 2085 sc->mlx_busycmd[mc->mc_slot] = NULL; 2086 device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n"); 2087 mc->mc_status = MLX_STATUS_WEDGED; 2088 mlx_complete(sc); 2089 return(EIO); 2090} 2091 2092/******************************************************************************** 2093 * Poll the controller (sc) for completed commands. 2094 * Update command status and free slots for reuse. If any slots were freed, 2095 * new commands may be posted. 2096 * 2097 * Returns nonzero if one or more commands were completed. 2098 */ 2099static int 2100mlx_done(struct mlx_softc *sc) 2101{ 2102 struct mlx_command *mc; 2103 int s, result; 2104 u_int8_t slot; 2105 u_int16_t status; 2106 2107 debug_called(2); 2108 2109 result = 0; 2110 2111 /* loop collecting completed commands */ 2112 s = splbio(); 2113 for (;;) { 2114 /* poll for a completed command's identifier and status */ 2115 if (sc->mlx_findcomplete(sc, &slot, &status)) { 2116 result = 1; 2117 mc = sc->mlx_busycmd[slot]; /* find command */ 2118 if (mc != NULL) { /* paranoia */ 2119 if (mc->mc_status == MLX_STATUS_BUSY) { 2120 mc->mc_status = status; /* save status */ 2121 2122 /* free slot for reuse */ 2123 sc->mlx_busycmd[slot] = NULL; 2124 sc->mlx_busycmds--; 2125 } else { 2126 device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot); 2127 } 2128 } else { 2129 device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot); 2130 } 2131 } else { 2132 break; 2133 } 2134 } 2135 2136 /* if we've completed any commands, try posting some more */ 2137 if (result) 2138 mlx_startio(sc); 2139 2140 /* handle completion and timeouts */ 2141 mlx_complete(sc); 2142 2143 return(result); 2144} 2145 2146/******************************************************************************** 2147 * Perform post-completion processing for commands on (sc). 2148 */ 2149static void 2150mlx_complete(struct mlx_softc *sc) 2151{ 2152 struct mlx_command *mc, *nc; 2153 int s, count; 2154 2155 debug_called(2); 2156 2157 /* avoid reentrancy XXX might want to signal and request a restart */ 2158 if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING)) 2159 return; 2160 2161 s = splbio(); 2162 count = 0; 2163 2164 /* scan the list of busy/done commands */ 2165 mc = TAILQ_FIRST(&sc->mlx_work); 2166 while (mc != NULL) { 2167 nc = TAILQ_NEXT(mc, mc_link); 2168 2169 /* Command has been completed in some fashion */ 2170 if (mc->mc_status != MLX_STATUS_BUSY) { 2171 2172 /* unmap the command's data buffer */ 2173 mlx_unmapcmd(mc); 2174 /* 2175 * Does the command have a completion handler? 2176 */ 2177 if (mc->mc_complete != NULL) { 2178 /* remove from list and give to handler */ 2179 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link); 2180 mc->mc_complete(mc); 2181 2182 /* 2183 * Is there a sleeper waiting on this command? 2184 */ 2185 } else if (mc->mc_private != NULL) { /* sleeping caller wants to know about it */ 2186 2187 /* remove from list and wake up sleeper */ 2188 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link); 2189 wakeup_one(mc->mc_private); 2190 2191 /* 2192 * Leave the command for a caller that's polling for it. 2193 */ 2194 } else { 2195 } 2196 } 2197 mc = nc; 2198 } 2199 splx(s); 2200 2201 mlx_lock_clr(sc, MLX_LOCK_COMPLETING); 2202} 2203 2204/******************************************************************************** 2205 ******************************************************************************** 2206 Command Buffer Management 2207 ******************************************************************************** 2208 ********************************************************************************/ 2209 2210/******************************************************************************** 2211 * Get a new command buffer. 2212 * 2213 * This may return NULL in low-memory cases. 2214 * 2215 * Note that using malloc() is expensive (the command buffer is << 1 page) but 2216 * necessary if we are to be a loadable module before the zone allocator is fixed. 2217 * 2218 * If possible, we recycle a command buffer that's been used before. 2219 * 2220 * XXX Note that command buffers are not cleaned out - it is the caller's 2221 * responsibility to ensure that all required fields are filled in before 2222 * using a buffer. 2223 */ 2224static struct mlx_command * 2225mlx_alloccmd(struct mlx_softc *sc) 2226{ 2227 struct mlx_command *mc; 2228 int error; 2229 int s; 2230 2231 debug_called(1); 2232 2233 s = splbio(); 2234 if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) 2235 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link); 2236 splx(s); 2237 2238 /* allocate a new command buffer? */ 2239 if (mc == NULL) { 2240 mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT); 2241 if (mc != NULL) { 2242 bzero(mc, sizeof(*mc)); 2243 mc->mc_sc = sc; 2244 error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap); 2245 if (error) { 2246 free(mc, M_DEVBUF); 2247 return(NULL); 2248 } 2249 } 2250 } 2251 return(mc); 2252} 2253 2254/******************************************************************************** 2255 * Release a command buffer for recycling. 2256 * 2257 * XXX It might be a good idea to limit the number of commands we save for reuse 2258 * if it's shown that this list bloats out massively. 2259 */ 2260static void 2261mlx_releasecmd(struct mlx_command *mc) 2262{ 2263 int s; 2264 2265 debug_called(1); 2266 2267 s = splbio(); 2268 TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link); 2269 splx(s); 2270} 2271 2272/******************************************************************************** 2273 * Permanently discard a command buffer. 2274 */ 2275static void 2276mlx_freecmd(struct mlx_command *mc) 2277{ 2278 struct mlx_softc *sc = mc->mc_sc; 2279 2280 debug_called(1); 2281 bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap); 2282 free(mc, M_DEVBUF); 2283} 2284 2285 2286/******************************************************************************** 2287 ******************************************************************************** 2288 Type 3 interface accessor methods 2289 ******************************************************************************** 2290 ********************************************************************************/ 2291 2292/******************************************************************************** 2293 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure 2294 * (the controller is not ready to take a command). 2295 * 2296 * Must be called at splbio or in a fashion that prevents reentry. 2297 */ 2298static int 2299mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2300{ 2301 int i; 2302 2303 debug_called(2); 2304 2305 /* ready for our command? */ 2306 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) { 2307 /* copy mailbox data to window */ 2308 for (i = 0; i < 13; i++) 2309 MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); 2310 2311 /* post command */ 2312 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_FULL); 2313 return(1); 2314 } 2315 return(0); 2316} 2317 2318/******************************************************************************** 2319 * See if a command has been completed, if so acknowledge its completion 2320 * and recover the slot number and status code. 2321 * 2322 * Must be called at splbio or in a fashion that prevents reentry. 2323 */ 2324static int 2325mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2326{ 2327 2328 debug_called(2); 2329 2330 /* status available? */ 2331 if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) { 2332 *slot = MLX_V3_GET_STATUS_IDENT(sc); /* get command identifier */ 2333 *status = MLX_V3_GET_STATUS(sc); /* get status */ 2334 2335 /* acknowledge completion */ 2336 MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL); 2337 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK); 2338 return(1); 2339 } 2340 return(0); 2341} 2342 2343/******************************************************************************** 2344 * Enable/disable interrupts as requested. (No acknowledge required) 2345 * 2346 * Must be called at splbio or in a fashion that prevents reentry. 2347 */ 2348static void 2349mlx_v3_intaction(struct mlx_softc *sc, int action) 2350{ 2351 debug_called(1); 2352 2353 switch(action) { 2354 case MLX_INTACTION_DISABLE: 2355 MLX_V3_PUT_IER(sc, 0); 2356 sc->mlx_state &= ~MLX_STATE_INTEN; 2357 break; 2358 case MLX_INTACTION_ENABLE: 2359 MLX_V3_PUT_IER(sc, 1); 2360 sc->mlx_state |= MLX_STATE_INTEN; 2361 break; 2362 } 2363} 2364 2365/******************************************************************************** 2366 * Poll for firmware error codes during controller initialisation. 2367 * Returns 0 if initialisation is complete, 1 if still in progress but no 2368 * error has been fetched, 2 if an error has been retrieved. 2369 */ 2370static int 2371mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2) 2372{ 2373 u_int8_t fwerror; 2374 static int initted = 0; 2375 2376 debug_called(2); 2377 2378 /* first time around, clear any hardware completion status */ 2379 if (!initted) { 2380 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK); 2381 DELAY(1000); 2382 initted = 1; 2383 } 2384 2385 /* init in progress? */ 2386 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_INIT_BUSY)) 2387 return(0); 2388 2389 /* test error value */ 2390 fwerror = MLX_V3_GET_FWERROR(sc); 2391 if (!(fwerror & MLX_V3_FWERROR_PEND)) 2392 return(1); 2393 2394 /* mask status pending bit, fetch status */ 2395 *error = fwerror & ~MLX_V3_FWERROR_PEND; 2396 *param1 = MLX_V3_GET_FWERROR_PARAM1(sc); 2397 *param2 = MLX_V3_GET_FWERROR_PARAM2(sc); 2398 2399 /* acknowledge */ 2400 MLX_V3_PUT_FWERROR(sc, 0); 2401 2402 return(2); 2403} 2404 2405/******************************************************************************** 2406 ******************************************************************************** 2407 Type 4 interface accessor methods 2408 ******************************************************************************** 2409 ********************************************************************************/ 2410 2411/******************************************************************************** 2412 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure 2413 * (the controller is not ready to take a command). 2414 * 2415 * Must be called at splbio or in a fashion that prevents reentry. 2416 */ 2417static int 2418mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2419{ 2420 int i; 2421 2422 debug_called(2); 2423 2424 /* ready for our command? */ 2425 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) { 2426 /* copy mailbox data to window */ 2427 for (i = 0; i < 13; i++) 2428 MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); 2429 2430 /* memory-mapped controller, so issue a write barrier to ensure the mailbox is filled */ 2431 bus_space_barrier(sc->mlx_btag, sc->mlx_bhandle, MLX_V4_MAILBOX, MLX_V4_MAILBOX_LENGTH, 2432 BUS_SPACE_BARRIER_WRITE); 2433 2434 /* post command */ 2435 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD); 2436 return(1); 2437 } 2438 return(0); 2439} 2440 2441/******************************************************************************** 2442 * See if a command has been completed, if so acknowledge its completion 2443 * and recover the slot number and status code. 2444 * 2445 * Must be called at splbio or in a fashion that prevents reentry. 2446 */ 2447static int 2448mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2449{ 2450 2451 debug_called(2); 2452 2453 /* status available? */ 2454 if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) { 2455 *slot = MLX_V4_GET_STATUS_IDENT(sc); /* get command identifier */ 2456 *status = MLX_V4_GET_STATUS(sc); /* get status */ 2457 2458 /* acknowledge completion */ 2459 MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK); 2460 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK); 2461 return(1); 2462 } 2463 return(0); 2464} 2465 2466/******************************************************************************** 2467 * Enable/disable interrupts as requested. 2468 * 2469 * Must be called at splbio or in a fashion that prevents reentry. 2470 */ 2471static void 2472mlx_v4_intaction(struct mlx_softc *sc, int action) 2473{ 2474 debug_called(1); 2475 2476 switch(action) { 2477 case MLX_INTACTION_DISABLE: 2478 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT); 2479 sc->mlx_state &= ~MLX_STATE_INTEN; 2480 break; 2481 case MLX_INTACTION_ENABLE: 2482 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT); 2483 sc->mlx_state |= MLX_STATE_INTEN; 2484 break; 2485 } 2486} 2487 2488/******************************************************************************** 2489 * Poll for firmware error codes during controller initialisation. 2490 * Returns 0 if initialisation is complete, 1 if still in progress but no 2491 * error has been fetched, 2 if an error has been retrieved. 2492 */ 2493static int 2494mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2) 2495{ 2496 u_int8_t fwerror; 2497 static int initted = 0; 2498 2499 debug_called(2); 2500 2501 /* first time around, clear any hardware completion status */ 2502 if (!initted) { 2503 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK); 2504 DELAY(1000); 2505 initted = 1; 2506 } 2507 2508 /* init in progress? */ 2509 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_INIT_BUSY)) 2510 return(0); 2511 2512 /* test error value */ 2513 fwerror = MLX_V4_GET_FWERROR(sc); 2514 if (!(fwerror & MLX_V4_FWERROR_PEND)) 2515 return(1); 2516 2517 /* mask status pending bit, fetch status */ 2518 *error = fwerror & ~MLX_V4_FWERROR_PEND; 2519 *param1 = MLX_V4_GET_FWERROR_PARAM1(sc); 2520 *param2 = MLX_V4_GET_FWERROR_PARAM2(sc); 2521 2522 /* acknowledge */ 2523 MLX_V4_PUT_FWERROR(sc, 0); 2524 2525 return(2); 2526} 2527 2528/******************************************************************************** 2529 ******************************************************************************** 2530 Type 5 interface accessor methods 2531 ******************************************************************************** 2532 ********************************************************************************/ 2533 2534/******************************************************************************** 2535 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure 2536 * (the controller is not ready to take a command). 2537 * 2538 * Must be called at splbio or in a fashion that prevents reentry. 2539 */ 2540static int 2541mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc) 2542{ 2543 int i; 2544 2545 debug_called(2); 2546 2547 /* ready for our command? */ 2548 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) { 2549 /* copy mailbox data to window */ 2550 for (i = 0; i < 13; i++) 2551 MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]); 2552 2553 /* post command */ 2554 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD); 2555 return(1); 2556 } 2557 return(0); 2558} 2559 2560/******************************************************************************** 2561 * See if a command has been completed, if so acknowledge its completion 2562 * and recover the slot number and status code. 2563 * 2564 * Must be called at splbio or in a fashion that prevents reentry. 2565 */ 2566static int 2567mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status) 2568{ 2569 2570 debug_called(2); 2571 2572 /* status available? */ 2573 if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) { 2574 *slot = MLX_V5_GET_STATUS_IDENT(sc); /* get command identifier */ 2575 *status = MLX_V5_GET_STATUS(sc); /* get status */ 2576 2577 /* acknowledge completion */ 2578 MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK); 2579 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK); 2580 return(1); 2581 } 2582 return(0); 2583} 2584 2585/******************************************************************************** 2586 * Enable/disable interrupts as requested. 2587 * 2588 * Must be called at splbio or in a fashion that prevents reentry. 2589 */ 2590static void 2591mlx_v5_intaction(struct mlx_softc *sc, int action) 2592{ 2593 debug_called(1); 2594 2595 switch(action) { 2596 case MLX_INTACTION_DISABLE: 2597 MLX_V5_PUT_IER(sc, 0xff & MLX_V5_IER_DISINT); 2598 sc->mlx_state &= ~MLX_STATE_INTEN; 2599 break; 2600 case MLX_INTACTION_ENABLE: 2601 MLX_V5_PUT_IER(sc, 0xff & ~MLX_V5_IER_DISINT); 2602 sc->mlx_state |= MLX_STATE_INTEN; 2603 break; 2604 } 2605} 2606 2607/******************************************************************************** 2608 * Poll for firmware error codes during controller initialisation. 2609 * Returns 0 if initialisation is complete, 1 if still in progress but no 2610 * error has been fetched, 2 if an error has been retrieved. 2611 */ 2612static int 2613mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2) 2614{ 2615 u_int8_t fwerror; 2616 static int initted = 0; 2617 2618 debug_called(2); 2619 2620 /* first time around, clear any hardware completion status */ 2621 if (!initted) { 2622 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK); 2623 DELAY(1000); 2624 initted = 1; 2625 } 2626 2627 /* init in progress? */ 2628 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_INIT_DONE) 2629 return(0); 2630 2631 /* test for error value */ 2632 fwerror = MLX_V5_GET_FWERROR(sc); 2633 if (!(fwerror & MLX_V5_FWERROR_PEND)) 2634 return(1); 2635 2636 /* mask status pending bit, fetch status */ 2637 *error = fwerror & ~MLX_V5_FWERROR_PEND; 2638 *param1 = MLX_V5_GET_FWERROR_PARAM1(sc); 2639 *param2 = MLX_V5_GET_FWERROR_PARAM2(sc); 2640 2641 /* acknowledge */ 2642 MLX_V5_PUT_FWERROR(sc, 0xff); 2643 2644 return(2); 2645} 2646 2647/******************************************************************************** 2648 ******************************************************************************** 2649 Debugging 2650 ******************************************************************************** 2651 ********************************************************************************/ 2652 2653/******************************************************************************** 2654 * Return a status message describing (mc) 2655 */ 2656static char *mlx_status_messages[] = { 2657 "normal completion", /* 00 */ 2658 "irrecoverable data error", /* 01 */ 2659 "drive does not exist, or is offline", /* 02 */ 2660 "attempt to write beyond end of drive", /* 03 */ 2661 "bad data encountered", /* 04 */ 2662 "invalid log entry request", /* 05 */ 2663 "attempt to rebuild online drive", /* 06 */ 2664 "new disk failed during rebuild", /* 07 */ 2665 "invalid channel/target", /* 08 */ 2666 "rebuild/check already in progress", /* 09 */ 2667 "one or more disks are dead", /* 10 */ 2668 "invalid or non-redundant drive", /* 11 */ 2669 "channel is busy", /* 12 */ 2670 "channel is not stopped", /* 13 */ 2671 "rebuild successfully terminated", /* 14 */ 2672 "unsupported command", /* 15 */ 2673 "check condition received", /* 16 */ 2674 "device is busy", /* 17 */ 2675 "selection or command timeout", /* 18 */ 2676 "command terminated abnormally", /* 19 */ 2677 "" 2678}; 2679 2680static struct 2681{ 2682 int command; 2683 u_int16_t status; 2684 int msg; 2685} mlx_messages[] = { 2686 {MLX_CMD_READSG, 0x0001, 1}, 2687 {MLX_CMD_READSG, 0x0002, 1}, 2688 {MLX_CMD_READSG, 0x0105, 3}, 2689 {MLX_CMD_READSG, 0x010c, 4}, 2690 {MLX_CMD_WRITESG, 0x0001, 1}, 2691 {MLX_CMD_WRITESG, 0x0002, 1}, 2692 {MLX_CMD_WRITESG, 0x0105, 3}, 2693 {MLX_CMD_READSG_OLD, 0x0001, 1}, 2694 {MLX_CMD_READSG_OLD, 0x0002, 1}, 2695 {MLX_CMD_READSG_OLD, 0x0105, 3}, 2696 {MLX_CMD_WRITESG_OLD, 0x0001, 1}, 2697 {MLX_CMD_WRITESG_OLD, 0x0002, 1}, 2698 {MLX_CMD_WRITESG_OLD, 0x0105, 3}, 2699 {MLX_CMD_LOGOP, 0x0105, 5}, 2700 {MLX_CMD_REBUILDASYNC, 0x0002, 6}, 2701 {MLX_CMD_REBUILDASYNC, 0x0004, 7}, 2702 {MLX_CMD_REBUILDASYNC, 0x0105, 8}, 2703 {MLX_CMD_REBUILDASYNC, 0x0106, 9}, 2704 {MLX_CMD_REBUILDASYNC, 0x0107, 14}, 2705 {MLX_CMD_CHECKASYNC, 0x0002, 10}, 2706 {MLX_CMD_CHECKASYNC, 0x0105, 11}, 2707 {MLX_CMD_CHECKASYNC, 0x0106, 9}, 2708 {MLX_CMD_STOPCHANNEL, 0x0106, 12}, 2709 {MLX_CMD_STOPCHANNEL, 0x0105, 8}, 2710 {MLX_CMD_STARTCHANNEL, 0x0005, 13}, 2711 {MLX_CMD_STARTCHANNEL, 0x0105, 8}, 2712 {MLX_CMD_DIRECT_CDB, 0x0002, 16}, 2713 {MLX_CMD_DIRECT_CDB, 0x0008, 17}, 2714 {MLX_CMD_DIRECT_CDB, 0x000e, 18}, 2715 {MLX_CMD_DIRECT_CDB, 0x000f, 19}, 2716 {MLX_CMD_DIRECT_CDB, 0x0105, 8}, 2717 2718 {0, 0x0104, 14}, 2719 {-1, 0, 0} 2720}; 2721 2722static char * 2723mlx_diagnose_command(struct mlx_command *mc) 2724{ 2725 static char unkmsg[80]; 2726 int i; 2727 2728 /* look up message in table */ 2729 for (i = 0; mlx_messages[i].command != -1; i++) 2730 if (((mc->mc_mailbox[0] == mlx_messages[i].command) || (mlx_messages[i].command == 0)) && 2731 (mc->mc_status == mlx_messages[i].status)) 2732 return(mlx_status_messages[mlx_messages[i].msg]); 2733 2734 sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]); 2735 return(unkmsg); 2736} 2737 2738/******************************************************************************* 2739 * Print a string describing the controller (sc) 2740 */ 2741static struct 2742{ 2743 int hwid; 2744 char *name; 2745} mlx_controller_names[] = { 2746 {0x01, "960P/PD"}, 2747 {0x02, "960PL"}, 2748 {0x10, "960PG"}, 2749 {0x11, "960PJ"}, 2750 {0x12, "960PR"}, 2751 {0x13, "960PT"}, 2752 {0x14, "960PTL0"}, 2753 {0x15, "960PRL"}, 2754 {0x16, "960PTL1"}, 2755 {0x20, "1164PVX"}, 2756 {-1, NULL} 2757}; 2758 2759static void 2760mlx_describe_controller(struct mlx_softc *sc) 2761{ 2762 static char buf[80]; 2763 char *model; 2764 int i; 2765 2766 for (i = 0, model = NULL; mlx_controller_names[i].name != NULL; i++) { 2767 if ((sc->mlx_enq2->me_hardware_id & 0xff) == mlx_controller_names[i].hwid) { 2768 model = mlx_controller_names[i].name; 2769 break; 2770 } 2771 } 2772 if (model == NULL) { 2773 sprintf(buf, " model 0x%x", sc->mlx_enq2->me_hardware_id & 0xff); 2774 model = buf; 2775 } 2776 device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%02d, %dMB RAM\n", 2777 model, 2778 sc->mlx_enq2->me_actual_channels, 2779 sc->mlx_enq2->me_actual_channels > 1 ? "s" : "", 2780 sc->mlx_enq2->me_firmware_id & 0xff, 2781 (sc->mlx_enq2->me_firmware_id >> 8) & 0xff, 2782 (sc->mlx_enq2->me_firmware_id >> 24) & 0xff, 2783 (sc->mlx_enq2->me_firmware_id >> 16) & 0xff, 2784 sc->mlx_enq2->me_mem_size / (1024 * 1024)); 2785 2786 if (bootverbose) { 2787 device_printf(sc->mlx_dev, " Hardware ID 0x%08x\n", sc->mlx_enq2->me_hardware_id); 2788 device_printf(sc->mlx_dev, " Firmware ID 0x%08x\n", sc->mlx_enq2->me_firmware_id); 2789 device_printf(sc->mlx_dev, " Configured/Actual channels %d/%d\n", sc->mlx_enq2->me_configured_channels, 2790 sc->mlx_enq2->me_actual_channels); 2791 device_printf(sc->mlx_dev, " Max Targets %d\n", sc->mlx_enq2->me_max_targets); 2792 device_printf(sc->mlx_dev, " Max Tags %d\n", sc->mlx_enq2->me_max_tags); 2793 device_printf(sc->mlx_dev, " Max System Drives %d\n", sc->mlx_enq2->me_max_sys_drives); 2794 device_printf(sc->mlx_dev, " Max Arms %d\n", sc->mlx_enq2->me_max_arms); 2795 device_printf(sc->mlx_dev, " Max Spans %d\n", sc->mlx_enq2->me_max_spans); 2796 device_printf(sc->mlx_dev, " DRAM/cache/flash/NVRAM size %d/%d/%d/%d\n", sc->mlx_enq2->me_mem_size, 2797 sc->mlx_enq2->me_cache_size, sc->mlx_enq2->me_flash_size, sc->mlx_enq2->me_nvram_size); 2798 device_printf(sc->mlx_dev, " DRAM type %d\n", sc->mlx_enq2->me_mem_type); 2799 device_printf(sc->mlx_dev, " Clock Speed %dns\n", sc->mlx_enq2->me_clock_speed); 2800 device_printf(sc->mlx_dev, " Hardware Speed %dns\n", sc->mlx_enq2->me_hardware_speed); 2801 device_printf(sc->mlx_dev, " Max Commands %d\n", sc->mlx_enq2->me_max_commands); 2802 device_printf(sc->mlx_dev, " Max SG Entries %d\n", sc->mlx_enq2->me_max_sg); 2803 device_printf(sc->mlx_dev, " Max DP %d\n", sc->mlx_enq2->me_max_dp); 2804 device_printf(sc->mlx_dev, " Max IOD %d\n", sc->mlx_enq2->me_max_iod); 2805 device_printf(sc->mlx_dev, " Max Comb %d\n", sc->mlx_enq2->me_max_comb); 2806 device_printf(sc->mlx_dev, " Latency %ds\n", sc->mlx_enq2->me_latency); 2807 device_printf(sc->mlx_dev, " SCSI Timeout %ds\n", sc->mlx_enq2->me_scsi_timeout); 2808 device_printf(sc->mlx_dev, " Min Free Lines %d\n", sc->mlx_enq2->me_min_freelines); 2809 device_printf(sc->mlx_dev, " Rate Constant %d\n", sc->mlx_enq2->me_rate_const); 2810 device_printf(sc->mlx_dev, " MAXBLK %d\n", sc->mlx_enq2->me_maxblk); 2811 device_printf(sc->mlx_dev, " Blocking Factor %d sectors\n", sc->mlx_enq2->me_blocking_factor); 2812 device_printf(sc->mlx_dev, " Cache Line Size %d blocks\n", sc->mlx_enq2->me_cacheline); 2813 device_printf(sc->mlx_dev, " SCSI Capability %s%dMHz, %d bit\n", 2814 sc->mlx_enq2->me_scsi_cap & (1<<4) ? "differential " : "", 2815 (1 << ((sc->mlx_enq2->me_scsi_cap >> 2) & 3)) * 10, 2816 8 << (sc->mlx_enq2->me_scsi_cap & 0x3)); 2817 device_printf(sc->mlx_dev, " Firmware Build Number %d\n", sc->mlx_enq2->me_firmware_build); 2818 device_printf(sc->mlx_dev, " Fault Management Type %d\n", sc->mlx_enq2->me_fault_mgmt_type); 2819 device_printf(sc->mlx_dev, " Features %b\n", sc->mlx_enq2->me_firmware_features, 2820 "\20\4Background Init\3Read Ahead\2MORE\1Cluster\n"); 2821 2822 } 2823} 2824 2825/******************************************************************************* 2826 * Emit a string describing the firmware handshake status code, and return a flag 2827 * indicating whether the code represents a fatal error. 2828 * 2829 * Error code interpretations are from the Linux driver, and don't directly match 2830 * the messages printed by Mylex's BIOS. This may change if documentation on the 2831 * codes is forthcoming. 2832 */ 2833static int 2834mlx_fw_message(struct mlx_softc *sc, int error, int param1, int param2) 2835{ 2836 switch(error) { 2837 case 0x00: 2838 device_printf(sc->mlx_dev, "physical drive %d:%d not responding\n", param2, param1); 2839 break; 2840 case 0x08: 2841 /* we could be neater about this and give some indication when we receive more of them */ 2842 if (!(sc->mlx_flags & MLX_SPINUP_REPORTED)) { 2843 device_printf(sc->mlx_dev, "spinning up drives...\n"); 2844 sc->mlx_flags |= MLX_SPINUP_REPORTED; 2845 } 2846 break; 2847 case 0x30: 2848 device_printf(sc->mlx_dev, "configuration checksum error\n"); 2849 break; 2850 case 0x60: 2851 device_printf(sc->mlx_dev, "mirror race recovery failed\n"); 2852 break; 2853 case 0x70: 2854 device_printf(sc->mlx_dev, "mirror race recovery in progress\n"); 2855 break; 2856 case 0x90: 2857 device_printf(sc->mlx_dev, "physical drive %d:%d COD mismatch\n", param2, param1); 2858 break; 2859 case 0xa0: 2860 device_printf(sc->mlx_dev, "logical drive installation aborted\n"); 2861 break; 2862 case 0xb0: 2863 device_printf(sc->mlx_dev, "mirror race on a critical system drive\n"); 2864 break; 2865 case 0xd0: 2866 device_printf(sc->mlx_dev, "new controller configuration found\n"); 2867 break; 2868 case 0xf0: 2869 device_printf(sc->mlx_dev, "FATAL MEMORY PARITY ERROR\n"); 2870 return(1); 2871 default: 2872 device_printf(sc->mlx_dev, "unknown firmware initialisation error %02x:%02x:%02x\n", error, param1, param2); 2873 break; 2874 } 2875 return(0); 2876} 2877 2878/******************************************************************************** 2879 ******************************************************************************** 2880 Utility Functions 2881 ******************************************************************************** 2882 ********************************************************************************/ 2883 2884/******************************************************************************** 2885 * Find the disk whose unit number is (unit) on this controller 2886 */ 2887static struct mlx_sysdrive * 2888mlx_findunit(struct mlx_softc *sc, int unit) 2889{ 2890 int i; 2891 2892 /* search system drives */ 2893 for (i = 0; i < MLX_MAXDRIVES; i++) { 2894 /* is this one attached? */ 2895 if (sc->mlx_sysdrive[i].ms_disk != 0) { 2896 /* is this the one? */ 2897 if (unit == device_get_unit(sc->mlx_sysdrive[i].ms_disk)) 2898 return(&sc->mlx_sysdrive[i]); 2899 } 2900 } 2901 return(NULL); 2902}
|