amr.c revision 57297
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/amr/amr.c 57297 2000-02-17 23:33:57Z msmith $ 27 */ 28 29/* 30 * Driver for the AMI MegaRaid family of 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 44#include <machine/resource.h> 45#include <machine/bus.h> 46#include <machine/clock.h> 47#include <sys/rman.h> 48 49#include <dev/amr/amrio.h> 50#include <dev/amr/amrreg.h> 51#include <dev/amr/amrvar.h> 52 53#if 0 54#define debug(fmt, args...) printf("%s: " fmt "\n", __FUNCTION__ , ##args) 55#else 56#define debug(fmt, args...) 57#endif 58 59#define AMR_CDEV_MAJOR 132 60 61static struct cdevsw amr_cdevsw = { 62 /* open */ amr_open, 63 /* close */ amr_close, 64 /* read */ noread, 65 /* write */ nowrite, 66 /* ioctl */ amr_ioctl, 67 /* poll */ nopoll, 68 /* mmap */ nommap, 69 /* strategy */ nostrategy, 70 /* name */ "amr", 71 /* maj */ AMR_CDEV_MAJOR, 72 /* dump */ nodump, 73 /* psize */ nopsize, 74 /* flags */ 0, 75 /* bmaj */ 254 /* XXX magic no-bdev */ 76}; 77 78static int cdev_registered = 0; 79devclass_t amr_devclass; 80 81/* 82 * Command wrappers 83 */ 84static int amr_query_controller(struct amr_softc *sc); 85static void *amr_enquiry(struct amr_softc *sc, size_t bufsize, 86 u_int8_t cmd, u_int8_t cmdsub, u_int8_t cmdqual); 87static int amr_flush(struct amr_softc *sc); 88static void amr_startio(struct amr_softc *sc); 89static void amr_completeio(struct amr_command *ac); 90 91/* 92 * Command processing. 93 */ 94static int amr_wait_command(struct amr_command *ac); 95static int amr_poll_command(struct amr_command *ac); 96static int amr_getslot(struct amr_command *ac); 97static void amr_mapcmd(struct amr_command *ac); 98static void amr_unmapcmd(struct amr_command *ac); 99static int amr_start(struct amr_command *ac); 100static int amr_done(struct amr_softc *sc); 101static void amr_complete(struct amr_softc *sc); 102 103/* 104 * Command buffer allocation. 105 */ 106static struct amr_command *amr_alloccmd(struct amr_softc *sc); 107static void amr_releasecmd(struct amr_command *ac); 108static void amr_freecmd(struct amr_command *ac); 109 110/* 111 * Interface-specific shims 112 */ 113static void amr_quartz_submit_command(struct amr_softc *sc); 114static int amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave); 115static void amr_quartz_attach_mailbox(struct amr_softc *sc); 116 117static void amr_std_submit_command(struct amr_softc *sc); 118static int amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave); 119static void amr_std_attach_mailbox(struct amr_softc *sc); 120 121/* 122 * Debugging 123 */ 124static void amr_printcommand(struct amr_command *ac); 125 126/******************************************************************************** 127 ******************************************************************************** 128 Public Interfaces 129 ******************************************************************************** 130 ********************************************************************************/ 131 132/******************************************************************************** 133 * Free all of the resources associated with (sc) 134 * 135 * Should not be called if the controller is active. 136 */ 137void 138amr_free(struct amr_softc *sc) 139{ 140 struct amr_command *ac; 141 u_int8_t *p; 142 143 debug("called"); 144 145 146 /* throw away any command buffers */ 147 while ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL) { 148 TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link); 149 amr_freecmd(ac); 150 } 151 152 /* destroy data-transfer DMA tag */ 153 if (sc->amr_buffer_dmat) 154 bus_dma_tag_destroy(sc->amr_buffer_dmat); 155 156 /* free and destroy DMA memory and tag for s/g lists */ 157 if (sc->amr_sgtable) 158 bus_dmamem_free(sc->amr_sg_dmat, sc->amr_sgtable, sc->amr_sg_dmamap); 159 if (sc->amr_sg_dmat) 160 bus_dma_tag_destroy(sc->amr_sg_dmat); 161 162 /* free and destroy DMA memory and tag for mailbox */ 163 if (sc->amr_mailbox) { 164 p = (u_int8_t *)sc->amr_mailbox; 165 bus_dmamem_free(sc->amr_sg_dmat, p - 16, sc->amr_sg_dmamap); 166 } 167 if (sc->amr_sg_dmat) 168 bus_dma_tag_destroy(sc->amr_sg_dmat); 169 170 /* disconnect the interrupt handler */ 171 if (sc->amr_intr) 172 bus_teardown_intr(sc->amr_dev, sc->amr_irq, sc->amr_intr); 173 if (sc->amr_irq != NULL) 174 bus_release_resource(sc->amr_dev, SYS_RES_IRQ, 0, sc->amr_irq); 175 176 /* destroy the parent DMA tag */ 177 if (sc->amr_parent_dmat) 178 bus_dma_tag_destroy(sc->amr_parent_dmat); 179 180 /* release the register window mapping */ 181 if (sc->amr_reg != NULL) 182 bus_release_resource(sc->amr_dev, 183 (sc->amr_type == AMR_TYPE_QUARTZ) ? SYS_RES_MEMORY : SYS_RES_IOPORT, 184 AMR_CFG_BASE, sc->amr_reg); 185} 186 187/******************************************************************************** 188 * Allocate and map the scatter/gather table in bus space. 189 */ 190static void 191amr_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) 192{ 193 struct amr_softc *sc = (struct amr_softc *)arg; 194 195 debug("called"); 196 197 /* save base of s/g table's address in bus space */ 198 sc->amr_sgbusaddr = segs->ds_addr; 199} 200 201static int 202amr_sglist_map(struct amr_softc *sc) 203{ 204 size_t segsize; 205 int error; 206 207 debug("called"); 208 209 /* destroy any existing mappings */ 210 if (sc->amr_sgtable) 211 bus_dmamem_free(sc->amr_sg_dmat, sc->amr_sgtable, sc->amr_sg_dmamap); 212 if (sc->amr_sg_dmat) 213 bus_dma_tag_destroy(sc->amr_sg_dmat); 214 215 /* 216 * Create a single tag describing a region large enough to hold all of 217 * the s/g lists we will need. 218 */ 219 segsize = sizeof(struct amr_sgentry) * AMR_NSEG * sc->amr_maxio; 220 error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ 221 1, 0, /* alignment, boundary */ 222 BUS_SPACE_MAXADDR, /* lowaddr */ 223 BUS_SPACE_MAXADDR, /* highaddr */ 224 NULL, NULL, /* filter, filterarg */ 225 segsize, 1, /* maxsize, nsegments */ 226 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 227 0, /* flags */ 228 &sc->amr_sg_dmat); 229 if (error != 0) { 230 device_printf(sc->amr_dev, "can't allocate scatter/gather DMA tag\n"); 231 return(ENOMEM); 232 } 233 234 /* 235 * Allocate enough s/g maps for all commands and permanently map them into 236 * controller-visible space. 237 * 238 * XXX this assumes we can get enough space for all the s/g maps in one 239 * contiguous slab. We may need to switch to a more complex arrangement where 240 * we allocate in smaller chunks and keep a lookup table from slot to bus address. 241 */ 242 error = bus_dmamem_alloc(sc->amr_sg_dmat, (void **)&sc->amr_sgtable, BUS_DMA_NOWAIT, &sc->amr_sg_dmamap); 243 if (error) { 244 device_printf(sc->amr_dev, "can't allocate s/g table\n"); 245 return(ENOMEM); 246 } 247 bus_dmamap_load(sc->amr_sg_dmat, sc->amr_sg_dmamap, sc->amr_sgtable, segsize, amr_dma_map_sg, sc, 0); 248 return(0); 249} 250 251/******************************************************************************** 252 * Allocate and set up mailbox areas for the controller (sc) 253 * 254 * The basic mailbox structure should be 16-byte aligned. This means that the 255 * mailbox64 structure has 4 bytes hanging off the bottom. 256 */ 257static void 258amr_map_mailbox(void *arg, bus_dma_segment_t *segs, int nseg, int error) 259{ 260 struct amr_softc *sc = (struct amr_softc *)arg; 261 262 debug("called"); 263 264 /* save phsyical base of the basic mailbox structure */ 265 sc->amr_mailboxphys = segs->ds_addr + 16; 266} 267 268static int 269amr_setup_mbox(struct amr_softc *sc) 270{ 271 int error; 272 u_int8_t *p; 273 274 debug("called"); 275 276 /* 277 * Create a single tag describing a region large enough to hold the entire 278 * mailbox. 279 */ 280 error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ 281 16, 0, /* alignment, boundary */ 282 BUS_SPACE_MAXADDR, /* lowaddr */ 283 BUS_SPACE_MAXADDR, /* highaddr */ 284 NULL, NULL, /* filter, filterarg */ 285 sizeof(struct amr_mailbox) + 16, 1, /* maxsize, nsegments */ 286 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 287 0, /* flags */ 288 &sc->amr_mailbox_dmat); 289 if (error != 0) { 290 device_printf(sc->amr_dev, "can't allocate mailbox tag\n"); 291 return(ENOMEM); 292 } 293 294 /* 295 * Allocate the mailbox structure and permanently map it into 296 * controller-visible space. 297 */ 298 error = bus_dmamem_alloc(sc->amr_mailbox_dmat, (void **)&p, BUS_DMA_NOWAIT, 299 &sc->amr_mailbox_dmamap); 300 if (error) { 301 device_printf(sc->amr_dev, "can't allocate mailbox memory\n"); 302 return(ENOMEM); 303 } 304 bus_dmamap_load(sc->amr_mailbox_dmat, sc->amr_mailbox_dmamap, p, 305 sizeof(struct amr_mailbox64), amr_map_mailbox, sc, 0); 306 /* 307 * Conventional mailbox is inside the mailbox64 region. 308 */ 309 bzero(p, sizeof(struct amr_mailbox64)); 310 sc->amr_mailbox64 = (struct amr_mailbox64 *)(p + 12); 311 sc->amr_mailbox = (struct amr_mailbox *)(p + 16); 312 313 if (sc->amr_type == AMR_TYPE_STD) { 314 /* XXX we have to tell the controller where we put it */ 315 } 316 return(0); 317} 318 319 320/******************************************************************************** 321 * Initialise the controller and softc. 322 */ 323int 324amr_attach(struct amr_softc *sc) 325{ 326 int rid, error; 327 328 /* 329 * Initialise per-controller queues. 330 */ 331 TAILQ_INIT(&sc->amr_work); 332 TAILQ_INIT(&sc->amr_freecmds); 333 bufq_init(&sc->amr_bufq); 334 335 /* 336 * Configure for this controller type. 337 */ 338 if (sc->amr_type == AMR_TYPE_QUARTZ) { 339 sc->amr_submit_command = amr_quartz_submit_command; 340 sc->amr_get_work = amr_quartz_get_work; 341 sc->amr_attach_mailbox = amr_quartz_attach_mailbox; 342 } else { 343 sc->amr_submit_command = amr_std_submit_command; 344 sc->amr_get_work = amr_std_get_work; 345 sc->amr_attach_mailbox = amr_std_attach_mailbox; 346 } 347 348 /* 349 * Allocate and connect our interrupt. 350 */ 351 rid = 0; 352 sc->amr_irq = bus_alloc_resource(sc->amr_dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 353 if (sc->amr_irq == NULL) { 354 device_printf(sc->amr_dev, "couldn't allocate interrupt\n"); 355 amr_free(sc); 356 return(ENXIO); 357 } 358 error = bus_setup_intr(sc->amr_dev, sc->amr_irq, INTR_TYPE_BIO, amr_intr, sc, &sc->amr_intr); 359 if (error) { 360 device_printf(sc->amr_dev, "couldn't set up interrupt\n"); 361 amr_free(sc); 362 return(ENXIO); 363 } 364 365 /* 366 * Create DMA tag for mapping buffers into controller-addressable space. 367 */ 368 error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ 369 1, 0, /* alignment, boundary */ 370 BUS_SPACE_MAXADDR, /* lowaddr */ 371 BUS_SPACE_MAXADDR, /* highaddr */ 372 NULL, NULL, /* filter, filterarg */ 373 MAXBSIZE, AMR_NSEG, /* maxsize, nsegments */ 374 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 375 0, /* flags */ 376 &sc->amr_buffer_dmat); 377 if (error != 0) { 378 device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n"); 379 return(ENOMEM); 380 } 381 382 /* 383 * Allocate and set up mailbox in a bus-visible fashion, attach to controller. 384 */ 385 if ((error = amr_setup_mbox(sc)) != 0) 386 return(error); 387 sc->amr_attach_mailbox(sc); 388 389 /* 390 * Build a temporary set of scatter/gather buffers. 391 */ 392 sc->amr_maxio = 2; 393 if (amr_sglist_map(sc)) 394 return(ENXIO); 395 396 /* 397 * Quiz controller for features and limits. 398 */ 399 if (amr_query_controller(sc)) 400 return(ENXIO); 401 402 /* 403 * Rebuild the scatter/gather buffers now we know how many we need. 404 */ 405 if (amr_sglist_map(sc)) 406 return(ENXIO); 407 408 return(0); 409} 410 411/******************************************************************************** 412 * Locate disk resources and attach children to them. 413 */ 414void 415amr_startup(struct amr_softc *sc) 416{ 417 struct amr_logdrive *dr; 418 int i, error; 419 420 debug("called"); 421 422 /* get up-to-date drive information */ 423 if (amr_query_controller(sc)) { 424 device_printf(sc->amr_dev, "couldn't scan controller for drives\n"); 425 return; 426 } 427 428 /* iterate over available drives */ 429 for (i = 0, dr = &sc->amr_drive[0]; (i < AMR_MAXLD) && (dr->al_size != 0xffffffff); i++, dr++) { 430 /* are we already attached to this drive? */ 431 if (dr->al_disk == 0) { 432 /* generate geometry information */ 433 if (dr->al_size > 0x200000) { /* extended translation? */ 434 dr->al_heads = 255; 435 dr->al_sectors = 63; 436 } else { 437 dr->al_heads = 64; 438 dr->al_sectors = 32; 439 } 440 dr->al_cylinders = dr->al_size / (dr->al_heads * dr->al_sectors); 441 442 dr->al_disk = device_add_child(sc->amr_dev, NULL, -1); 443 if (dr->al_disk == 0) 444 device_printf(sc->amr_dev, "device_add_child failed\n"); 445 device_set_ivars(dr->al_disk, dr); 446 } 447 } 448 449 if ((error = bus_generic_attach(sc->amr_dev)) != 0) 450 device_printf(sc->amr_dev, "bus_generic_attach returned %d\n", error); 451 452 /* mark controller back up */ 453 sc->amr_state &= ~AMR_STATE_SHUTDOWN; 454 455 /* interrupts will be enabled before we do anything more */ 456 sc->amr_state |= AMR_STATE_INTEN; 457} 458 459/******************************************************************************** 460 * Disconnect from the controller completely, in preparation for unload. 461 */ 462int 463amr_detach(device_t dev) 464{ 465 struct amr_softc *sc = device_get_softc(dev); 466 int error; 467 468 debug("called"); 469 470 if (sc->amr_state & AMR_STATE_OPEN) 471 return(EBUSY); 472 473 if ((error = amr_shutdown(dev))) 474 return(error); 475 476 amr_free(sc); 477 478 /* 479 * Deregister the control device on last detach. 480 */ 481 if (--cdev_registered == 0) 482 cdevsw_remove(&amr_cdevsw); 483 484 return(0); 485} 486 487/******************************************************************************** 488 * Bring the controller down to a dormant state and detach all child devices. 489 * 490 * This function is called before detach, system shutdown, or before performing 491 * an operation which may add or delete system disks. (Call amr_startup to 492 * resume normal operation.) 493 * 494 * Note that we can assume that the bufq on the controller is empty, as we won't 495 * allow shutdown if any device is open. 496 */ 497int 498amr_shutdown(device_t dev) 499{ 500 struct amr_softc *sc = device_get_softc(dev); 501 struct amrd_softc *ad; 502 int i, s, error; 503 504 debug("called"); 505 506 s = splbio(); 507 error = 0; 508 509 /* assume we're going to shut down */ 510 sc->amr_state |= AMR_STATE_SHUTDOWN; 511 for (i = 0; i < AMR_MAXLD; i++) { 512 if (sc->amr_drive[i].al_disk != 0) { 513 ad = device_get_softc(sc->amr_drive[i].al_disk); 514 if (ad->amrd_flags & AMRD_OPEN) { /* drive is mounted, abort shutdown */ 515 sc->amr_state &= ~AMR_STATE_SHUTDOWN; 516 device_printf(sc->amr_drive[i].al_disk, "still open, can't shutdown\n"); 517 error = EBUSY; 518 goto out; 519 } 520 } 521 } 522 523 /* flush controller */ 524 device_printf(sc->amr_dev, "flushing cache..."); 525 if (amr_flush(sc)) { 526 printf("failed\n"); 527 } else { 528 printf("done\n"); 529 } 530 531 /* delete all our child devices */ 532 for (i = 0; i < AMR_MAXLD; i++) { 533 if (sc->amr_drive[i].al_disk != 0) { 534 if ((error = device_delete_child(sc->amr_dev, sc->amr_drive[i].al_disk)) != 0) 535 goto out; 536 sc->amr_drive[i].al_disk = 0; 537 } 538 } 539 bus_generic_detach(sc->amr_dev); 540 541 out: 542 splx(s); 543 return(error); 544} 545 546/******************************************************************************** 547 * Bring the controller to a quiescent state, ready for system suspend. 548 */ 549int 550amr_suspend(device_t dev) 551{ 552 struct amr_softc *sc = device_get_softc(dev); 553 554 debug("called"); 555 556 sc->amr_state |= AMR_STATE_SUSPEND; 557 558 /* flush controller */ 559 device_printf(sc->amr_dev, "flushing cache..."); 560 printf("%s\n", amr_flush(sc) ? "failed" : "done"); 561 562 return(0); 563} 564 565/******************************************************************************** 566 * Bring the controller back to a state ready for operation. 567 */ 568int 569amr_resume(device_t dev) 570{ 571 struct amr_softc *sc = device_get_softc(dev); 572 573 debug("called"); 574 575 sc->amr_state &= ~AMR_STATE_SUSPEND; 576 577 return(0); 578} 579 580/******************************************************************************* 581 * Take an interrupt, or be poked by other code to look for interrupt-worthy 582 * status. 583 */ 584void 585amr_intr(void *arg) 586{ 587 struct amr_softc *sc = (struct amr_softc *)arg; 588 int worked; 589 590 debug("called on %p", sc); 591 592 /* spin collecting finished commands, process them if we find anything */ 593 worked = 0; 594 while (amr_done(sc)) 595 worked = 1; 596 if (worked) 597 amr_complete(sc); 598}; 599 600/******************************************************************************* 601 * Receive a buf structure from a child device and queue it on a particular 602 * disk resource, then poke the disk resource to start as much work as it can. 603 */ 604int 605amr_submit_buf(struct amr_softc *sc, struct buf *bp) 606{ 607 int s; 608 609 debug("called"); 610 611 s = splbio(); 612 bufq_insert_tail(&sc->amr_bufq, bp); 613 splx(s); 614 sc->amr_waitbufs++; 615 amr_startio(sc); 616 return(0); 617} 618 619/******************************************************************************** 620 * Accept an open operation on the control device. 621 */ 622int 623amr_open(dev_t dev, int flags, int fmt, struct proc *p) 624{ 625 int unit = minor(dev); 626 struct amr_softc *sc = devclass_get_softc(amr_devclass, unit); 627 628 sc->amr_state |= AMR_STATE_OPEN; 629 return(0); 630} 631 632/******************************************************************************** 633 * Accept the last close on the control device. 634 */ 635int 636amr_close(dev_t dev, int flags, int fmt, struct proc *p) 637{ 638 int unit = minor(dev); 639 struct amr_softc *sc = devclass_get_softc(amr_devclass, unit); 640 641 sc->amr_state &= ~AMR_STATE_OPEN; 642 return (0); 643} 644 645/******************************************************************************** 646 * Handle controller-specific control operations. 647 */ 648int 649amr_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) 650{ 651 652 switch(cmd) { 653 default: 654 return(ENOTTY); 655 } 656} 657 658/******************************************************************************** 659 * Handle operations requested by a drive connected to this controller. 660 */ 661int 662amr_submit_ioctl(struct amr_softc *sc, struct amr_logdrive *drive, u_long cmd, 663 caddr_t addr, int32_t flag, struct proc *p) 664{ 665 return(ENOTTY); 666} 667 668/******************************************************************************** 669 ******************************************************************************** 670 Command Wrappers 671 ******************************************************************************** 672 ********************************************************************************/ 673 674/******************************************************************************** 675 * Interrogate the controller for the operational parameters we require. 676 */ 677static int 678amr_query_controller(struct amr_softc *sc) 679{ 680 void *buf; 681 int i; 682 683 /* try to issue an ENQUIRY3 command */ 684 if ((buf = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_ENQ3, 685 AMR_CONFIG_ENQ3_SOLICITED_FULL)) == NULL) { 686 687 struct amr_enquiry *ae; 688 689 /* failed, try the old ENQUIRY command */ 690 if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_ENQUIRY, 0, 0)) == NULL) { 691 device_printf(sc->amr_dev, "could not obtain configuration data from controller\n"); 692 return(1); 693 } 694 /* first-time enquiry? */ 695 if (sc->amr_maxdrives == 0) { 696 device_printf(sc->amr_dev, "firmware %.4s bios %.4s %dMB memory\n", 697 ae->ae_adapter.aa_firmware, ae->ae_adapter.aa_bios, 698 ae->ae_adapter.aa_memorysize); 699 } 700 sc->amr_maxdrives = 8; 701 sc->amr_maxio = ae->ae_adapter.aa_maxio; 702 for (i = 0; i < ae->ae_ldrv.al_numdrives; i++) { 703 sc->amr_drive[i].al_size = ae->ae_ldrv.al_size[i]; 704 sc->amr_drive[i].al_state = ae->ae_ldrv.al_state[i]; 705 sc->amr_drive[i].al_properties = ae->ae_ldrv.al_properties[i]; 706 debug(" drive %d: %d state %x properties %x\n", i, sc->amr_drive[i].al_size, 707 sc->amr_drive[i].al_state, sc->amr_drive[i].al_properties); 708 } 709 for (; i < AMR_MAXLD; i++) 710 sc->amr_drive[i].al_size = 0xffffffff; 711 free(ae, M_DEVBUF); 712 } else { 713 free(buf, M_DEVBUF); 714 sc->amr_maxdrives = 40; 715 716 /* get static product info */ 717 if ((buf = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODINFO, 0)) == NULL) { 718 device_printf(sc->amr_dev, "controller supports 40ld but CONFIG_PRODINFO failed\n"); 719 return(1); 720 } 721 free(buf, M_DEVBUF); 722 device_printf(sc->amr_dev, "40LD firmware unsupported; send controller to msmith@freebsd.org\n"); 723 return(1); 724 } 725 return(0); 726} 727 728/******************************************************************************** 729 * Run a generic enquiry-style command. 730 */ 731static void * 732amr_enquiry(struct amr_softc *sc, size_t bufsize, u_int8_t cmd, u_int8_t cmdsub, u_int8_t cmdqual) 733{ 734 struct amr_command *ac; 735 void *result; 736 u_int8_t *mbox; 737 int error; 738 739 debug("called"); 740 741 error = 1; 742 result = NULL; 743 744 /* get ourselves a command buffer */ 745 if ((ac = amr_alloccmd(sc)) == NULL) 746 goto out; 747 /* allocate the response structure */ 748 if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL) 749 goto out; 750 /* get a command slot */ 751 ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT; 752 if (amr_getslot(ac)) 753 goto out; 754 755 /* map the command so the controller can see it */ 756 ac->ac_data = result; 757 ac->ac_length = bufsize; 758 amr_mapcmd(ac); 759 760 /* build the command proper */ 761 mbox = (u_int8_t *)&ac->ac_mailbox; /* XXX want a real structure for this? */ 762 mbox[0] = cmd; 763 mbox[2] = cmdsub; 764 mbox[3] = cmdqual; 765 ac->ac_mailbox.mb_physaddr = ac->ac_dataphys; 766 767 /* run the command in polled/wait mode as suits the current mode */ 768 if ((sc->amr_state & AMR_STATE_INTEN) ? amr_wait_command(ac) : amr_poll_command(ac)) 769 goto out; 770 error = ac->ac_status; 771 772 out: 773 if (ac != NULL) 774 amr_releasecmd(ac); 775 if ((error != 0) && (result != NULL)) { 776 free(result, M_DEVBUF); 777 result = NULL; 778 } 779 return(result); 780} 781 782/******************************************************************************** 783 * Flush the controller's internal cache, return status. 784 */ 785static int 786amr_flush(struct amr_softc *sc) 787{ 788 struct amr_command *ac; 789 int error; 790 791 /* get ourselves a command buffer */ 792 error = 1; 793 if ((ac = amr_alloccmd(sc)) == NULL) 794 goto out; 795 /* get a command slot */ 796 ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT; 797 if (amr_getslot(ac)) 798 goto out; 799 800 /* build the command proper */ 801 ac->ac_mailbox.mb_command = AMR_CMD_FLUSH; 802 803 /* run the command in polled/wait mode as suits the current mode */ 804 if ((sc->amr_state & AMR_STATE_INTEN) ? amr_wait_command(ac) : amr_poll_command(ac)) 805 goto out; 806 error = ac->ac_status; 807 808 out: 809 if (ac != NULL) 810 amr_releasecmd(ac); 811 return(error); 812} 813 814/******************************************************************************** 815 * Pull as much work off the softc's work queue as possible and give it to the 816 * controller. Leave a couple of slots free for emergencies. 817 * 818 * We avoid running at splbio() whenever possible. 819 */ 820static void 821amr_startio(struct amr_softc *sc) 822{ 823 struct amr_command *ac; 824 struct amrd_softc *amrd; 825 struct buf *bp; 826 int blkcount; 827 int driveno; 828 int cmd; 829 int s; 830 831 /* spin until something prevents us from doing any work */ 832 s = splbio(); 833 for (;;) { 834 835 /* see if there's work to be done */ 836 if ((bp = bufq_first(&sc->amr_bufq)) == NULL) 837 break; 838 /* get a command */ 839 if ((ac = amr_alloccmd(sc)) == NULL) 840 break; 841 /* get a slot for the command */ 842 if (amr_getslot(ac) != 0) { 843 amr_releasecmd(ac); 844 break; 845 } 846 /* get the buf containing our work */ 847 bufq_remove(&sc->amr_bufq, bp); 848 sc->amr_waitbufs--; 849 splx(s); 850 851 /* connect the buf to the command */ 852 ac->ac_complete = amr_completeio; 853 ac->ac_private = bp; 854 ac->ac_data = bp->b_data; 855 ac->ac_length = bp->b_bcount; 856 if (bp->b_flags & B_READ) { 857 ac->ac_flags |= AMR_CMD_DATAIN; 858 cmd = AMR_CMD_LREAD; 859 } else { 860 ac->ac_flags |= AMR_CMD_DATAOUT; 861 cmd = AMR_CMD_LWRITE; 862 } 863 864 /* map the command so the controller can work with it */ 865 amr_mapcmd(ac); 866 867 /* build a suitable I/O command (assumes 512-byte rounded transfers) */ 868 amrd = (struct amrd_softc *)bp->b_driver1; 869 driveno = amrd->amrd_drive - &sc->amr_drive[0]; 870 blkcount = bp->b_bcount / AMR_BLKSIZE; 871 872 if ((bp->b_pblkno + blkcount) > sc->amr_drive[driveno].al_size) 873 device_printf(sc->amr_dev, "I/O beyond end of unit (%u,%d > %u)\n", 874 bp->b_pblkno, blkcount, sc->amr_drive[driveno].al_size); 875 876 /* 877 * Build the I/O command. 878 */ 879 ac->ac_mailbox.mb_command = cmd; 880 ac->ac_mailbox.mb_blkcount = blkcount; 881 ac->ac_mailbox.mb_lba = bp->b_pblkno; 882 ac->ac_mailbox.mb_physaddr = ac->ac_sgphys; 883 ac->ac_mailbox.mb_drive = driveno; 884 ac->ac_mailbox.mb_nsgelem = ac->ac_nsgent; 885 886 /* try to give command to controller */ 887 if (amr_start(ac) != 0) { 888 /* fail the command */ 889 ac->ac_status = AMR_STATUS_WEDGED; 890 amr_completeio(ac); 891 } 892 s = splbio(); 893 } 894 splx(s); 895} 896 897/******************************************************************************** 898 * Handle completion of an I/O command. 899 */ 900static void 901amr_completeio(struct amr_command *ac) 902{ 903 struct amr_softc *sc = ac->ac_sc; 904 struct buf *bp = (struct buf *)ac->ac_private; 905 906 if (ac->ac_status != AMR_STATUS_SUCCESS) { /* could be more verbose here? */ 907 bp->b_error = EIO; 908 bp->b_flags |= B_ERROR; 909 910 switch(ac->ac_status) { 911 /* XXX need more information on I/O error reasons */ 912 default: 913 device_printf(sc->amr_dev, "I/O error - %x\n", ac->ac_status); 914 amr_printcommand(ac); 915 break; 916 } 917 } 918 amr_releasecmd(ac); 919 amrd_intr(bp); 920} 921 922/******************************************************************************** 923 ******************************************************************************** 924 Command Processing 925 ******************************************************************************** 926 ********************************************************************************/ 927 928/******************************************************************************** 929 * Take a command, submit it to the controller and sleep until it completes 930 * or fails. Interrupts must be enabled, returns nonzero on error. 931 */ 932static int 933amr_wait_command(struct amr_command *ac) 934{ 935 struct amr_softc *sc = ac->ac_sc; 936 int error, count; 937 938 debug("called"); 939 940 ac->ac_complete = NULL; 941 ac->ac_private = ac; 942 if ((error = amr_start(ac)) != 0) 943 return(error); 944 945 count = 0; 946 /* XXX better timeout? */ 947 while ((ac->ac_status == AMR_STATUS_BUSY) && (count < 30)) { 948 tsleep(ac->ac_private, PRIBIO | PCATCH, "amrwcmd", hz); 949 } 950 951 if (ac->ac_status != 0) { 952 device_printf(sc->amr_dev, "I/O error 0x%x\n", ac->ac_status); 953 return(EIO); 954 } 955 return(0); 956} 957 958/******************************************************************************** 959 * Take a command, submit it to the controller and busy-wait for it to return. 960 * Returns nonzero on error. Can be safely called with interrupts enabled. 961 */ 962static int 963amr_poll_command(struct amr_command *ac) 964{ 965 struct amr_softc *sc = ac->ac_sc; 966 int error, count, s; 967 968 debug("called"); 969 970 ac->ac_complete = NULL; 971 ac->ac_private = NULL; 972 if ((error = amr_start(ac)) != 0) 973 return(error); 974 975 count = 0; 976 do { 977 /* 978 * Poll for completion, although the interrupt handler may beat us to it. 979 * Note that the timeout here is somewhat arbitrary. 980 */ 981 amr_done(sc); 982 } while ((ac->ac_status == AMR_STATUS_BUSY) && (count++ < 100000)); 983 s = splbio(); 984 if (ac->ac_status != AMR_STATUS_BUSY) { 985 TAILQ_REMOVE(&sc->amr_work, ac, ac_link); 986 sc->amr_workcount--; 987 error = 0; 988 } else { 989 /* take the command out of the busy list, mark slot as bogus */ 990 sc->amr_busycmd[ac->ac_slot] = (struct amr_command *)sc; 991 error = EIO; 992 device_printf(sc->amr_dev, "I/O error 0x%x\n", ac->ac_status); 993 } 994 splx(s); 995 return(error); 996} 997 998/******************************************************************************** 999 * Get a free command slot. 1000 */ 1001static int 1002amr_getslot(struct amr_command *ac) 1003{ 1004 struct amr_softc *sc = ac->ac_sc; 1005 int s, slot, limit; 1006 1007 debug("called"); 1008 1009 /* enforce slot usage limit */ 1010 limit = (ac->ac_flags & AMR_CMD_PRIORITY) ? sc->amr_maxio : sc->amr_maxio - 4; 1011 if (sc->amr_busycmdcount > limit) 1012 return(EBUSY); 1013 1014 /* 1015 * Allocate a slot 1016 */ 1017 s = splbio(); 1018 for (slot = 0; slot < sc->amr_maxio; slot++) { 1019 if (sc->amr_busycmd[slot] == NULL) 1020 break; 1021 } 1022 if (slot < sc->amr_maxio) { 1023 sc->amr_busycmdcount++; 1024 sc->amr_busycmd[slot] = ac; 1025 } 1026 splx(s); 1027 1028 /* out of slots? */ 1029 if (slot >= sc->amr_maxio) 1030 return(EBUSY); 1031 1032 ac->ac_slot = slot; 1033 return(0); 1034} 1035 1036/******************************************************************************** 1037 * Map/unmap (ac)'s data in the controller's addressable space. 1038 */ 1039static void 1040amr_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error) 1041{ 1042 struct amr_command *ac = (struct amr_command *)arg; 1043 struct amr_softc *sc = ac->ac_sc; 1044 struct amr_sgentry *sg; 1045 int i; 1046 1047 debug("called"); 1048 1049 /* get base address of s/g table */ 1050 sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG); 1051 1052 /* save s/g table information in command */ 1053 ac->ac_nsgent = nsegments; 1054 ac->ac_sgphys = sc->amr_sgbusaddr + (ac->ac_slot * AMR_NSEG * sizeof(struct amr_sgentry)); 1055 ac->ac_dataphys = segs[0].ds_addr; 1056 1057 /* populate s/g table */ 1058 for (i = 0; i < nsegments; i++, sg++) { 1059 sg->sg_addr = segs[i].ds_addr; 1060 sg->sg_count = segs[i].ds_len; 1061 } 1062} 1063 1064static void 1065amr_mapcmd(struct amr_command *ac) 1066{ 1067 struct amr_softc *sc = ac->ac_sc; 1068 1069 debug("called"); 1070 1071 /* if the command involves data at all */ 1072 if (ac->ac_data != NULL) { 1073 1074 /* map the data buffer into bus space and build the s/g list */ 1075 bus_dmamap_load(sc->amr_buffer_dmat, ac->ac_dmamap, ac->ac_data, ac->ac_length, 1076 amr_setup_dmamap, ac, 0); 1077 if (ac->ac_flags & AMR_CMD_DATAIN) 1078 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_PREREAD); 1079 if (ac->ac_flags & AMR_CMD_DATAOUT) 1080 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_PREWRITE); 1081 } 1082} 1083 1084static void 1085amr_unmapcmd(struct amr_command *ac) 1086{ 1087 struct amr_softc *sc = ac->ac_sc; 1088 1089 debug("called"); 1090 1091 /* if the command involved data at all */ 1092 if (ac->ac_data != NULL) { 1093 1094 if (ac->ac_flags & AMR_CMD_DATAIN) 1095 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_POSTREAD); 1096 if (ac->ac_flags & AMR_CMD_DATAOUT) 1097 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_POSTWRITE); 1098 1099 bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_dmamap); 1100 } 1101} 1102 1103/******************************************************************************** 1104 * Take a command and give it to the controller. Take care of any completed 1105 * commands we encouter while waiting. 1106 */ 1107static int 1108amr_start(struct amr_command *ac) 1109{ 1110 struct amr_softc *sc = ac->ac_sc; 1111 int worked, done, s, i; 1112 1113 debug("called"); 1114 1115 /* 1116 * Save the slot number so that we can locate this command when complete. 1117 * Note that ident = 0 seems to be special, so we don't use it. 1118 */ 1119 ac->ac_mailbox.mb_ident = ac->ac_slot + 1; 1120 1121 /* set the busy flag when we copy the mailbox in */ 1122 ac->ac_mailbox.mb_busy = 1; 1123 1124 /* set impossible status so that a woken sleeper can tell the command is busy */ 1125 ac->ac_status = AMR_STATUS_BUSY; 1126 1127 /* spin waiting for the mailbox */ 1128 debug("wait for mailbox"); 1129 for (i = 100000, done = 0, worked = 0; (i > 0) && !done; i--) { 1130 s = splbio(); 1131 1132 /* is the mailbox free? */ 1133 if (sc->amr_mailbox->mb_busy == 0) { 1134 debug("got mailbox"); 1135 sc->amr_mailbox64->mb64_segment = 0; 1136 bcopy(&ac->ac_mailbox, sc->amr_mailbox, AMR_MBOX_CMDSIZE); 1137 sc->amr_submit_command(sc); 1138 done = 1; 1139 sc->amr_workcount++; 1140 TAILQ_INSERT_TAIL(&sc->amr_work, ac, ac_link); 1141 1142 /* not free, try to clean up while we wait */ 1143 } else { 1144 debug("busy flag %x\n", sc->amr_mailbox->mb_busy); 1145 worked = amr_done(sc); 1146 } 1147 splx(s); 1148 } 1149 1150 /* do completion processing if we picked anything up */ 1151 if (worked) 1152 amr_complete(sc); 1153 1154 /* command is enqueued? */ 1155 if (done) { 1156 ac->ac_stamp = time_second; 1157 debug("posted command"); 1158 return(0); 1159 } 1160 1161 /* 1162 * The controller wouldn't take the command. Revoke the slot 1163 * that the command was given and return with a bad status. 1164 */ 1165 sc->amr_busycmd[ac->ac_slot] = NULL; 1166 device_printf(sc->amr_dev, "controller wedged (not taking commands)\n"); 1167 ac->ac_status = AMR_STATUS_WEDGED; 1168 return(EIO); 1169} 1170 1171/******************************************************************************** 1172 * Extract one or more completed commands from the controller (sc) 1173 * 1174 * Returns nonzero if any commands on the work queue were marked as completed. 1175 */ 1176static int 1177amr_done(struct amr_softc *sc) 1178{ 1179 struct amr_command *ac; 1180 struct amr_mailbox mbox; 1181 int i, idx, result; 1182 1183 debug("called"); 1184 1185 /* See if there's anything for us to do */ 1186 result = 0; 1187 if (sc->amr_get_work(sc, &mbox)) { 1188 /* iterate over completed commands */ 1189 for (i = 0; i < mbox.mb_nstatus; i++) { 1190 /* get pointer to busy command */ 1191 idx = mbox.mb_completed[i] - 1; 1192 ac = sc->amr_busycmd[idx]; 1193 1194 /* really a busy command? */ 1195 if (ac != NULL) { 1196 1197 /* pull the command from the busy index */ 1198 sc->amr_busycmd[idx] = NULL; 1199 sc->amr_busycmdcount--; 1200 1201 /* unmap data buffer */ 1202 amr_unmapcmd(ac); 1203 1204 /* aborted command? */ 1205 if (ac == (struct amr_command *)sc) { 1206 device_printf(sc->amr_dev, "aborted command completed (%d)\n", idx); 1207 ac = NULL; 1208 1209 /* completed normally, save status */ 1210 } else { 1211 ac->ac_status = mbox.mb_status; 1212 debug("completed command with status %x", mbox.mb_status); 1213 } 1214 result = 1; 1215 } 1216 } 1217 } 1218 return(result); 1219} 1220 1221/******************************************************************************** 1222 * Do completion processing on done commands on (sc) 1223 */ 1224static void 1225amr_complete(struct amr_softc *sc) 1226{ 1227 struct amr_command *ac, *nc; 1228 int s, count; 1229 1230 debug("called"); 1231 1232 count = 0; 1233 1234 s = splbio(); 1235 ac = TAILQ_FIRST(&sc->amr_work); 1236 while (ac != NULL) { 1237 nc = TAILQ_NEXT(ac, ac_link); 1238 1239 /* Skip if command is still active */ 1240 if (ac->ac_status != AMR_STATUS_BUSY) { 1241 1242 /* 1243 * Is there a completion handler? 1244 */ 1245 if (ac->ac_complete != NULL) { 1246 1247 /* remove and give to completion handler */ 1248 TAILQ_REMOVE(&sc->amr_work, ac, ac_link); 1249 sc->amr_workcount--; 1250 ac->ac_complete(ac); 1251 1252 /* 1253 * Is someone sleeping on this one? 1254 */ 1255 } else if (ac->ac_private != NULL) { 1256 1257 /* remove and wake up */ 1258 TAILQ_REMOVE(&sc->amr_work, ac, ac_link); 1259 sc->amr_workcount--; 1260 wakeup_one(ac->ac_private); 1261 1262 /* 1263 * Leave it for a polling caller. 1264 */ 1265 } else { 1266 } 1267 } 1268 ac = nc; 1269 } 1270 splx(s); 1271 1272 /* queue more work if we can */ 1273 amr_startio(sc); 1274} 1275 1276/******************************************************************************** 1277 ******************************************************************************** 1278 Command Buffer Management 1279 ******************************************************************************** 1280 ********************************************************************************/ 1281 1282/******************************************************************************** 1283 * Get a new command buffer. 1284 * 1285 * This may return NULL in low-memory cases. 1286 * 1287 * Note that using malloc() is expensive (the command buffer is << 1 page) but 1288 * necessary if we are to be a loadable module before the zone allocator is fixed. 1289 * 1290 * If possible, we recycle a command buffer that's been used before. 1291 * 1292 * XXX Note that command buffers are not cleaned out - it is the caller's 1293 * responsibility to ensure that all required fields are filled in before 1294 * using a buffer. 1295 */ 1296static struct amr_command * 1297amr_alloccmd(struct amr_softc *sc) 1298{ 1299 struct amr_command *ac; 1300 int error; 1301 int s; 1302 1303 debug("called"); 1304 1305 s = splbio(); 1306 if ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL) 1307 TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link); 1308 splx(s); 1309 1310 /* allocate a new command buffer? */ 1311 if (ac == NULL) { 1312 ac = (struct amr_command *)malloc(sizeof(*ac), M_DEVBUF, M_NOWAIT); 1313 if (ac != NULL) { 1314 bzero(ac, sizeof(*ac)); 1315 ac->ac_sc = sc; 1316 error = bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_dmamap); 1317 if (error) { 1318 free(ac, M_DEVBUF); 1319 return(NULL); 1320 } 1321 } 1322 } 1323 bzero(&ac->ac_mailbox, sizeof(struct amr_mailbox)); 1324 return(ac); 1325} 1326 1327/******************************************************************************** 1328 * Release a command buffer for recycling. 1329 * 1330 * XXX It might be a good idea to limit the number of commands we save for reuse 1331 * if it's shown that this list bloats out massively. 1332 */ 1333static void 1334amr_releasecmd(struct amr_command *ac) 1335{ 1336 int s; 1337 1338 debug("called"); 1339 1340 s = splbio(); 1341 TAILQ_INSERT_HEAD(&ac->ac_sc->amr_freecmds, ac, ac_link); 1342 splx(s); 1343} 1344 1345/******************************************************************************** 1346 * Permanently discard a command buffer. 1347 */ 1348static void 1349amr_freecmd(struct amr_command *ac) 1350{ 1351 struct amr_softc *sc = ac->ac_sc; 1352 1353 debug("called"); 1354 1355 bus_dmamap_destroy(sc->amr_buffer_dmat, ac->ac_dmamap); 1356 free(ac, M_DEVBUF); 1357} 1358 1359/******************************************************************************** 1360 ******************************************************************************** 1361 Interface-specific Shims 1362 ******************************************************************************** 1363 ********************************************************************************/ 1364 1365/******************************************************************************** 1366 * Tell the controller that the mailbox contains a valid command 1367 */ 1368static void 1369amr_quartz_submit_command(struct amr_softc *sc) 1370{ 1371 debug("called"); 1372 1373 sc->amr_mailbox->mb_poll = 0; 1374 sc->amr_mailbox->mb_ack = 0; 1375 /* XXX write barrier? */ 1376 while(AMR_QGET_IDB(sc) & AMR_QIDB_SUBMIT) 1377 ; /* XXX aiee! what if it dies? */ 1378 AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT); 1379} 1380 1381static void 1382amr_std_submit_command(struct amr_softc *sc) 1383{ 1384 debug("called"); 1385 1386 /* XXX write barrier? */ 1387 while (AMR_SGET_MBSTAT(sc) & AMR_SMBOX_BUSYFLAG) 1388 ; /* XXX aiee! what if it dies? */ 1389 AMR_SPOST_COMMAND(sc); 1390} 1391 1392/******************************************************************************** 1393 * Claim any work that the controller has completed; acknowledge completion, 1394 * save details of the completion in (mbsave) 1395 */ 1396static int 1397amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave) 1398{ 1399 int s, worked; 1400 u_int32_t outd; 1401 1402 debug("called"); 1403 1404 worked = 0; 1405 s = splbio(); 1406 1407 /* work waiting for us? */ 1408 if ((outd = AMR_QGET_ODB(sc)) == AMR_QODB_READY) { 1409 AMR_QPUT_ODB(sc, AMR_QODB_READY); 1410 1411 /* save mailbox, which contains a list of completed commands */ 1412 /* XXX read barrier? */ 1413 bcopy(sc->amr_mailbox, mbsave, sizeof(*mbsave)); 1414 1415 /* acknowledge that we have the commands */ 1416 AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_ACK); 1417 while(AMR_QGET_IDB(sc) & AMR_QIDB_ACK) 1418 ; /* XXX aiee! what if it dies? */ 1419 worked = 1; /* got some work */ 1420 } 1421 1422 splx(s); 1423 return(worked); 1424} 1425 1426static int 1427amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave) 1428{ 1429 int s, worked; 1430 u_int8_t istat; 1431 1432 debug("called"); 1433 1434 worked = 0; 1435 s = splbio(); 1436 1437 /* check for valid interrupt status */ 1438 istat = AMR_SGET_ISTAT(sc); 1439 if ((istat & AMR_SINTR_VALID) != 0) { 1440 AMR_SPUT_ISTAT(sc, istat); /* ack interrupt status */ 1441 1442 /* save mailbox, which contains a list of completed commands */ 1443 /* XXX read barrier? */ 1444 bcopy(sc->amr_mailbox, mbsave, sizeof(*mbsave)); 1445 1446 AMR_SACK_INTERRUPT(sc); /* acknowledge we have the mailbox */ 1447 worked = 1; 1448 } 1449 1450 splx(s); 1451 return(worked); 1452} 1453 1454/******************************************************************************** 1455 * Notify the controller of the mailbox location. 1456 */ 1457static void 1458amr_quartz_attach_mailbox(struct amr_softc *sc) 1459{ 1460 /* Quartz is given the mailbox location when a command is submitted */ 1461} 1462 1463static void 1464amr_std_attach_mailbox(struct amr_softc *sc) 1465{ 1466 1467 /* program the mailbox physical address */ 1468 AMR_SBYTE_SET(sc, AMR_SMBOX_0, sc->amr_mailboxphys & 0xff); 1469 AMR_SBYTE_SET(sc, AMR_SMBOX_1, (sc->amr_mailboxphys >> 8) & 0xff); 1470 AMR_SBYTE_SET(sc, AMR_SMBOX_2, (sc->amr_mailboxphys >> 16) & 0xff); 1471 AMR_SBYTE_SET(sc, AMR_SMBOX_3, (sc->amr_mailboxphys >> 24) & 0xff); 1472 AMR_SBYTE_SET(sc, AMR_SMBOX_ENABLE, AMR_SMBOX_ADDR); 1473 1474 /* clear any outstanding interrupt and enable interrupts proper */ 1475 AMR_SACK_INTERRUPT(sc); 1476 AMR_SENABLE_INTR(sc); 1477} 1478 1479/******************************************************************************** 1480 ******************************************************************************** 1481 Debugging 1482 ******************************************************************************** 1483 ********************************************************************************/ 1484 1485/******************************************************************************** 1486 * Print the command (ac) in human-readable format 1487 */ 1488static void 1489amr_printcommand(struct amr_command *ac) 1490{ 1491 struct amr_softc *sc = ac->ac_sc; 1492 struct amr_sgentry *sg; 1493 int i; 1494 1495 device_printf(sc->amr_dev, "cmd %x ident %d drive %d\n", 1496 ac->ac_mailbox.mb_command, ac->ac_mailbox.mb_ident, ac->ac_mailbox.mb_drive); 1497 device_printf(sc->amr_dev, "blkcount %d lba %d\n", 1498 ac->ac_mailbox.mb_blkcount, ac->ac_mailbox.mb_lba); 1499 device_printf(sc->amr_dev, "virtaddr %p length %lu\n", ac->ac_data, (unsigned long)ac->ac_length); 1500 device_printf(sc->amr_dev, "physaddr %08x nsg %d\n", 1501 ac->ac_mailbox.mb_physaddr, ac->ac_mailbox.mb_nsgelem); 1502 1503 /* get base address of s/g table */ 1504 sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG); 1505 for (i = 0; i < ac->ac_mailbox.mb_nsgelem; i++, sg++) 1506 device_printf(sc->amr_dev, " %x/%d\n", sg->sg_addr, sg->sg_count); 1507} 1508