amr.c revision 160443
1214501Srpaulo/*- 2214501Srpaulo * Copyright (c) 1999,2000 Michael Smith 3214501Srpaulo * Copyright (c) 2000 BSDi 4214501Srpaulo * Copyright (c) 2005 Scott Long 5252726Srpaulo * All rights reserved. 6252726Srpaulo * 7214501Srpaulo * Redistribution and use in source and binary forms, with or without 8214501Srpaulo * modification, are permitted provided that the following conditions 9214501Srpaulo * are met: 10214501Srpaulo * 1. Redistributions of source code must retain the above copyright 11214501Srpaulo * notice, this list of conditions and the following disclaimer. 12214501Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 13214501Srpaulo * notice, this list of conditions and the following disclaimer in the 14214501Srpaulo * documentation and/or other materials provided with the distribution. 15214501Srpaulo * 16214501Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17214501Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18214501Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19214501Srpaulo * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20214501Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21214501Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22214501Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23214501Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24214501Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25214501Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26214501Srpaulo * SUCH DAMAGE. 27214501Srpaulo */ 28214501Srpaulo/*- 29214501Srpaulo * Copyright (c) 2002 Eric Moore 30214501Srpaulo * Copyright (c) 2002, 2004 LSI Logic Corporation 31214501Srpaulo * All rights reserved. 32214501Srpaulo * 33214501Srpaulo * Redistribution and use in source and binary forms, with or without 34214501Srpaulo * modification, are permitted provided that the following conditions 35214501Srpaulo * are met: 36214501Srpaulo * 1. Redistributions of source code must retain the above copyright 37214501Srpaulo * notice, this list of conditions and the following disclaimer. 38214501Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 39214501Srpaulo * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 3. The party using or redistributing the source code and binary forms 42 * agrees to the disclaimer below and the terms and conditions set forth 43 * herein. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * SUCH DAMAGE. 56 */ 57 58#include <sys/cdefs.h> 59__FBSDID("$FreeBSD: head/sys/dev/amr/amr.c 160443 2006-07-17 19:45:47Z jhb $"); 60 61/* 62 * Driver for the AMI MegaRaid family of controllers. 63 */ 64 65#include <sys/param.h> 66#include <sys/systm.h> 67#include <sys/malloc.h> 68#include <sys/kernel.h> 69#include <sys/proc.h> 70#include <sys/sysctl.h> 71 72#include <sys/bio.h> 73#include <sys/bus.h> 74#include <sys/conf.h> 75#include <sys/stat.h> 76 77#include <machine/bus.h> 78#include <machine/cpu.h> 79#include <machine/resource.h> 80#include <sys/rman.h> 81 82#include <dev/pci/pcireg.h> 83#include <dev/pci/pcivar.h> 84 85#include <dev/amr/amrio.h> 86#include <dev/amr/amrreg.h> 87#include <dev/amr/amrvar.h> 88#define AMR_DEFINE_TABLES 89#include <dev/amr/amr_tables.h> 90 91/* 92 * The CAM interface appears to be completely broken. Disable it. 93 */ 94#ifndef AMR_ENABLE_CAM 95#define AMR_ENABLE_CAM 0 96#endif 97 98SYSCTL_NODE(_hw, OID_AUTO, amr, CTLFLAG_RD, 0, "AMR driver parameters"); 99 100static d_open_t amr_open; 101static d_close_t amr_close; 102static d_ioctl_t amr_ioctl; 103 104static struct cdevsw amr_cdevsw = { 105 .d_version = D_VERSION, 106 .d_flags = D_NEEDGIANT, 107 .d_open = amr_open, 108 .d_close = amr_close, 109 .d_ioctl = amr_ioctl, 110 .d_name = "amr", 111}; 112 113int linux_no_adapter = 0; 114/* 115 * Initialisation, bus interface. 116 */ 117static void amr_startup(void *arg); 118 119/* 120 * Command wrappers 121 */ 122static int amr_query_controller(struct amr_softc *sc); 123static void *amr_enquiry(struct amr_softc *sc, size_t bufsize, 124 u_int8_t cmd, u_int8_t cmdsub, u_int8_t cmdqual, int *status); 125static void amr_completeio(struct amr_command *ac); 126static int amr_support_ext_cdb(struct amr_softc *sc); 127 128/* 129 * Command buffer allocation. 130 */ 131static void amr_alloccmd_cluster(struct amr_softc *sc); 132static void amr_freecmd_cluster(struct amr_command_cluster *acc); 133 134/* 135 * Command processing. 136 */ 137static int amr_bio_command(struct amr_softc *sc, struct amr_command **acp); 138static int amr_wait_command(struct amr_command *ac) __unused; 139static int amr_mapcmd(struct amr_command *ac); 140static void amr_unmapcmd(struct amr_command *ac); 141static int amr_start(struct amr_command *ac); 142static void amr_complete(void *context, int pending); 143static void amr_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error); 144static void amr_setup_dma64map(void *arg, bus_dma_segment_t *segs, int nsegments, int error); 145static void amr_setup_data_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error); 146 147/* 148 * Status monitoring 149 */ 150static void amr_periodic(void *data); 151 152/* 153 * Interface-specific shims 154 */ 155static int amr_quartz_submit_command(struct amr_command *ac); 156static int amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave); 157static int amr_quartz_poll_command(struct amr_command *ac); 158static int amr_quartz_poll_command1(struct amr_softc *sc, struct amr_command *ac); 159 160static int amr_std_submit_command(struct amr_command *ac); 161static int amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave); 162static int amr_std_poll_command(struct amr_command *ac); 163static void amr_std_attach_mailbox(struct amr_softc *sc); 164 165#ifdef AMR_BOARD_INIT 166static int amr_quartz_init(struct amr_softc *sc); 167static int amr_std_init(struct amr_softc *sc); 168#endif 169 170/* 171 * Debugging 172 */ 173static void amr_describe_controller(struct amr_softc *sc); 174#ifdef AMR_DEBUG 175#if 0 176static void amr_printcommand(struct amr_command *ac); 177#endif 178#endif 179 180static void amr_init_sysctl(struct amr_softc *sc); 181static int amr_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t addr, 182 int32_t flag, d_thread_t *td); 183 184/******************************************************************************** 185 ******************************************************************************** 186 Inline Glue 187 ******************************************************************************** 188 ********************************************************************************/ 189 190/******************************************************************************** 191 ******************************************************************************** 192 Public Interfaces 193 ******************************************************************************** 194 ********************************************************************************/ 195 196/******************************************************************************** 197 * Initialise the controller and softc. 198 */ 199int 200amr_attach(struct amr_softc *sc) 201{ 202 203 debug_called(1); 204 205 /* 206 * Initialise per-controller queues. 207 */ 208 TAILQ_INIT(&sc->amr_completed); 209 TAILQ_INIT(&sc->amr_freecmds); 210 TAILQ_INIT(&sc->amr_cmd_clusters); 211 TAILQ_INIT(&sc->amr_ready); 212 bioq_init(&sc->amr_bioq); 213 214 debug(2, "queue init done"); 215 216 /* 217 * Configure for this controller type. 218 */ 219 if (AMR_IS_QUARTZ(sc)) { 220 sc->amr_submit_command = amr_quartz_submit_command; 221 sc->amr_get_work = amr_quartz_get_work; 222 sc->amr_poll_command = amr_quartz_poll_command; 223 sc->amr_poll_command1 = amr_quartz_poll_command1; 224 } else { 225 sc->amr_submit_command = amr_std_submit_command; 226 sc->amr_get_work = amr_std_get_work; 227 sc->amr_poll_command = amr_std_poll_command; 228 amr_std_attach_mailbox(sc);; 229 } 230 231#ifdef AMR_BOARD_INIT 232 if ((AMR_IS_QUARTZ(sc) ? amr_quartz_init(sc) : amr_std_init(sc)))) 233 return(ENXIO); 234#endif 235 236 /* 237 * Quiz controller for features and limits. 238 */ 239 if (amr_query_controller(sc)) 240 return(ENXIO); 241 242 debug(2, "controller query complete"); 243 244 /* 245 * Setup sysctls. 246 */ 247 amr_init_sysctl(sc); 248 249#if AMR_ENABLE_CAM != 0 250 /* 251 * Attach our 'real' SCSI channels to CAM. 252 */ 253 if (amr_cam_attach(sc)) 254 return(ENXIO); 255 debug(2, "CAM attach done"); 256#endif 257 258 /* 259 * Create the control device. 260 */ 261 sc->amr_dev_t = make_dev(&amr_cdevsw, device_get_unit(sc->amr_dev), UID_ROOT, GID_OPERATOR, 262 S_IRUSR | S_IWUSR, "amr%d", device_get_unit(sc->amr_dev)); 263 sc->amr_dev_t->si_drv1 = sc; 264 linux_no_adapter++; 265 if (device_get_unit(sc->amr_dev) == 0) 266 make_dev_alias(sc->amr_dev_t, "megadev0"); 267 268 /* 269 * Schedule ourselves to bring the controller up once interrupts are 270 * available. 271 */ 272 bzero(&sc->amr_ich, sizeof(struct intr_config_hook)); 273 sc->amr_ich.ich_func = amr_startup; 274 sc->amr_ich.ich_arg = sc; 275 if (config_intrhook_establish(&sc->amr_ich) != 0) { 276 device_printf(sc->amr_dev, "can't establish configuration hook\n"); 277 return(ENOMEM); 278 } 279 280 /* 281 * Print a little information about the controller. 282 */ 283 amr_describe_controller(sc); 284 285 debug(2, "attach complete"); 286 return(0); 287} 288 289/******************************************************************************** 290 * Locate disk resources and attach children to them. 291 */ 292static void 293amr_startup(void *arg) 294{ 295 struct amr_softc *sc = (struct amr_softc *)arg; 296 struct amr_logdrive *dr; 297 int i, error; 298 299 debug_called(1); 300 301 /* pull ourselves off the intrhook chain */ 302 if (sc->amr_ich.ich_func) 303 config_intrhook_disestablish(&sc->amr_ich); 304 sc->amr_ich.ich_func = NULL; 305 306 /* get up-to-date drive information */ 307 if (amr_query_controller(sc)) { 308 device_printf(sc->amr_dev, "can't scan controller for drives\n"); 309 return; 310 } 311 312 /* iterate over available drives */ 313 for (i = 0, dr = &sc->amr_drive[0]; (i < AMR_MAXLD) && (dr->al_size != 0xffffffff); i++, dr++) { 314 /* are we already attached to this drive? */ 315 if (dr->al_disk == 0) { 316 /* generate geometry information */ 317 if (dr->al_size > 0x200000) { /* extended translation? */ 318 dr->al_heads = 255; 319 dr->al_sectors = 63; 320 } else { 321 dr->al_heads = 64; 322 dr->al_sectors = 32; 323 } 324 dr->al_cylinders = dr->al_size / (dr->al_heads * dr->al_sectors); 325 326 dr->al_disk = device_add_child(sc->amr_dev, NULL, -1); 327 if (dr->al_disk == 0) 328 device_printf(sc->amr_dev, "device_add_child failed\n"); 329 device_set_ivars(dr->al_disk, dr); 330 } 331 } 332 333 if ((error = bus_generic_attach(sc->amr_dev)) != 0) 334 device_printf(sc->amr_dev, "bus_generic_attach returned %d\n", error); 335 336 /* mark controller back up */ 337 sc->amr_state &= ~AMR_STATE_SHUTDOWN; 338 339 /* interrupts will be enabled before we do anything more */ 340 sc->amr_state |= AMR_STATE_INTEN; 341 342 /* 343 * Start the timeout routine. 344 */ 345/* sc->amr_timeout = timeout(amr_periodic, sc, hz);*/ 346 347 return; 348} 349 350static void 351amr_init_sysctl(struct amr_softc *sc) 352{ 353 354 SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->amr_dev), 355 SYSCTL_CHILDREN(device_get_sysctl_tree(sc->amr_dev)), 356 OID_AUTO, "allow_volume_configure", CTLFLAG_RW, &sc->amr_allow_vol_config, 0, 357 ""); 358} 359 360 361/******************************************************************************* 362 * Free resources associated with a controller instance 363 */ 364void 365amr_free(struct amr_softc *sc) 366{ 367 struct amr_command_cluster *acc; 368 369#if AMR_ENABLE_CAM != 0 370 /* detach from CAM */ 371 amr_cam_detach(sc); 372#endif 373 374 /* cancel status timeout */ 375 untimeout(amr_periodic, sc, sc->amr_timeout); 376 377 /* throw away any command buffers */ 378 while ((acc = TAILQ_FIRST(&sc->amr_cmd_clusters)) != NULL) { 379 TAILQ_REMOVE(&sc->amr_cmd_clusters, acc, acc_link); 380 amr_freecmd_cluster(acc); 381 } 382 383 /* destroy control device */ 384 if( sc->amr_dev_t != (struct cdev *)NULL) 385 destroy_dev(sc->amr_dev_t); 386 387 if (mtx_initialized(&sc->amr_hw_lock)) 388 mtx_destroy(&sc->amr_hw_lock); 389 390 if (mtx_initialized(&sc->amr_list_lock)) 391 mtx_destroy(&sc->amr_list_lock); 392} 393 394/******************************************************************************* 395 * Receive a bio structure from a child device and queue it on a particular 396 * disk resource, then poke the disk resource to start as much work as it can. 397 */ 398int 399amr_submit_bio(struct amr_softc *sc, struct bio *bio) 400{ 401 debug_called(2); 402 403 mtx_lock(&sc->amr_list_lock); 404 amr_enqueue_bio(sc, bio); 405 amr_startio(sc); 406 mtx_unlock(&sc->amr_list_lock); 407 return(0); 408} 409 410/******************************************************************************** 411 * Accept an open operation on the control device. 412 */ 413static int 414amr_open(struct cdev *dev, int flags, int fmt, d_thread_t *td) 415{ 416 int unit = minor(dev); 417 struct amr_softc *sc = devclass_get_softc(devclass_find("amr"), unit); 418 419 debug_called(1); 420 421 sc->amr_state |= AMR_STATE_OPEN; 422 return(0); 423} 424 425#ifdef LSI 426static int 427amr_del_ld(struct amr_softc *sc, int drv_no, int status) 428{ 429 430 debug_called(1); 431 432 sc->amr_state &= ~AMR_STATE_QUEUE_FRZN; 433 sc->amr_state &= ~AMR_STATE_LD_DELETE; 434 sc->amr_state |= AMR_STATE_REMAP_LD; 435 debug(1, "State Set"); 436 437 if (!status) { 438 debug(1, "disk begin destroyed %d",drv_no); 439 if (--amr_disks_registered == 0) 440 cdevsw_remove(&amrddisk_cdevsw); 441 debug(1, "disk begin destroyed success"); 442 } 443 return 0; 444} 445 446static int 447amr_prepare_ld_delete(struct amr_softc *sc) 448{ 449 450 debug_called(1); 451 if (sc->ld_del_supported == 0) 452 return(ENOIOCTL); 453 454 sc->amr_state |= AMR_STATE_QUEUE_FRZN; 455 sc->amr_state |= AMR_STATE_LD_DELETE; 456 457 /* 5 minutes for the all the commands to be flushed.*/ 458 tsleep((void *)&sc->ld_del_supported, PCATCH | PRIBIO,"delete_logical_drv",hz * 60 * 1); 459 if ( sc->amr_busyslots ) 460 return(ENOIOCTL); 461 462 return 0; 463} 464#endif 465 466/******************************************************************************** 467 * Accept the last close on the control device. 468 */ 469static int 470amr_close(struct cdev *dev, int flags, int fmt, d_thread_t *td) 471{ 472 int unit = minor(dev); 473 struct amr_softc *sc = devclass_get_softc(devclass_find("amr"), unit); 474 475 debug_called(1); 476 477 sc->amr_state &= ~AMR_STATE_OPEN; 478 return (0); 479} 480 481/******************************************************************************** 482 * Handle controller-specific control operations. 483 */ 484static void 485amr_rescan_drives(struct cdev *dev) 486{ 487 struct amr_softc *sc = (struct amr_softc *)dev->si_drv1; 488 int i, error = 0; 489 490 sc->amr_state |= AMR_STATE_REMAP_LD; 491 while (sc->amr_busyslots) { 492 device_printf(sc->amr_dev, "idle controller\n"); 493 amr_done(sc); 494 } 495 496 /* mark ourselves as in-shutdown */ 497 sc->amr_state |= AMR_STATE_SHUTDOWN; 498 499 /* flush controller */ 500 device_printf(sc->amr_dev, "flushing cache..."); 501 printf("%s\n", amr_flush(sc) ? "failed" : "done"); 502 503 /* delete all our child devices */ 504 for(i = 0 ; i < AMR_MAXLD; i++) { 505 if(sc->amr_drive[i].al_disk != 0) { 506 if((error = device_delete_child(sc->amr_dev, 507 sc->amr_drive[i].al_disk)) != 0) 508 goto shutdown_out; 509 510 sc->amr_drive[i].al_disk = 0; 511 } 512 } 513 514shutdown_out: 515 amr_startup(sc); 516} 517 518int 519amr_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, 520 d_thread_t *td) 521{ 522 struct amr_softc *sc = (struct amr_softc *)dev->si_drv1; 523 struct amr_command *ac; 524 struct amr_mailbox *mb; 525 struct amr_linux_ioctl ali; 526 void *dp, *temp; 527 int error; 528 int adapter, len, ac_flags = 0; 529 int logical_drives_changed = 0; 530 u_int32_t linux_version = 0x02100000; 531 u_int8_t status; 532 struct amr_passthrough *ap; /* 60 bytes */ 533 534 error = 0; 535 dp = NULL; 536 ac = NULL; 537 ap = NULL; 538 539 if ((error = copyin(addr, &ali, sizeof(ali))) != 0) 540 return (error); 541 switch (ali.ui.fcs.opcode) { 542 case 0x82: 543 switch(ali.ui.fcs.subopcode) { 544 case 'e': 545 copyout(&linux_version, (void *)(uintptr_t)ali.data, 546 sizeof(linux_version)); 547 error = 0; 548 break; 549 550 case 'm': 551 copyout(&linux_no_adapter, (void *)(uintptr_t)ali.data, 552 sizeof(linux_no_adapter)); 553 td->td_retval[0] = linux_no_adapter; 554 error = 0; 555 break; 556 557 default: 558 printf("Unknown subopcode\n"); 559 error = ENOIOCTL; 560 break; 561 } 562 break; 563 564 case 0x80: 565 case 0x81: 566 if (ali.ui.fcs.opcode == 0x80) 567 len = max(ali.outlen, ali.inlen); 568 else 569 len = ali.ui.fcs.length; 570 571 adapter = (ali.ui.fcs.adapno) ^ 'm' << 8; 572 573 ap = malloc(sizeof(struct amr_passthrough), 574 M_DEVBUF, M_WAITOK | M_ZERO); 575 576 mb = (void *)&ali.mbox[0]; 577 578 if ((ali.mbox[0] == FC_DEL_LOGDRV && ali.mbox[2] == OP_DEL_LOGDRV) || /* delete */ 579 (ali.mbox[0] == AMR_CMD_CONFIG && ali.mbox[2] == 0x0d)) { /* create */ 580 if (sc->amr_allow_vol_config == 0) { 581 error = EPERM; 582 break; 583 } 584 logical_drives_changed = 1; 585 } 586 587 if (ali.mbox[0] == AMR_CMD_PASS) { 588 error = copyin((void *)(uintptr_t)mb->mb_physaddr, ap, 589 sizeof(struct amr_passthrough)); 590 if (error) 591 break; 592 593 if (ap->ap_data_transfer_length) 594 dp = malloc(ap->ap_data_transfer_length, M_DEVBUF, 595 M_WAITOK | M_ZERO); 596 597 if (ali.inlen) { 598 error = copyin((void *)(uintptr_t)ap->ap_data_transfer_address, 599 dp, ap->ap_data_transfer_length); 600 if (error) 601 break; 602 } 603 604 mtx_lock(&sc->amr_list_lock); 605 while ((ac = amr_alloccmd(sc)) == NULL) 606 msleep(sc, &sc->amr_list_lock, PPAUSE, "amrioc", hz); 607 608 ac_flags = AMR_CMD_DATAIN|AMR_CMD_DATAOUT|AMR_CMD_CCB_DATAIN|AMR_CMD_CCB_DATAOUT; 609 bzero(&ac->ac_mailbox, sizeof(ac->ac_mailbox)); 610 ac->ac_mailbox.mb_command = AMR_CMD_PASS; 611 ac->ac_flags = ac_flags; 612 613 ac->ac_data = ap; 614 ac->ac_length = sizeof(struct amr_passthrough); 615 ac->ac_ccb_data = dp; 616 ac->ac_ccb_length = ap->ap_data_transfer_length; 617 temp = (void *)(uintptr_t)ap->ap_data_transfer_address; 618 619 error = amr_wait_command(ac); 620 mtx_unlock(&sc->amr_list_lock); 621 if (error) 622 break; 623 624 status = ac->ac_status; 625 error = copyout(&status, &((struct amr_passthrough *)(uintptr_t)mb->mb_physaddr)->ap_scsi_status, sizeof(status)); 626 if (error) 627 break; 628 629 if (ali.outlen) { 630 error = copyout(dp, temp, ap->ap_data_transfer_length); 631 if (error) 632 break; 633 } 634 error = copyout(ap->ap_request_sense_area, ((struct amr_passthrough *)(uintptr_t)mb->mb_physaddr)->ap_request_sense_area, ap->ap_request_sense_length); 635 if (error) 636 break; 637 638 error = 0; 639 break; 640 } else if (ali.mbox[0] == AMR_CMD_PASS_64) { 641 printf("No AMR_CMD_PASS_64\n"); 642 error = ENOIOCTL; 643 break; 644 } else if (ali.mbox[0] == AMR_CMD_EXTPASS) { 645 printf("No AMR_CMD_EXTPASS\n"); 646 error = ENOIOCTL; 647 break; 648 } else { 649 if (len) 650 dp = malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); 651 652 if (ali.inlen) { 653 error = copyin((void *)(uintptr_t)mb->mb_physaddr, dp, len); 654 if (error) 655 break; 656 } 657 658 mtx_lock(&sc->amr_list_lock); 659 while ((ac = amr_alloccmd(sc)) == NULL) 660 msleep(sc, &sc->amr_list_lock, PPAUSE, "amrioc", hz); 661 662 ac_flags = AMR_CMD_DATAIN|AMR_CMD_DATAOUT; 663 bzero(&ac->ac_mailbox, sizeof(ac->ac_mailbox)); 664 bcopy(&ali.mbox[0], &ac->ac_mailbox, sizeof(ali.mbox)); 665 666 ac->ac_length = len; 667 ac->ac_data = dp; 668 ac->ac_flags = ac_flags; 669 670 error = amr_wait_command(ac); 671 mtx_unlock(&sc->amr_list_lock); 672 if (error) 673 break; 674 675 status = ac->ac_status; 676 error = copyout(&status, &((struct amr_mailbox *)&((struct amr_linux_ioctl *)addr)->mbox[0])->mb_status, sizeof(status)); 677 if (ali.outlen) { 678 error = copyout(dp, (void *)(uintptr_t)mb->mb_physaddr, len); 679 if (error) 680 break; 681 } 682 683 error = 0; 684 if (logical_drives_changed) 685 amr_rescan_drives(dev); 686 break; 687 } 688 break; 689 690 default: 691 debug(1, "unknown linux ioctl 0x%lx", cmd); 692 printf("unknown linux ioctl 0x%lx\n", cmd); 693 error = ENOIOCTL; 694 break; 695 } 696 697 /* 698 * At this point, we know that there is a lock held and that these 699 * objects have been allocated. 700 */ 701 mtx_lock(&sc->amr_list_lock); 702 if (ac != NULL) 703 amr_releasecmd(ac); 704 mtx_unlock(&sc->amr_list_lock); 705 if (dp != NULL) 706 free(dp, M_DEVBUF); 707 if (ap != NULL) 708 free(ap, M_DEVBUF); 709 return(error); 710} 711 712static int 713amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *td) 714{ 715 struct amr_softc *sc = (struct amr_softc *)dev->si_drv1; 716 union { 717 void *_p; 718 struct amr_user_ioctl *au; 719#ifdef AMR_IO_COMMAND32 720 struct amr_user_ioctl32 *au32; 721#endif 722 int *result; 723 } arg; 724 struct amr_command *ac; 725 struct amr_mailbox_ioctl *mbi; 726 void *dp, *au_buffer; 727 unsigned long au_length; 728 unsigned char *au_cmd; 729 int *au_statusp, au_direction; 730 int error, ac_flags = 0; 731 struct amr_passthrough *ap; /* 60 bytes */ 732 int logical_drives_changed = 0; 733 734 debug_called(1); 735 736 arg._p = (void *)addr; 737 738 error = 0; 739 dp = NULL; 740 ac = NULL; 741 ap = NULL; 742 743 switch(cmd) { 744 745 case AMR_IO_VERSION: 746 debug(1, "AMR_IO_VERSION"); 747 *arg.result = AMR_IO_VERSION_NUMBER; 748 return(0); 749 750#ifdef AMR_IO_COMMAND32 751 /* 752 * Accept ioctl-s from 32-bit binaries on non-32-bit 753 * platforms, such as AMD. LSI's MEGAMGR utility is 754 * the only example known today... -mi 755 */ 756 case AMR_IO_COMMAND32: 757 debug(1, "AMR_IO_COMMAND32 0x%x", arg.au32->au_cmd[0]); 758 au_cmd = arg.au32->au_cmd; 759 au_buffer = (void *)(u_int64_t)arg.au32->au_buffer; 760 au_length = arg.au32->au_length; 761 au_direction = arg.au32->au_direction; 762 au_statusp = &arg.au32->au_status; 763 break; 764#endif 765 766 case AMR_IO_COMMAND: 767 debug(1, "AMR_IO_COMMAND 0x%x", arg.au->au_cmd[0]); 768 au_cmd = arg.au->au_cmd; 769 au_buffer = (void *)arg.au->au_buffer; 770 au_length = arg.au->au_length; 771 au_direction = arg.au->au_direction; 772 au_statusp = &arg.au->au_status; 773 break; 774 775 case 0xc0046d00: 776 case 0xc06e6d00: /* Linux emulation */ 777 { 778 devclass_t devclass; 779 struct amr_linux_ioctl ali; 780 int adapter, error; 781 782 devclass = devclass_find("amr"); 783 if (devclass == NULL) 784 return (ENOENT); 785 786 error = copyin(addr, &ali, sizeof(ali)); 787 if (error) 788 return (error); 789 if (ali.ui.fcs.opcode == 0x82) 790 adapter = 0; 791 else 792 adapter = (ali.ui.fcs.adapno) ^ 'm' << 8; 793 794 sc = devclass_get_softc(devclass, adapter); 795 if (sc == NULL) 796 return (ENOENT); 797 798 return (amr_linux_ioctl_int(sc->amr_dev_t, cmd, 799 addr, 0, td)); 800 } 801 default: 802 debug(1, "unknown ioctl 0x%lx", cmd); 803 return(ENOIOCTL); 804 } 805 806 if ((au_cmd[0] == FC_DEL_LOGDRV && au_cmd[1] == OP_DEL_LOGDRV) || /* delete */ 807 (au_cmd[0] == AMR_CMD_CONFIG && au_cmd[1] == 0x0d)) { /* create */ 808 if (sc->amr_allow_vol_config == 0) { 809 error = EPERM; 810 goto out; 811 } 812 logical_drives_changed = 1; 813#ifdef LSI 814 if ((error = amr_prepare_ld_delete(sc)) != 0) 815 return (error); 816#endif 817 } 818 819 /* handle inbound data buffer */ 820 if (au_length != 0 && au_cmd[0] != 0x06) { 821 if ((dp = malloc(au_length, M_DEVBUF, M_WAITOK|M_ZERO)) == NULL) { 822 error = ENOMEM; 823 goto out; 824 } 825 if ((error = copyin(au_buffer, dp, au_length)) != 0) { 826 free(dp, M_DEVBUF); 827 return (error); 828 } 829 debug(2, "copyin %ld bytes from %p -> %p", au_length, au_buffer, dp); 830 } 831 832 /* Allocate this now before the mutex gets held */ 833 if (au_cmd[0] == AMR_CMD_PASS) 834 ap = malloc(sizeof(struct amr_passthrough), M_DEVBUF, M_WAITOK|M_ZERO); 835 836 mtx_lock(&sc->amr_list_lock); 837 while ((ac = amr_alloccmd(sc)) == NULL) 838 msleep(sc, &sc->amr_list_lock, PPAUSE, "amrioc", hz); 839 840 /* handle SCSI passthrough command */ 841 if (au_cmd[0] == AMR_CMD_PASS) { 842 int len; 843 844 /* copy cdb */ 845 len = au_cmd[2]; 846 ap->ap_cdb_length = len; 847 bcopy(au_cmd + 3, ap->ap_cdb, len); 848 849 /* build passthrough */ 850 ap->ap_timeout = au_cmd[len + 3] & 0x07; 851 ap->ap_ars = (au_cmd[len + 3] & 0x08) ? 1 : 0; 852 ap->ap_islogical = (au_cmd[len + 3] & 0x80) ? 1 : 0; 853 ap->ap_logical_drive_no = au_cmd[len + 4]; 854 ap->ap_channel = au_cmd[len + 5]; 855 ap->ap_scsi_id = au_cmd[len + 6]; 856 ap->ap_request_sense_length = 14; 857 ap->ap_data_transfer_length = au_length; 858 /* XXX what about the request-sense area? does the caller want it? */ 859 860 /* build command */ 861 ac->ac_data = ap; 862 ac->ac_length = sizeof(struct amr_passthrough); 863 ac->ac_ccb_data = dp; 864 ac->ac_ccb_length = au_length; 865 866 ac->ac_mailbox.mb_command = AMR_CMD_PASS; 867 ac_flags = AMR_CMD_DATAIN|AMR_CMD_DATAOUT|AMR_CMD_CCB_DATAIN|AMR_CMD_CCB_DATAOUT; 868 869 } else { 870 /* direct command to controller */ 871 mbi = (struct amr_mailbox_ioctl *)&ac->ac_mailbox; 872 873 /* copy pertinent mailbox items */ 874 mbi->mb_command = au_cmd[0]; 875 mbi->mb_channel = au_cmd[1]; 876 mbi->mb_param = au_cmd[2]; 877 mbi->mb_pad[0] = au_cmd[3]; 878 mbi->mb_drive = au_cmd[4]; 879 880 /* build the command */ 881 ac->ac_data = dp; 882 ac->ac_length = au_length; 883 ac_flags = AMR_CMD_DATAIN|AMR_CMD_DATAOUT; 884 } 885 886 ac->ac_flags = ac_flags; 887 888 /* run the command */ 889 error = amr_wait_command(ac); 890 mtx_unlock(&sc->amr_list_lock); 891 if (error) 892 goto out; 893 894 /* copy out data and set status */ 895 if (au_length != 0) { 896 error = copyout(dp, au_buffer, au_length); 897 } 898 debug(2, "copyout %ld bytes from %p -> %p", au_length, dp, au_buffer); 899 if (dp != NULL) 900 debug(2, "%16d", (int)dp); 901 *au_statusp = ac->ac_status; 902 903out: 904 /* 905 * At this point, we know that there is a lock held and that these 906 * objects have been allocated. 907 */ 908 mtx_lock(&sc->amr_list_lock); 909 if (ac != NULL) 910 amr_releasecmd(ac); 911 mtx_unlock(&sc->amr_list_lock); 912 if (dp != NULL) 913 free(dp, M_DEVBUF); 914 if (ap != NULL) 915 free(ap, M_DEVBUF); 916 917#ifndef LSI 918 if (logical_drives_changed) 919 amr_rescan_drives(dev); 920#endif 921 922 return(error); 923} 924 925/******************************************************************************** 926 ******************************************************************************** 927 Status Monitoring 928 ******************************************************************************** 929 ********************************************************************************/ 930 931/******************************************************************************** 932 * Perform a periodic check of the controller status 933 */ 934static void 935amr_periodic(void *data) 936{ 937 struct amr_softc *sc = (struct amr_softc *)data; 938 939 debug_called(2); 940 941 /* XXX perform periodic status checks here */ 942 943 /* compensate for missed interrupts */ 944 amr_done(sc); 945 946 /* reschedule */ 947 sc->amr_timeout = timeout(amr_periodic, sc, hz); 948} 949 950/******************************************************************************** 951 ******************************************************************************** 952 Command Wrappers 953 ******************************************************************************** 954 ********************************************************************************/ 955 956/******************************************************************************** 957 * Interrogate the controller for the operational parameters we require. 958 */ 959static int 960amr_query_controller(struct amr_softc *sc) 961{ 962 struct amr_enquiry3 *aex; 963 struct amr_prodinfo *ap; 964 struct amr_enquiry *ae; 965 int ldrv; 966 int status; 967 968 /* 969 * If we haven't found the real limit yet, let us have a couple of commands in 970 * order to be able to probe. 971 */ 972 if (sc->amr_maxio == 0) 973 sc->amr_maxio = 2; 974 975 /* 976 * Greater than 10 byte cdb support 977 */ 978 sc->support_ext_cdb = amr_support_ext_cdb(sc); 979 980 if(sc->support_ext_cdb) { 981 debug(2,"supports extended CDBs."); 982 } 983 984 /* 985 * Try to issue an ENQUIRY3 command 986 */ 987 if ((aex = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_ENQ3, 988 AMR_CONFIG_ENQ3_SOLICITED_FULL, &status)) != NULL) { 989 990 /* 991 * Fetch current state of logical drives. 992 */ 993 for (ldrv = 0; ldrv < aex->ae_numldrives; ldrv++) { 994 sc->amr_drive[ldrv].al_size = aex->ae_drivesize[ldrv]; 995 sc->amr_drive[ldrv].al_state = aex->ae_drivestate[ldrv]; 996 sc->amr_drive[ldrv].al_properties = aex->ae_driveprop[ldrv]; 997 debug(2, " drive %d: %d state %x properties %x\n", ldrv, sc->amr_drive[ldrv].al_size, 998 sc->amr_drive[ldrv].al_state, sc->amr_drive[ldrv].al_properties); 999 } 1000 free(aex, M_DEVBUF); 1001 1002 /* 1003 * Get product info for channel count. 1004 */ 1005 if ((ap = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODUCT_INFO, 0, &status)) == NULL) { 1006 device_printf(sc->amr_dev, "can't obtain product data from controller\n"); 1007 return(1); 1008 } 1009 sc->amr_maxdrives = 40; 1010 sc->amr_maxchan = ap->ap_nschan; 1011 sc->amr_maxio = ap->ap_maxio; 1012 sc->amr_type |= AMR_TYPE_40LD; 1013 free(ap, M_DEVBUF); 1014 1015 ap = amr_enquiry(sc, 0, FC_DEL_LOGDRV, OP_SUP_DEL_LOGDRV, 0, &status); 1016 if (ap != NULL) 1017 free(ap, M_DEVBUF); 1018 if (!status) { 1019 sc->amr_ld_del_supported = 1; 1020 device_printf(sc->amr_dev, "delete logical drives supported by controller\n"); 1021 } 1022 } else { 1023 1024 /* failed, try the 8LD ENQUIRY commands */ 1025 if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_EXT_ENQUIRY2, 0, 0, &status)) == NULL) { 1026 if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_ENQUIRY, 0, 0, &status)) == NULL) { 1027 device_printf(sc->amr_dev, "can't obtain configuration data from controller\n"); 1028 return(1); 1029 } 1030 ae->ae_signature = 0; 1031 } 1032 1033 /* 1034 * Fetch current state of logical drives. 1035 */ 1036 for (ldrv = 0; ldrv < ae->ae_ldrv.al_numdrives; ldrv++) { 1037 sc->amr_drive[ldrv].al_size = ae->ae_ldrv.al_size[ldrv]; 1038 sc->amr_drive[ldrv].al_state = ae->ae_ldrv.al_state[ldrv]; 1039 sc->amr_drive[ldrv].al_properties = ae->ae_ldrv.al_properties[ldrv]; 1040 debug(2, " drive %d: %d state %x properties %x\n", ldrv, sc->amr_drive[ldrv].al_size, 1041 sc->amr_drive[ldrv].al_state, sc->amr_drive[ldrv].al_properties); 1042 } 1043 1044 sc->amr_maxdrives = 8; 1045 sc->amr_maxchan = ae->ae_adapter.aa_channels; 1046 sc->amr_maxio = ae->ae_adapter.aa_maxio; 1047 free(ae, M_DEVBUF); 1048 } 1049 1050 /* 1051 * Mark remaining drives as unused. 1052 */ 1053 for (; ldrv < AMR_MAXLD; ldrv++) 1054 sc->amr_drive[ldrv].al_size = 0xffffffff; 1055 1056 /* 1057 * Cap the maximum number of outstanding I/Os. AMI's Linux driver doesn't trust 1058 * the controller's reported value, and lockups have been seen when we do. 1059 */ 1060 sc->amr_maxio = imin(sc->amr_maxio, AMR_LIMITCMD); 1061 1062 return(0); 1063} 1064 1065/******************************************************************************** 1066 * Run a generic enquiry-style command. 1067 */ 1068static void * 1069amr_enquiry(struct amr_softc *sc, size_t bufsize, u_int8_t cmd, u_int8_t cmdsub, u_int8_t cmdqual, int *status) 1070{ 1071 struct amr_command *ac; 1072 void *result; 1073 u_int8_t *mbox; 1074 int error; 1075 1076 debug_called(1); 1077 1078 error = 1; 1079 result = NULL; 1080 1081 /* get ourselves a command buffer */ 1082 mtx_lock(&sc->amr_list_lock); 1083 ac = amr_alloccmd(sc); 1084 mtx_unlock(&sc->amr_list_lock); 1085 if (ac == NULL) 1086 goto out; 1087 /* allocate the response structure */ 1088 if ((result = malloc(bufsize, M_DEVBUF, M_ZERO|M_NOWAIT)) == NULL) 1089 goto out; 1090 /* set command flags */ 1091 1092 ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAIN; 1093 1094 /* point the command at our data */ 1095 ac->ac_data = result; 1096 ac->ac_length = bufsize; 1097 1098 /* build the command proper */ 1099 mbox = (u_int8_t *)&ac->ac_mailbox; /* XXX want a real structure for this? */ 1100 mbox[0] = cmd; 1101 mbox[2] = cmdsub; 1102 mbox[3] = cmdqual; 1103 *status = 0; 1104 1105 /* can't assume that interrupts are going to work here, so play it safe */ 1106 if (sc->amr_poll_command(ac)) 1107 goto out; 1108 error = ac->ac_status; 1109 *status = ac->ac_status; 1110 1111 out: 1112 mtx_lock(&sc->amr_list_lock); 1113 if (ac != NULL) 1114 amr_releasecmd(ac); 1115 mtx_unlock(&sc->amr_list_lock); 1116 if ((error != 0) && (result != NULL)) { 1117 free(result, M_DEVBUF); 1118 result = NULL; 1119 } 1120 return(result); 1121} 1122 1123/******************************************************************************** 1124 * Flush the controller's internal cache, return status. 1125 */ 1126int 1127amr_flush(struct amr_softc *sc) 1128{ 1129 struct amr_command *ac; 1130 int error; 1131 1132 /* get ourselves a command buffer */ 1133 error = 1; 1134 mtx_lock(&sc->amr_list_lock); 1135 ac = amr_alloccmd(sc); 1136 mtx_unlock(&sc->amr_list_lock); 1137 if (ac == NULL) 1138 goto out; 1139 /* set command flags */ 1140 ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT; 1141 1142 /* build the command proper */ 1143 ac->ac_mailbox.mb_command = AMR_CMD_FLUSH; 1144 1145 /* we have to poll, as the system may be going down or otherwise damaged */ 1146 if (sc->amr_poll_command(ac)) 1147 goto out; 1148 error = ac->ac_status; 1149 1150 out: 1151 mtx_lock(&sc->amr_list_lock); 1152 if (ac != NULL) 1153 amr_releasecmd(ac); 1154 mtx_unlock(&sc->amr_list_lock); 1155 return(error); 1156} 1157 1158/******************************************************************************** 1159 * Detect extented cdb >> greater than 10 byte cdb support 1160 * returns '1' means this support exist 1161 * returns '0' means this support doesn't exist 1162 */ 1163static int 1164amr_support_ext_cdb(struct amr_softc *sc) 1165{ 1166 struct amr_command *ac; 1167 u_int8_t *mbox; 1168 int error; 1169 1170 /* get ourselves a command buffer */ 1171 error = 0; 1172 mtx_lock(&sc->amr_list_lock); 1173 ac = amr_alloccmd(sc); 1174 mtx_unlock(&sc->amr_list_lock); 1175 if (ac == NULL) 1176 goto out; 1177 /* set command flags */ 1178 ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT; 1179 1180 /* build the command proper */ 1181 mbox = (u_int8_t *)&ac->ac_mailbox; /* XXX want a real structure for this? */ 1182 mbox[0] = 0xA4; 1183 mbox[2] = 0x16; 1184 1185 1186 /* we have to poll, as the system may be going down or otherwise damaged */ 1187 if (sc->amr_poll_command(ac)) 1188 goto out; 1189 if( ac->ac_status == AMR_STATUS_SUCCESS ) { 1190 error = 1; 1191 } 1192 1193out: 1194 mtx_lock(&sc->amr_list_lock); 1195 if (ac != NULL) 1196 amr_releasecmd(ac); 1197 mtx_unlock(&sc->amr_list_lock); 1198 return(error); 1199} 1200 1201/******************************************************************************** 1202 * Try to find I/O work for the controller from one or more of the work queues. 1203 * 1204 * We make the assumption that if the controller is not ready to take a command 1205 * at some given time, it will generate an interrupt at some later time when 1206 * it is. 1207 */ 1208void 1209amr_startio(struct amr_softc *sc) 1210{ 1211 struct amr_command *ac; 1212 1213 /* spin until something prevents us from doing any work */ 1214 for (;;) { 1215 1216 /* Don't bother to queue commands no bounce buffers are available. */ 1217 if (sc->amr_state & AMR_STATE_QUEUE_FRZN) 1218 break; 1219 1220 /* try to get a ready command */ 1221 ac = amr_dequeue_ready(sc); 1222 1223 /* if that failed, build a command from a bio */ 1224 if (ac == NULL) 1225 (void)amr_bio_command(sc, &ac); 1226 1227#if AMR_ENABLE_CAM != 0 1228 /* if that failed, build a command from a ccb */ 1229 if (ac == NULL) 1230 (void)amr_cam_command(sc, &ac); 1231#endif 1232 1233 /* if we don't have anything to do, give up */ 1234 if (ac == NULL) 1235 break; 1236 1237 /* try to give the command to the controller; if this fails save it for later and give up */ 1238 if (amr_start(ac)) { 1239 debug(2, "controller busy, command deferred"); 1240 amr_requeue_ready(ac); /* XXX schedule retry very soon? */ 1241 break; 1242 } 1243 } 1244} 1245 1246/******************************************************************************** 1247 * Handle completion of an I/O command. 1248 */ 1249static void 1250amr_completeio(struct amr_command *ac) 1251{ 1252 struct amrd_softc *sc = ac->ac_bio->bio_disk->d_drv1; 1253 static struct timeval lastfail; 1254 static int curfail; 1255 1256 if (ac->ac_status != AMR_STATUS_SUCCESS) { /* could be more verbose here? */ 1257 ac->ac_bio->bio_error = EIO; 1258 ac->ac_bio->bio_flags |= BIO_ERROR; 1259 1260 if (ppsratecheck(&lastfail, &curfail, 1)) 1261 device_printf(sc->amrd_dev, "I/O error - 0x%x\n", ac->ac_status); 1262/* amr_printcommand(ac);*/ 1263 } 1264 amrd_intr(ac->ac_bio); 1265 mtx_lock(&ac->ac_sc->amr_list_lock); 1266 amr_releasecmd(ac); 1267 mtx_unlock(&ac->ac_sc->amr_list_lock); 1268} 1269 1270/******************************************************************************** 1271 ******************************************************************************** 1272 Command Processing 1273 ******************************************************************************** 1274 ********************************************************************************/ 1275 1276/******************************************************************************** 1277 * Convert a bio off the top of the bio queue into a command. 1278 */ 1279static int 1280amr_bio_command(struct amr_softc *sc, struct amr_command **acp) 1281{ 1282 struct amr_command *ac; 1283 struct amrd_softc *amrd; 1284 struct bio *bio; 1285 int error; 1286 int blkcount; 1287 int driveno; 1288 int cmd; 1289 1290 ac = NULL; 1291 error = 0; 1292 1293 /* get a command */ 1294 if ((ac = amr_alloccmd(sc)) == NULL) 1295 return (ENOMEM); 1296 1297 /* get a bio to work on */ 1298 if ((bio = amr_dequeue_bio(sc)) == NULL) { 1299 amr_releasecmd(ac); 1300 return (0); 1301 } 1302 1303 /* connect the bio to the command */ 1304 ac->ac_complete = amr_completeio; 1305 ac->ac_bio = bio; 1306 ac->ac_data = bio->bio_data; 1307 ac->ac_length = bio->bio_bcount; 1308 if (bio->bio_cmd == BIO_READ) { 1309 ac->ac_flags |= AMR_CMD_DATAIN; 1310 if (AMR_IS_SG64(sc)) { 1311 cmd = AMR_CMD_LREAD64; 1312 ac->ac_flags |= AMR_CMD_SG64; 1313 } else 1314 cmd = AMR_CMD_LREAD; 1315 } else { 1316 ac->ac_flags |= AMR_CMD_DATAOUT; 1317 if (AMR_IS_SG64(sc)) { 1318 cmd = AMR_CMD_LWRITE64; 1319 ac->ac_flags |= AMR_CMD_SG64; 1320 } else 1321 cmd = AMR_CMD_LWRITE; 1322 } 1323 amrd = (struct amrd_softc *)bio->bio_disk->d_drv1; 1324 driveno = amrd->amrd_drive - sc->amr_drive; 1325 blkcount = (bio->bio_bcount + AMR_BLKSIZE - 1) / AMR_BLKSIZE; 1326 1327 ac->ac_mailbox.mb_command = cmd; 1328 ac->ac_mailbox.mb_blkcount = blkcount; 1329 ac->ac_mailbox.mb_lba = bio->bio_pblkno; 1330 ac->ac_mailbox.mb_drive = driveno; 1331 if (sc->amr_state & AMR_STATE_REMAP_LD) 1332 ac->ac_mailbox.mb_drive |= 0x80; 1333 1334 /* we fill in the s/g related data when the command is mapped */ 1335 1336 if ((bio->bio_pblkno + blkcount) > sc->amr_drive[driveno].al_size) 1337 device_printf(sc->amr_dev, "I/O beyond end of unit (%lld,%d > %lu)\n", 1338 (long long)bio->bio_pblkno, blkcount, 1339 (u_long)sc->amr_drive[driveno].al_size); 1340 1341 *acp = ac; 1342 return(error); 1343} 1344 1345/******************************************************************************** 1346 * Take a command, submit it to the controller and sleep until it completes 1347 * or fails. Interrupts must be enabled, returns nonzero on error. 1348 */ 1349static int 1350amr_wait_command(struct amr_command *ac) 1351{ 1352 int error = 0; 1353 struct amr_softc *sc = ac->ac_sc; 1354 1355 debug_called(1); 1356 1357 ac->ac_complete = NULL; 1358 ac->ac_flags |= AMR_CMD_SLEEP; 1359 if ((error = amr_start(ac)) != 0) { 1360 return(error); 1361 } 1362 1363 while ((ac->ac_flags & AMR_CMD_BUSY) && (error != EWOULDBLOCK)) { 1364 error = msleep(ac,&sc->amr_list_lock, PRIBIO, "amrwcmd", 0); 1365 } 1366 1367 return(error); 1368} 1369 1370/******************************************************************************** 1371 * Take a command, submit it to the controller and busy-wait for it to return. 1372 * Returns nonzero on error. Can be safely called with interrupts enabled. 1373 */ 1374static int 1375amr_std_poll_command(struct amr_command *ac) 1376{ 1377 struct amr_softc *sc = ac->ac_sc; 1378 int error, count; 1379 1380 debug_called(2); 1381 1382 ac->ac_complete = NULL; 1383 if ((error = amr_start(ac)) != 0) 1384 return(error); 1385 1386 count = 0; 1387 do { 1388 /* 1389 * Poll for completion, although the interrupt handler may beat us to it. 1390 * Note that the timeout here is somewhat arbitrary. 1391 */ 1392 amr_done(sc); 1393 DELAY(1000); 1394 } while ((ac->ac_flags & AMR_CMD_BUSY) && (count++ < 1000)); 1395 if (!(ac->ac_flags & AMR_CMD_BUSY)) { 1396 error = 0; 1397 } else { 1398 /* XXX the slot is now marked permanently busy */ 1399 error = EIO; 1400 device_printf(sc->amr_dev, "polled command timeout\n"); 1401 } 1402 return(error); 1403} 1404 1405static void 1406amr_setup_polled_dmamap(void *arg, bus_dma_segment_t *segs, int nsegs, int err) 1407{ 1408 struct amr_command *ac = arg; 1409 struct amr_softc *sc = ac->ac_sc; 1410 int flags; 1411 1412 flags = 0; 1413 if (ac->ac_flags & AMR_CMD_DATAIN) 1414 flags |= BUS_DMASYNC_PREREAD; 1415 if (ac->ac_flags & AMR_CMD_DATAOUT) 1416 flags |= BUS_DMASYNC_PREWRITE; 1417 1418 if (AC_IS_SG64(ac)) { 1419 amr_setup_dma64map(arg, segs, nsegs, err); 1420 bus_dmamap_sync(sc->amr_buffer64_dmat,ac->ac_dma64map, flags); 1421 } else { 1422 amr_setup_dmamap(arg, segs, nsegs, err); 1423 bus_dmamap_sync(sc->amr_buffer_dmat,ac->ac_dmamap, flags); 1424 } 1425 sc->amr_poll_command1(sc, ac); 1426} 1427 1428/******************************************************************************** 1429 * Take a command, submit it to the controller and busy-wait for it to return. 1430 * Returns nonzero on error. Can be safely called with interrupts enabled. 1431 */ 1432static int 1433amr_quartz_poll_command(struct amr_command *ac) 1434{ 1435 bus_dma_tag_t tag; 1436 bus_dmamap_t datamap; 1437 struct amr_softc *sc = ac->ac_sc; 1438 int error; 1439 1440 debug_called(2); 1441 1442 error = 0; 1443 1444 if (AC_IS_SG64(ac)) { 1445 tag = sc->amr_buffer64_dmat; 1446 datamap = ac->ac_dma64map; 1447 } else { 1448 tag = sc->amr_buffer_dmat; 1449 datamap = ac->ac_dmamap; 1450 } 1451 1452 /* now we have a slot, we can map the command (unmapped in amr_complete) */ 1453 if (ac->ac_data != 0) { 1454 if (bus_dmamap_load(tag, datamap, ac->ac_data, ac->ac_length, 1455 amr_setup_polled_dmamap, ac, BUS_DMA_NOWAIT) != 0) { 1456 error = 1; 1457 } 1458 } else { 1459 error = amr_quartz_poll_command1(sc, ac); 1460 } 1461 1462 return (error); 1463} 1464 1465static int 1466amr_quartz_poll_command1(struct amr_softc *sc, struct amr_command *ac) 1467{ 1468 int count, error; 1469 1470 mtx_lock(&sc->amr_hw_lock); 1471 if ((sc->amr_state & AMR_STATE_INTEN) == 0) { 1472 count=0; 1473 while (sc->amr_busyslots) { 1474 msleep(sc, &sc->amr_hw_lock, PRIBIO | PCATCH, "amrpoll", hz); 1475 if(count++>10) { 1476 break; 1477 } 1478 } 1479 1480 if(sc->amr_busyslots) { 1481 device_printf(sc->amr_dev, "adapter is busy\n"); 1482 mtx_unlock(&sc->amr_hw_lock); 1483 if (ac->ac_data != NULL) { 1484 if (AC_IS_SG64(ac)) 1485 bus_dmamap_unload(sc->amr_buffer64_dmat, ac->ac_dma64map); 1486 else 1487 bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_dmamap); 1488 } 1489 ac->ac_status=0; 1490 return(1); 1491 } 1492 } 1493 1494 bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, AMR_MBOX_CMDSIZE); 1495 1496 /* clear the poll/ack fields in the mailbox */ 1497 sc->amr_mailbox->mb_ident = 0xFE; 1498 sc->amr_mailbox->mb_nstatus = 0xFF; 1499 sc->amr_mailbox->mb_status = 0xFF; 1500 sc->amr_mailbox->mb_poll = 0; 1501 sc->amr_mailbox->mb_ack = 0; 1502 sc->amr_mailbox->mb_busy = 1; 1503 1504 AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT); 1505 1506 while(sc->amr_mailbox->mb_nstatus == 0xFF) 1507 DELAY(1); 1508 while(sc->amr_mailbox->mb_status == 0xFF) 1509 DELAY(1); 1510 ac->ac_status=sc->amr_mailbox->mb_status; 1511 error = (ac->ac_status !=AMR_STATUS_SUCCESS) ? 1:0; 1512 while(sc->amr_mailbox->mb_poll != 0x77) 1513 DELAY(1); 1514 sc->amr_mailbox->mb_poll = 0; 1515 sc->amr_mailbox->mb_ack = 0x77; 1516 1517 /* acknowledge that we have the commands */ 1518 AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_ACK); 1519 while(AMR_QGET_IDB(sc) & AMR_QIDB_ACK) 1520 DELAY(1); 1521 mtx_unlock(&sc->amr_hw_lock); 1522 1523 /* unmap the command's data buffer */ 1524 if (ac->ac_flags & AMR_CMD_DATAIN) { 1525 bus_dmamap_sync(sc->amr_buffer_dmat,ac->ac_dmamap, 1526 BUS_DMASYNC_POSTREAD); 1527 } 1528 if (ac->ac_flags & AMR_CMD_DATAOUT) { 1529 bus_dmamap_sync(sc->amr_buffer_dmat,ac->ac_dmamap, 1530 BUS_DMASYNC_POSTWRITE); 1531 } 1532 if (AC_IS_SG64(ac)) 1533 bus_dmamap_unload(sc->amr_buffer64_dmat, ac->ac_dma64map); 1534 else 1535 bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_dmamap); 1536 1537 return(error); 1538} 1539 1540static __inline int 1541amr_freeslot(struct amr_command *ac) 1542{ 1543 struct amr_softc *sc = ac->ac_sc; 1544 int slot; 1545 1546 debug_called(3); 1547 1548 slot = ac->ac_slot; 1549 if (sc->amr_busycmd[slot] == NULL) 1550 panic("amr: slot %d not busy?\n", slot); 1551 1552 sc->amr_busycmd[slot] = NULL; 1553 atomic_subtract_int(&sc->amr_busyslots, 1); 1554 1555 return (0); 1556} 1557 1558/******************************************************************************** 1559 * Map/unmap (ac)'s data in the controller's addressable space as required. 1560 * 1561 * These functions may be safely called multiple times on a given command. 1562 */ 1563static void 1564amr_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error) 1565{ 1566 struct amr_command *ac = (struct amr_command *)arg; 1567 struct amr_sgentry *sg; 1568 int i; 1569 u_int8_t *sgc; 1570 1571 debug_called(3); 1572 1573 /* get base address of s/g table */ 1574 sg = ac->ac_sg.sg32; 1575 1576 /* save data physical address */ 1577 1578 /* for AMR_CMD_CONFIG Read/Write the s/g count goes elsewhere */ 1579 if (ac->ac_mailbox.mb_command == AMR_CMD_CONFIG && ( 1580 ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_channel == AMR_CONFIG_READ_NVRAM_CONFIG || 1581 ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_channel == AMR_CONFIG_WRITE_NVRAM_CONFIG)) { 1582 sgc = &(((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_param); 1583 } else { 1584 sgc = &ac->ac_mailbox.mb_nsgelem; 1585 } 1586 1587 /* decide whether we need to populate the s/g table */ 1588 if (nsegments < 2) { 1589 *sgc = 0; 1590 ac->ac_mailbox.mb_nsgelem = 0; 1591 ac->ac_mailbox.mb_physaddr = segs[0].ds_addr; 1592 } else { 1593 ac->ac_mailbox.mb_nsgelem = nsegments; 1594 *sgc = nsegments; 1595 /* XXX Setting these to 0 might not be needed. */ 1596 ac->ac_sg64_lo = 0; 1597 ac->ac_sg64_hi = 0; 1598 ac->ac_mailbox.mb_physaddr = ac->ac_sgbusaddr; 1599 for (i = 0; i < nsegments; i++, sg++) { 1600 sg->sg_addr = segs[i].ds_addr; 1601 sg->sg_count = segs[i].ds_len; 1602 } 1603 } 1604 1605} 1606 1607static void 1608amr_setup_dma64map(void *arg, bus_dma_segment_t *segs, int nsegments, int error) 1609{ 1610 struct amr_command *ac = (struct amr_command *)arg; 1611 struct amr_sg64entry *sg; 1612 int i; 1613 u_int8_t *sgc; 1614 1615 debug_called(3); 1616 1617 /* get base address of s/g table */ 1618 sg = ac->ac_sg.sg64; 1619 1620 /* save data physical address */ 1621 1622 /* for AMR_CMD_CONFIG Read/Write the s/g count goes elsewhere */ 1623 if (ac->ac_mailbox.mb_command == AMR_CMD_CONFIG && ( 1624 ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_channel == AMR_CONFIG_READ_NVRAM_CONFIG || 1625 ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_channel == AMR_CONFIG_WRITE_NVRAM_CONFIG)) { 1626 sgc = &(((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_param); 1627 } else { 1628 sgc = &ac->ac_mailbox.mb_nsgelem; 1629 } 1630 1631 ac->ac_mailbox.mb_nsgelem = nsegments; 1632 *sgc = nsegments; 1633 ac->ac_sg64_hi = 0; 1634 ac->ac_sg64_lo = ac->ac_sgbusaddr; 1635 ac->ac_mailbox.mb_physaddr = 0xffffffff; 1636 for (i = 0; i < nsegments; i++, sg++) { 1637 sg->sg_addr = segs[i].ds_addr; 1638 sg->sg_count = segs[i].ds_len; 1639 } 1640} 1641 1642static void 1643amr_setup_ccbmap(void *arg, bus_dma_segment_t *segs, int nsegments, int error) 1644{ 1645 struct amr_command *ac = (struct amr_command *)arg; 1646 struct amr_softc *sc = ac->ac_sc; 1647 struct amr_sgentry *sg; 1648 struct amr_passthrough *ap = (struct amr_passthrough *)ac->ac_data; 1649 struct amr_ext_passthrough *aep = (struct amr_ext_passthrough *)ac->ac_data; 1650 int i; 1651 1652 /* get base address of s/g table */ 1653 sg = ac->ac_sg.sg32; 1654 1655 /* decide whether we need to populate the s/g table */ 1656 if( ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS ) { 1657 if (nsegments < 2) { 1658 aep->ap_no_sg_elements = 0; 1659 aep->ap_data_transfer_address = segs[0].ds_addr; 1660 } else { 1661 /* save s/g table information in passthrough */ 1662 aep->ap_no_sg_elements = nsegments; 1663 aep->ap_data_transfer_address = ac->ac_sgbusaddr; 1664 /* 1665 * populate s/g table (overwrites previous call which mapped the 1666 * passthrough) 1667 */ 1668 for (i = 0; i < nsegments; i++, sg++) { 1669 sg->sg_addr = segs[i].ds_addr; 1670 sg->sg_count = segs[i].ds_len; 1671 debug(3, " %d: 0x%x/%d", i, sg->sg_addr, sg->sg_count); 1672 } 1673 } 1674 debug(3, "slot %d %d segments at 0x%x\n", ac->ac_slot, 1675 aep->ap_no_sg_elements, aep->ap_data_transfer_address); 1676 } else { 1677 if (nsegments < 2) { 1678 ap->ap_no_sg_elements = 0; 1679 ap->ap_data_transfer_address = segs[0].ds_addr; 1680 } else { 1681 /* save s/g table information in passthrough */ 1682 ap->ap_no_sg_elements = nsegments; 1683 ap->ap_data_transfer_address = ac->ac_sgbusaddr; 1684 /* 1685 * populate s/g table (overwrites previous call which mapped the 1686 * passthrough) 1687 */ 1688 for (i = 0; i < nsegments; i++, sg++) { 1689 sg->sg_addr = segs[i].ds_addr; 1690 sg->sg_count = segs[i].ds_len; 1691 debug(3, " %d: 0x%x/%d", i, sg->sg_addr, sg->sg_count); 1692 } 1693 } 1694 debug(3, "slot %d %d segments at 0x%x\n", ac->ac_slot, 1695 ap->ap_no_sg_elements, ap->ap_data_transfer_address); 1696 } 1697 if (ac->ac_flags & AMR_CMD_CCB_DATAIN) 1698 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, 1699 BUS_DMASYNC_PREREAD); 1700 if (ac->ac_flags & AMR_CMD_CCB_DATAOUT) 1701 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, 1702 BUS_DMASYNC_PREWRITE); 1703 if ((ac->ac_flags & (AMR_CMD_CCB_DATAIN | AMR_CMD_CCB_DATAOUT)) == 0) 1704 panic("no direction for ccb?\n"); 1705 1706 if (ac->ac_flags & AMR_CMD_DATAIN) 1707 bus_dmamap_sync(sc->amr_buffer_dmat,ac->ac_dmamap,BUS_DMASYNC_PREREAD); 1708 if (ac->ac_flags & AMR_CMD_DATAOUT) 1709 bus_dmamap_sync(sc->amr_buffer_dmat,ac->ac_dmamap,BUS_DMASYNC_PREWRITE); 1710 1711 ac->ac_flags |= AMR_CMD_MAPPED; 1712 1713 if (sc->amr_submit_command(ac) == EBUSY) { 1714 amr_freeslot(ac); 1715 amr_requeue_ready(ac); 1716 } 1717} 1718 1719static void 1720amr_setup_ccb64map(void *arg, bus_dma_segment_t *segs, int nsegments, int error) 1721{ 1722 struct amr_command *ac = (struct amr_command *)arg; 1723 struct amr_softc *sc = ac->ac_sc; 1724 struct amr_sg64entry *sg; 1725 struct amr_passthrough *ap = (struct amr_passthrough *)ac->ac_data; 1726 struct amr_ext_passthrough *aep = (struct amr_ext_passthrough *)ac->ac_data; 1727 int i; 1728 1729 /* get base address of s/g table */ 1730 sg = ac->ac_sg.sg64; 1731 1732 /* decide whether we need to populate the s/g table */ 1733 if( ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS ) { 1734 /* save s/g table information in passthrough */ 1735 aep->ap_no_sg_elements = nsegments; 1736 aep->ap_data_transfer_address = ac->ac_sgbusaddr; 1737 /* 1738 * populate s/g table (overwrites previous call which mapped the 1739 * passthrough) 1740 */ 1741 for (i = 0; i < nsegments; i++, sg++) { 1742 sg->sg_addr = segs[i].ds_addr; 1743 sg->sg_count = segs[i].ds_len; 1744 debug(3, " %d: 0x%x/%d", i, sg->sg_addr, sg->sg_count); 1745 } 1746 debug(3, "slot %d %d segments at 0x%x\n", ac->ac_slot, 1747 aep->ap_no_sg_elements, aep->ap_data_transfer_address); 1748 } else { 1749 /* save s/g table information in passthrough */ 1750 ap->ap_no_sg_elements = nsegments; 1751 ap->ap_data_transfer_address = ac->ac_sgbusaddr; 1752 /* 1753 * populate s/g table (overwrites previous call which mapped the 1754 * passthrough) 1755 */ 1756 for (i = 0; i < nsegments; i++, sg++) { 1757 sg->sg_addr = segs[i].ds_addr; 1758 sg->sg_count = segs[i].ds_len; 1759 debug(3, " %d: 0x%x/%d", i, sg->sg_addr, sg->sg_count); 1760 } 1761 debug(3, "slot %d %d segments at 0x%x\n", ac->ac_slot, 1762 ap->ap_no_sg_elements, ap->ap_data_transfer_address); 1763 } 1764 if (ac->ac_flags & AMR_CMD_CCB_DATAIN) 1765 bus_dmamap_sync(sc->amr_buffer64_dmat, ac->ac_ccb_dma64map, 1766 BUS_DMASYNC_PREREAD); 1767 if (ac->ac_flags & AMR_CMD_CCB_DATAOUT) 1768 bus_dmamap_sync(sc->amr_buffer64_dmat, ac->ac_ccb_dma64map, 1769 BUS_DMASYNC_PREWRITE); 1770 if ((ac->ac_flags & (AMR_CMD_CCB_DATAIN | AMR_CMD_CCB_DATAOUT)) == 0) 1771 panic("no direction for ccb?\n"); 1772 1773 if (ac->ac_flags & AMR_CMD_DATAIN) 1774 bus_dmamap_sync(sc->amr_buffer64_dmat, ac->ac_dma64map, 1775 BUS_DMASYNC_PREREAD); 1776 if (ac->ac_flags & AMR_CMD_DATAOUT) 1777 bus_dmamap_sync(sc->amr_buffer64_dmat, ac->ac_dma64map, 1778 BUS_DMASYNC_PREWRITE); 1779 1780 ac->ac_flags |= AMR_CMD_MAPPED; 1781 1782 if (sc->amr_submit_command(ac) == EBUSY) { 1783 amr_freeslot(ac); 1784 amr_requeue_ready(ac); 1785 } 1786} 1787 1788static void 1789amr_setup_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nsegments, 1790 int error) 1791{ 1792 struct amr_command *ac = (struct amr_command *)arg; 1793 struct amr_softc *sc = ac->ac_sc; 1794 1795 amr_setup_dmamap(arg, segs, nsegments, error); 1796 1797 if (bus_dmamap_load(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, 1798 ac->ac_ccb_data, ac->ac_ccb_length, amr_setup_ccbmap, ac, 1799 0) == EINPROGRESS) { 1800 sc->amr_state |= AMR_STATE_QUEUE_FRZN; 1801 } 1802} 1803 1804static void 1805amr_setup_dma64map_cb(void *arg, bus_dma_segment_t *segs, int nsegments, 1806 int error) 1807{ 1808 struct amr_command *ac = (struct amr_command *)arg; 1809 struct amr_softc *sc = ac->ac_sc; 1810 1811 amr_setup_dma64map(arg, segs, nsegments, error); 1812 1813 if (bus_dmamap_load(sc->amr_buffer64_dmat, ac->ac_ccb_dma64map, 1814 ac->ac_ccb_data, ac->ac_ccb_length, amr_setup_ccb64map, ac, 1815 0) == EINPROGRESS) { 1816 sc->amr_state |= AMR_STATE_QUEUE_FRZN; 1817 } 1818} 1819 1820static int 1821amr_mapcmd(struct amr_command *ac) 1822{ 1823 bus_dma_tag_t tag; 1824 bus_dmamap_t datamap; 1825 bus_dmamap_callback_t *cb; 1826 struct amr_softc *sc = ac->ac_sc; 1827 1828 debug_called(3); 1829 1830 if (AC_IS_SG64(ac)) { 1831 tag = sc->amr_buffer64_dmat; 1832 datamap = ac->ac_dma64map; 1833 cb = amr_setup_dma64map_cb; 1834 } else { 1835 tag = sc->amr_buffer_dmat; 1836 datamap = ac->ac_dmamap; 1837 cb = amr_setup_dmamap_cb; 1838 } 1839 1840 /* if the command involves data at all, and hasn't been mapped */ 1841 if ((ac->ac_flags & AMR_CMD_MAPPED) == 0 && (ac->ac_data != NULL)) { 1842 if (ac->ac_ccb_data == NULL) 1843 cb = amr_setup_data_dmamap; 1844 /* map the data buffers into bus space and build the s/g list */ 1845 if (bus_dmamap_load(tag, datamap, ac->ac_data, ac->ac_length, 1846 cb, ac, 0) == EINPROGRESS) { 1847 sc->amr_state |= AMR_STATE_QUEUE_FRZN; 1848 } 1849 } else { 1850 if (sc->amr_submit_command(ac) == EBUSY) { 1851 amr_freeslot(ac); 1852 amr_requeue_ready(ac); 1853 } 1854 } 1855 1856 return (0); 1857} 1858 1859static void 1860amr_unmapcmd(struct amr_command *ac) 1861{ 1862 struct amr_softc *sc = ac->ac_sc; 1863 int flag; 1864 1865 debug_called(3); 1866 1867 /* if the command involved data at all and was mapped */ 1868 if (ac->ac_flags & AMR_CMD_MAPPED) { 1869 1870 if (ac->ac_data != NULL) { 1871 1872 flag = 0; 1873 if (ac->ac_flags & AMR_CMD_DATAIN) 1874 flag |= BUS_DMASYNC_POSTREAD; 1875 if (ac->ac_flags & AMR_CMD_DATAOUT) 1876 flag |= BUS_DMASYNC_POSTWRITE; 1877 1878 if (AC_IS_SG64(ac)) { 1879 bus_dmamap_sync(sc->amr_buffer64_dmat, ac->ac_dma64map, flag); 1880 bus_dmamap_unload(sc->amr_buffer64_dmat, ac->ac_dma64map); 1881 } else { 1882 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, flag); 1883 bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_dmamap); 1884 } 1885 } 1886 1887 if (ac->ac_ccb_data != NULL) { 1888 1889 flag = 0; 1890 if (ac->ac_flags & AMR_CMD_CCB_DATAIN) 1891 flag |= BUS_DMASYNC_POSTREAD; 1892 if (ac->ac_flags & AMR_CMD_CCB_DATAOUT) 1893 flag |= BUS_DMASYNC_POSTWRITE; 1894 1895 if (AC_IS_SG64(ac)) { 1896 bus_dmamap_sync(sc->amr_buffer64_dmat,ac->ac_ccb_dma64map,flag); 1897 bus_dmamap_unload(sc->amr_buffer64_dmat, ac->ac_ccb_dma64map); 1898 } else { 1899 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, flag); 1900 bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_ccb_dmamap); 1901 } 1902 } 1903 ac->ac_flags &= ~AMR_CMD_MAPPED; 1904 } 1905} 1906 1907static void 1908amr_setup_data_dmamap(void *arg, bus_dma_segment_t *segs, int nsegs, int err) 1909{ 1910 struct amr_command *ac = arg; 1911 struct amr_softc *sc = ac->ac_sc; 1912 int flags; 1913 1914 flags = 0; 1915 if (ac->ac_flags & AMR_CMD_DATAIN) 1916 flags |= BUS_DMASYNC_PREREAD; 1917 if (ac->ac_flags & AMR_CMD_DATAOUT) 1918 flags |= BUS_DMASYNC_PREWRITE; 1919 1920 if (AC_IS_SG64(ac)) { 1921 amr_setup_dma64map(arg, segs, nsegs, err); 1922 bus_dmamap_sync(sc->amr_buffer64_dmat,ac->ac_dma64map, flags); 1923 } else { 1924 amr_setup_dmamap(arg, segs, nsegs, err); 1925 bus_dmamap_sync(sc->amr_buffer_dmat,ac->ac_dmamap, flags); 1926 } 1927 ac->ac_flags |= AMR_CMD_MAPPED; 1928 1929 if (sc->amr_submit_command(ac) == EBUSY) { 1930 amr_freeslot(ac); 1931 amr_requeue_ready(ac); 1932 } 1933} 1934 1935/******************************************************************************** 1936 * Take a command and give it to the controller, returns 0 if successful, or 1937 * EBUSY if the command should be retried later. 1938 */ 1939static int 1940amr_start(struct amr_command *ac) 1941{ 1942 struct amr_softc *sc; 1943 int error = 0; 1944 int slot; 1945 1946 debug_called(3); 1947 1948 /* mark command as busy so that polling consumer can tell */ 1949 sc = ac->ac_sc; 1950 ac->ac_flags |= AMR_CMD_BUSY; 1951 1952 /* get a command slot (freed in amr_done) */ 1953 slot = ac->ac_slot; 1954 if (sc->amr_busycmd[slot] != NULL) 1955 panic("amr: slot %d busy?\n", slot); 1956 sc->amr_busycmd[slot] = ac; 1957 atomic_add_int(&sc->amr_busyslots, 1); 1958 1959 /* Now we have a slot, we can map the command (unmapped in amr_complete). */ 1960 if ((error = amr_mapcmd(ac)) == ENOMEM) { 1961 /* 1962 * Memroy resources are short, so free the slot and let this be tried 1963 * later. 1964 */ 1965 amr_freeslot(ac); 1966 } 1967 1968 return (error); 1969} 1970 1971/******************************************************************************** 1972 * Extract one or more completed commands from the controller (sc) 1973 * 1974 * Returns nonzero if any commands on the work queue were marked as completed. 1975 */ 1976 1977int 1978amr_done(struct amr_softc *sc) 1979{ 1980 struct amr_command *ac; 1981 struct amr_mailbox mbox; 1982 int i, idx, result; 1983 1984 debug_called(3); 1985 1986 /* See if there's anything for us to do */ 1987 result = 0; 1988 1989 /* loop collecting completed commands */ 1990 for (;;) { 1991 /* poll for a completed command's identifier and status */ 1992 if (sc->amr_get_work(sc, &mbox)) { 1993 result = 1; 1994 1995 /* iterate over completed commands in this result */ 1996 for (i = 0; i < mbox.mb_nstatus; i++) { 1997 /* get pointer to busy command */ 1998 idx = mbox.mb_completed[i] - 1; 1999 ac = sc->amr_busycmd[idx]; 2000 2001 /* really a busy command? */ 2002 if (ac != NULL) { 2003 2004 /* pull the command from the busy index */ 2005 amr_freeslot(ac); 2006 2007 /* save status for later use */ 2008 ac->ac_status = mbox.mb_status; 2009 amr_enqueue_completed(ac); 2010 debug(3, "completed command with status %x", mbox.mb_status); 2011 } else { 2012 device_printf(sc->amr_dev, "bad slot %d completed\n", idx); 2013 } 2014 } 2015 } else 2016 break; /* no work */ 2017 } 2018 2019 /* handle completion and timeouts */ 2020 amr_complete(sc, 0); 2021 2022 return(result); 2023} 2024 2025/******************************************************************************** 2026 * Do completion processing on done commands on (sc) 2027 */ 2028 2029static void 2030amr_complete(void *context, int pending) 2031{ 2032 struct amr_softc *sc = (struct amr_softc *)context; 2033 struct amr_command *ac; 2034 2035 debug_called(3); 2036 2037 /* pull completed commands off the queue */ 2038 for (;;) { 2039 ac = amr_dequeue_completed(sc); 2040 if (ac == NULL) 2041 break; 2042 2043 /* unmap the command's data buffer */ 2044 amr_unmapcmd(ac); 2045 2046 /* 2047 * Is there a completion handler? 2048 */ 2049 if (ac->ac_complete != NULL) { 2050 /* unbusy the command */ 2051 ac->ac_flags &= ~AMR_CMD_BUSY; 2052 ac->ac_complete(ac); 2053 2054 /* 2055 * Is someone sleeping on this one? 2056 */ 2057 } else { 2058 mtx_lock(&sc->amr_list_lock); 2059 ac->ac_flags &= ~AMR_CMD_BUSY; 2060 if (ac->ac_flags & AMR_CMD_SLEEP) { 2061 /* unbusy the command */ 2062 wakeup(ac); 2063 } 2064 mtx_unlock(&sc->amr_list_lock); 2065 } 2066 2067 if(!sc->amr_busyslots) { 2068 wakeup(sc); 2069 } 2070 } 2071 2072 mtx_lock(&sc->amr_list_lock); 2073 sc->amr_state &= ~AMR_STATE_QUEUE_FRZN; 2074 amr_startio(sc); 2075 mtx_unlock(&sc->amr_list_lock); 2076} 2077 2078/******************************************************************************** 2079 ******************************************************************************** 2080 Command Buffer Management 2081 ******************************************************************************** 2082 ********************************************************************************/ 2083 2084/******************************************************************************** 2085 * Get a new command buffer. 2086 * 2087 * This may return NULL in low-memory cases. 2088 * 2089 * If possible, we recycle a command buffer that's been used before. 2090 */ 2091struct amr_command * 2092amr_alloccmd(struct amr_softc *sc) 2093{ 2094 struct amr_command *ac; 2095 2096 debug_called(3); 2097 2098 ac = amr_dequeue_free(sc); 2099 if (ac == NULL) { 2100 amr_alloccmd_cluster(sc); 2101 ac = amr_dequeue_free(sc); 2102 } 2103 if (ac == NULL) { 2104 sc->amr_state |= AMR_STATE_QUEUE_FRZN; 2105 return(NULL); 2106 } 2107 2108 /* clear out significant fields */ 2109 ac->ac_status = 0; 2110 bzero(&ac->ac_mailbox, sizeof(struct amr_mailbox)); 2111 ac->ac_flags = 0; 2112 ac->ac_bio = NULL; 2113 ac->ac_data = NULL; 2114 ac->ac_ccb_data = NULL; 2115 ac->ac_complete = NULL; 2116 return(ac); 2117} 2118 2119/******************************************************************************** 2120 * Release a command buffer for recycling. 2121 */ 2122void 2123amr_releasecmd(struct amr_command *ac) 2124{ 2125 debug_called(3); 2126 2127 amr_enqueue_free(ac); 2128} 2129 2130/******************************************************************************** 2131 * Allocate a new command cluster and initialise it. 2132 */ 2133static void 2134amr_alloccmd_cluster(struct amr_softc *sc) 2135{ 2136 struct amr_command_cluster *acc; 2137 struct amr_command *ac; 2138 int i, nextslot; 2139 2140 if (sc->amr_nextslot > sc->amr_maxio) 2141 return; 2142 acc = malloc(AMR_CMD_CLUSTERSIZE, M_DEVBUF, M_NOWAIT | M_ZERO); 2143 if (acc != NULL) { 2144 nextslot = sc->amr_nextslot; 2145 TAILQ_INSERT_TAIL(&sc->amr_cmd_clusters, acc, acc_link); 2146 for (i = 0; i < AMR_CMD_CLUSTERCOUNT; i++) { 2147 ac = &acc->acc_command[i]; 2148 ac->ac_sc = sc; 2149 ac->ac_slot = nextslot; 2150 2151 /* 2152 * The SG table for each slot is a fixed size and is assumed to 2153 * to hold 64-bit s/g objects when the driver is configured to do 2154 * 64-bit DMA. 32-bit DMA commands still use the same table, but 2155 * cast down to 32-bit objects. 2156 */ 2157 if (AMR_IS_SG64(sc)) { 2158 ac->ac_sgbusaddr = sc->amr_sgbusaddr + 2159 (ac->ac_slot * AMR_NSEG * sizeof(struct amr_sg64entry)); 2160 ac->ac_sg.sg64 = sc->amr_sg64table + (ac->ac_slot * AMR_NSEG); 2161 } else { 2162 ac->ac_sgbusaddr = sc->amr_sgbusaddr + 2163 (ac->ac_slot * AMR_NSEG * sizeof(struct amr_sgentry)); 2164 ac->ac_sg.sg32 = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG); 2165 } 2166 2167 if (bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_dmamap) || 2168 bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_ccb_dmamap) || 2169 (AMR_IS_SG64(sc) && 2170 (bus_dmamap_create(sc->amr_buffer64_dmat, 0,&ac->ac_dma64map) || 2171 bus_dmamap_create(sc->amr_buffer64_dmat, 0, &ac->ac_ccb_dma64map)))) 2172 break; 2173 amr_releasecmd(ac); 2174 if (++nextslot > sc->amr_maxio) 2175 break; 2176 } 2177 sc->amr_nextslot = nextslot; 2178 } 2179} 2180 2181/******************************************************************************** 2182 * Free a command cluster 2183 */ 2184static void 2185amr_freecmd_cluster(struct amr_command_cluster *acc) 2186{ 2187 struct amr_softc *sc = acc->acc_command[0].ac_sc; 2188 int i; 2189 2190 for (i = 0; i < AMR_CMD_CLUSTERCOUNT; i++) { 2191 bus_dmamap_destroy(sc->amr_buffer_dmat, acc->acc_command[i].ac_dmamap); 2192 bus_dmamap_destroy(sc->amr_buffer_dmat, acc->acc_command[i].ac_ccb_dmamap); 2193 if (AMR_IS_SG64(sc)) 2194 bus_dmamap_destroy(sc->amr_buffer64_dmat, acc->acc_command[i].ac_dma64map); 2195 bus_dmamap_destroy(sc->amr_buffer64_dmat, acc->acc_command[i].ac_ccb_dma64map); 2196 } 2197 free(acc, M_DEVBUF); 2198} 2199 2200/******************************************************************************** 2201 ******************************************************************************** 2202 Interface-specific Shims 2203 ******************************************************************************** 2204 ********************************************************************************/ 2205 2206/******************************************************************************** 2207 * Tell the controller that the mailbox contains a valid command 2208 */ 2209static int 2210amr_quartz_submit_command(struct amr_command *ac) 2211{ 2212 struct amr_softc *sc = ac->ac_sc; 2213 int i = 0; 2214 2215 mtx_lock(&sc->amr_hw_lock); 2216 while (sc->amr_mailbox->mb_busy && (i++ < 10)) 2217 DELAY(1); 2218 if (sc->amr_mailbox->mb_busy) { 2219 mtx_unlock(&sc->amr_hw_lock); 2220 return (EBUSY); 2221 } 2222 2223 /* 2224 * Save the slot number so that we can locate this command when complete. 2225 * Note that ident = 0 seems to be special, so we don't use it. 2226 */ 2227 ac->ac_mailbox.mb_ident = ac->ac_slot + 1; /* will be coppied into mbox */ 2228 bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, 14); 2229 sc->amr_mailbox->mb_busy = 1; 2230 sc->amr_mailbox->mb_poll = 0; 2231 sc->amr_mailbox->mb_ack = 0; 2232 sc->amr_mailbox64->sg64_hi = ac->ac_sg64_hi; 2233 sc->amr_mailbox64->sg64_lo = ac->ac_sg64_lo; 2234 2235 AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT); 2236 mtx_unlock(&sc->amr_hw_lock); 2237 return(0); 2238} 2239 2240static int 2241amr_std_submit_command(struct amr_command *ac) 2242{ 2243 struct amr_softc *sc = ac->ac_sc; 2244 2245 mtx_lock(&sc->amr_hw_lock); 2246 if (AMR_SGET_MBSTAT(sc) & AMR_SMBOX_BUSYFLAG) { 2247 mtx_unlock(&sc->amr_hw_lock); 2248 return (EBUSY); 2249 } 2250 2251 /* 2252 * Save the slot number so that we can locate this command when complete. 2253 * Note that ident = 0 seems to be special, so we don't use it. 2254 */ 2255 ac->ac_mailbox.mb_ident = ac->ac_slot + 1; /* will be coppied into mbox */ 2256 bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, 14); 2257 sc->amr_mailbox->mb_busy = 1; 2258 sc->amr_mailbox->mb_poll = 0; 2259 sc->amr_mailbox->mb_ack = 0; 2260 2261 AMR_SPOST_COMMAND(sc); 2262 mtx_unlock(&sc->amr_hw_lock); 2263 return(0); 2264} 2265 2266/******************************************************************************** 2267 * Claim any work that the controller has completed; acknowledge completion, 2268 * save details of the completion in (mbsave) 2269 */ 2270static int 2271amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave) 2272{ 2273 int worked, i; 2274 u_int32_t outd; 2275 u_int8_t nstatus; 2276 u_int8_t completed[46]; 2277 2278 debug_called(3); 2279 2280 worked = 0; 2281 2282 /* work waiting for us? */ 2283 if ((outd = AMR_QGET_ODB(sc)) == AMR_QODB_READY) { 2284 2285 /* acknowledge interrupt */ 2286 AMR_QPUT_ODB(sc, AMR_QODB_READY); 2287 2288 while ((nstatus = sc->amr_mailbox->mb_nstatus) == 0xff) 2289 DELAY(1); 2290 sc->amr_mailbox->mb_nstatus = 0xff; 2291 2292 /* wait until fw wrote out all completions */ 2293 for (i = 0; i < nstatus; i++) { 2294 while ((completed[i] = sc->amr_mailbox->mb_completed[i]) == 0xff) 2295 DELAY(1); 2296 sc->amr_mailbox->mb_completed[i] = 0xff; 2297 } 2298 2299 /* Save information for later processing */ 2300 mbsave->mb_nstatus = nstatus; 2301 mbsave->mb_status = sc->amr_mailbox->mb_status; 2302 sc->amr_mailbox->mb_status = 0xff; 2303 2304 for (i = 0; i < nstatus; i++) 2305 mbsave->mb_completed[i] = completed[i]; 2306 2307 /* acknowledge that we have the commands */ 2308 AMR_QPUT_IDB(sc, AMR_QIDB_ACK); 2309 2310#if 0 2311#ifndef AMR_QUARTZ_GOFASTER 2312 /* 2313 * This waits for the controller to notice that we've taken the 2314 * command from it. It's very inefficient, and we shouldn't do it, 2315 * but if we remove this code, we stop completing commands under 2316 * load. 2317 * 2318 * Peter J says we shouldn't do this. The documentation says we 2319 * should. Who is right? 2320 */ 2321 while(AMR_QGET_IDB(sc) & AMR_QIDB_ACK) 2322 ; /* XXX aiee! what if it dies? */ 2323#endif 2324#endif 2325 2326 worked = 1; /* got some work */ 2327 } 2328 2329 return(worked); 2330} 2331 2332static int 2333amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave) 2334{ 2335 int worked; 2336 u_int8_t istat; 2337 2338 debug_called(3); 2339 2340 worked = 0; 2341 2342 /* check for valid interrupt status */ 2343 istat = AMR_SGET_ISTAT(sc); 2344 if ((istat & AMR_SINTR_VALID) != 0) { 2345 AMR_SPUT_ISTAT(sc, istat); /* ack interrupt status */ 2346 2347 /* save mailbox, which contains a list of completed commands */ 2348 bcopy((void *)(uintptr_t)(volatile void *)sc->amr_mailbox, mbsave, sizeof(*mbsave)); 2349 2350 AMR_SACK_INTERRUPT(sc); /* acknowledge we have the mailbox */ 2351 worked = 1; 2352 } 2353 2354 return(worked); 2355} 2356 2357/******************************************************************************** 2358 * Notify the controller of the mailbox location. 2359 */ 2360static void 2361amr_std_attach_mailbox(struct amr_softc *sc) 2362{ 2363 2364 /* program the mailbox physical address */ 2365 AMR_SBYTE_SET(sc, AMR_SMBOX_0, sc->amr_mailboxphys & 0xff); 2366 AMR_SBYTE_SET(sc, AMR_SMBOX_1, (sc->amr_mailboxphys >> 8) & 0xff); 2367 AMR_SBYTE_SET(sc, AMR_SMBOX_2, (sc->amr_mailboxphys >> 16) & 0xff); 2368 AMR_SBYTE_SET(sc, AMR_SMBOX_3, (sc->amr_mailboxphys >> 24) & 0xff); 2369 AMR_SBYTE_SET(sc, AMR_SMBOX_ENABLE, AMR_SMBOX_ADDR); 2370 2371 /* clear any outstanding interrupt and enable interrupts proper */ 2372 AMR_SACK_INTERRUPT(sc); 2373 AMR_SENABLE_INTR(sc); 2374} 2375 2376#ifdef AMR_BOARD_INIT 2377/******************************************************************************** 2378 * Initialise the controller 2379 */ 2380static int 2381amr_quartz_init(struct amr_softc *sc) 2382{ 2383 int status, ostatus; 2384 2385 device_printf(sc->amr_dev, "initial init status %x\n", AMR_QGET_INITSTATUS(sc)); 2386 2387 AMR_QRESET(sc); 2388 2389 ostatus = 0xff; 2390 while ((status = AMR_QGET_INITSTATUS(sc)) != AMR_QINIT_DONE) { 2391 if (status != ostatus) { 2392 device_printf(sc->amr_dev, "(%x) %s\n", status, amr_describe_code(amr_table_qinit, status)); 2393 ostatus = status; 2394 } 2395 switch (status) { 2396 case AMR_QINIT_NOMEM: 2397 return(ENOMEM); 2398 2399 case AMR_QINIT_SCAN: 2400 /* XXX we could print channel/target here */ 2401 break; 2402 } 2403 } 2404 return(0); 2405} 2406 2407static int 2408amr_std_init(struct amr_softc *sc) 2409{ 2410 int status, ostatus; 2411 2412 device_printf(sc->amr_dev, "initial init status %x\n", AMR_SGET_INITSTATUS(sc)); 2413 2414 AMR_SRESET(sc); 2415 2416 ostatus = 0xff; 2417 while ((status = AMR_SGET_INITSTATUS(sc)) != AMR_SINIT_DONE) { 2418 if (status != ostatus) { 2419 device_printf(sc->amr_dev, "(%x) %s\n", status, amr_describe_code(amr_table_sinit, status)); 2420 ostatus = status; 2421 } 2422 switch (status) { 2423 case AMR_SINIT_NOMEM: 2424 return(ENOMEM); 2425 2426 case AMR_SINIT_INPROG: 2427 /* XXX we could print channel/target here? */ 2428 break; 2429 } 2430 } 2431 return(0); 2432} 2433#endif 2434 2435/******************************************************************************** 2436 ******************************************************************************** 2437 Debugging 2438 ******************************************************************************** 2439 ********************************************************************************/ 2440 2441/******************************************************************************** 2442 * Identify the controller and print some information about it. 2443 */ 2444static void 2445amr_describe_controller(struct amr_softc *sc) 2446{ 2447 struct amr_prodinfo *ap; 2448 struct amr_enquiry *ae; 2449 char *prod; 2450 int status; 2451 2452 /* 2453 * Try to get 40LD product info, which tells us what the card is labelled as. 2454 */ 2455 if ((ap = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODUCT_INFO, 0, &status)) != NULL) { 2456 device_printf(sc->amr_dev, "<LSILogic %.80s> Firmware %.16s, BIOS %.16s, %dMB RAM\n", 2457 ap->ap_product, ap->ap_firmware, ap->ap_bios, 2458 ap->ap_memsize); 2459 2460 free(ap, M_DEVBUF); 2461 return; 2462 } 2463 2464 /* 2465 * Try 8LD extended ENQUIRY to get controller signature, and use lookup table. 2466 */ 2467 if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_EXT_ENQUIRY2, 0, 0, &status)) != NULL) { 2468 prod = amr_describe_code(amr_table_adaptertype, ae->ae_signature); 2469 2470 } else if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_ENQUIRY, 0, 0, &status)) != NULL) { 2471 2472 /* 2473 * Try to work it out based on the PCI signatures. 2474 */ 2475 switch (pci_get_device(sc->amr_dev)) { 2476 case 0x9010: 2477 prod = "Series 428"; 2478 break; 2479 case 0x9060: 2480 prod = "Series 434"; 2481 break; 2482 default: 2483 prod = "unknown controller"; 2484 break; 2485 } 2486 } else { 2487 device_printf(sc->amr_dev, "<unsupported controller>\n"); 2488 return; 2489 } 2490 2491 /* 2492 * HP NetRaid controllers have a special encoding of the firmware and 2493 * BIOS versions. The AMI version seems to have it as strings whereas 2494 * the HP version does it with a leading uppercase character and two 2495 * binary numbers. 2496 */ 2497 2498 if(ae->ae_adapter.aa_firmware[2] >= 'A' && 2499 ae->ae_adapter.aa_firmware[2] <= 'Z' && 2500 ae->ae_adapter.aa_firmware[1] < ' ' && 2501 ae->ae_adapter.aa_firmware[0] < ' ' && 2502 ae->ae_adapter.aa_bios[2] >= 'A' && 2503 ae->ae_adapter.aa_bios[2] <= 'Z' && 2504 ae->ae_adapter.aa_bios[1] < ' ' && 2505 ae->ae_adapter.aa_bios[0] < ' ') { 2506 2507 /* this looks like we have an HP NetRaid version of the MegaRaid */ 2508 2509 if(ae->ae_signature == AMR_SIG_438) { 2510 /* the AMI 438 is a NetRaid 3si in HP-land */ 2511 prod = "HP NetRaid 3si"; 2512 } 2513 2514 device_printf(sc->amr_dev, "<%s> Firmware %c.%02d.%02d, BIOS %c.%02d.%02d, %dMB RAM\n", 2515 prod, ae->ae_adapter.aa_firmware[2], 2516 ae->ae_adapter.aa_firmware[1], 2517 ae->ae_adapter.aa_firmware[0], 2518 ae->ae_adapter.aa_bios[2], 2519 ae->ae_adapter.aa_bios[1], 2520 ae->ae_adapter.aa_bios[0], 2521 ae->ae_adapter.aa_memorysize); 2522 } else { 2523 device_printf(sc->amr_dev, "<%s> Firmware %.4s, BIOS %.4s, %dMB RAM\n", 2524 prod, ae->ae_adapter.aa_firmware, ae->ae_adapter.aa_bios, 2525 ae->ae_adapter.aa_memorysize); 2526 } 2527 free(ae, M_DEVBUF); 2528} 2529 2530int 2531amr_dump_blocks(struct amr_softc *sc, int unit, u_int32_t lba, void *data, int blks) 2532{ 2533 struct amr_command *ac; 2534 int error = EIO; 2535 2536 debug_called(1); 2537 2538 sc->amr_state |= AMR_STATE_INTEN; 2539 2540 /* get ourselves a command buffer */ 2541 if ((ac = amr_alloccmd(sc)) == NULL) 2542 goto out; 2543 /* set command flags */ 2544 ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT; 2545 2546 /* point the command at our data */ 2547 ac->ac_data = data; 2548 ac->ac_length = blks * AMR_BLKSIZE; 2549 2550 /* build the command proper */ 2551 ac->ac_mailbox.mb_command = AMR_CMD_LWRITE; 2552 ac->ac_mailbox.mb_blkcount = blks; 2553 ac->ac_mailbox.mb_lba = lba; 2554 ac->ac_mailbox.mb_drive = unit; 2555 2556 /* can't assume that interrupts are going to work here, so play it safe */ 2557 if (sc->amr_poll_command(ac)) 2558 goto out; 2559 error = ac->ac_status; 2560 2561 out: 2562 if (ac != NULL) 2563 amr_releasecmd(ac); 2564 2565 sc->amr_state &= ~AMR_STATE_INTEN; 2566 return (error); 2567} 2568 2569 2570 2571#ifdef AMR_DEBUG 2572/******************************************************************************** 2573 * Print the command (ac) in human-readable format 2574 */ 2575#if 0 2576static void 2577amr_printcommand(struct amr_command *ac) 2578{ 2579 struct amr_softc *sc = ac->ac_sc; 2580 struct amr_sgentry *sg; 2581 int i; 2582 2583 device_printf(sc->amr_dev, "cmd %x ident %d drive %d\n", 2584 ac->ac_mailbox.mb_command, ac->ac_mailbox.mb_ident, ac->ac_mailbox.mb_drive); 2585 device_printf(sc->amr_dev, "blkcount %d lba %d\n", 2586 ac->ac_mailbox.mb_blkcount, ac->ac_mailbox.mb_lba); 2587 device_printf(sc->amr_dev, "virtaddr %p length %lu\n", ac->ac_data, (unsigned long)ac->ac_length); 2588 device_printf(sc->amr_dev, "sg physaddr %08x nsg %d\n", 2589 ac->ac_mailbox.mb_physaddr, ac->ac_mailbox.mb_nsgelem); 2590 device_printf(sc->amr_dev, "ccb %p bio %p\n", ac->ac_ccb_data, ac->ac_bio); 2591 2592 /* get base address of s/g table */ 2593 sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG); 2594 for (i = 0; i < ac->ac_mailbox.mb_nsgelem; i++, sg++) 2595 device_printf(sc->amr_dev, " %x/%d\n", sg->sg_addr, sg->sg_count); 2596} 2597#endif 2598#endif 2599