aac.c revision 80359
1/*- 2 * Copyright (c) 2000 Michael Smith 3 * Copyright (c) 2000 BSDi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD: head/sys/dev/aac/aac.c 80359 2001-07-25 22:36:17Z scottl $ 28 */ 29 30/* 31 * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters. 32 */ 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/malloc.h> 37#include <sys/kernel.h> 38 39#include <dev/aac/aac_compat.h> 40 41#include <sys/bus.h> 42#include <sys/conf.h> 43#include <sys/devicestat.h> 44#include <sys/disk.h> 45#include <sys/file.h> 46#include <sys/signalvar.h> 47#include <sys/time.h> 48 49#include <machine/bus_memio.h> 50#include <machine/bus.h> 51#include <machine/resource.h> 52 53#include <dev/aac/aacreg.h> 54#include <dev/aac/aac_ioctl.h> 55#include <dev/aac/aacvar.h> 56#include <dev/aac/aac_tables.h> 57 58devclass_t aac_devclass; 59 60static void aac_startup(void *arg); 61 62/* Command Processing */ 63static void aac_startio(struct aac_softc *sc); 64static void aac_timeout(struct aac_softc *sc); 65static int aac_start(struct aac_command *cm); 66static void aac_complete(void *context, int pending); 67static int aac_bio_command(struct aac_softc *sc, struct aac_command **cmp); 68static void aac_bio_complete(struct aac_command *cm); 69static int aac_wait_command(struct aac_command *cm, int timeout); 70static void aac_host_command(struct aac_softc *sc); 71static void aac_host_response(struct aac_softc *sc); 72 73/* Command Buffer Management */ 74static int aac_alloc_command(struct aac_softc *sc, struct aac_command **cmp); 75static void aac_release_command(struct aac_command *cm); 76static void aac_map_command_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error); 77static int aac_alloc_commands(struct aac_softc *sc); 78static void aac_free_commands(struct aac_softc *sc); 79static void aac_map_command(struct aac_command *cm); 80static void aac_unmap_command(struct aac_command *cm); 81 82/* Hardware Interface */ 83static void aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, int error); 84static int aac_init(struct aac_softc *sc); 85static int aac_sync_command(struct aac_softc *sc, u_int32_t command, 86 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, 87 u_int32_t *sp); 88static int aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, 89 void *data, u_int16_t datasize, 90 void *result, u_int16_t *resultsize); 91static int aac_enqueue_fib(struct aac_softc *sc, int queue, u_int32_t fib_size, u_int32_t fib_addr); 92static int aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size, struct aac_fib **fib_addr); 93 94/* StrongARM interface */ 95static int aac_sa_get_fwstatus(struct aac_softc *sc); 96static void aac_sa_qnotify(struct aac_softc *sc, int qbit); 97static int aac_sa_get_istatus(struct aac_softc *sc); 98static void aac_sa_clear_istatus(struct aac_softc *sc, int mask); 99static void aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command, 100 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3); 101static int aac_sa_get_mailboxstatus(struct aac_softc *sc); 102static void aac_sa_set_interrupts(struct aac_softc *sc, int enable); 103 104struct aac_interface aac_sa_interface = { 105 aac_sa_get_fwstatus, 106 aac_sa_qnotify, 107 aac_sa_get_istatus, 108 aac_sa_clear_istatus, 109 aac_sa_set_mailbox, 110 aac_sa_get_mailboxstatus, 111 aac_sa_set_interrupts 112}; 113 114/* i960Rx interface */ 115static int aac_rx_get_fwstatus(struct aac_softc *sc); 116static void aac_rx_qnotify(struct aac_softc *sc, int qbit); 117static int aac_rx_get_istatus(struct aac_softc *sc); 118static void aac_rx_clear_istatus(struct aac_softc *sc, int mask); 119static void aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command, 120 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3); 121static int aac_rx_get_mailboxstatus(struct aac_softc *sc); 122static void aac_rx_set_interrupts(struct aac_softc *sc, int enable); 123 124struct aac_interface aac_rx_interface = { 125 aac_rx_get_fwstatus, 126 aac_rx_qnotify, 127 aac_rx_get_istatus, 128 aac_rx_clear_istatus, 129 aac_rx_set_mailbox, 130 aac_rx_get_mailboxstatus, 131 aac_rx_set_interrupts 132}; 133 134/* Debugging and Diagnostics */ 135static void aac_describe_controller(struct aac_softc *sc); 136static char *aac_describe_code(struct aac_code_lookup *table, u_int32_t code); 137 138/* Management Interface */ 139static d_open_t aac_open; 140static d_close_t aac_close; 141static d_ioctl_t aac_ioctl; 142static int aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib) __unused; 143static void aac_handle_aif(struct aac_softc *sc, struct aac_aif_command *aif); 144#ifdef AAC_COMPAT_LINUX 145static int aac_linux_rev_check(struct aac_softc *sc, caddr_t udata); 146static int aac_linux_getnext_aif(struct aac_softc *sc, caddr_t arg); 147static int aac_linux_return_aif(struct aac_softc *sc, caddr_t uptr); 148#endif 149 150#define AAC_CDEV_MAJOR 150 151 152static struct cdevsw aac_cdevsw = { 153 aac_open, /* open */ 154 aac_close, /* close */ 155 noread, /* read */ 156 nowrite, /* write */ 157 aac_ioctl, /* ioctl */ 158 nopoll, /* poll */ 159 nommap, /* mmap */ 160 nostrategy, /* strategy */ 161 "aac", /* name */ 162 AAC_CDEV_MAJOR, /* major */ 163 nodump, /* dump */ 164 nopsize, /* psize */ 165 0, /* flags */ 166}; 167 168/******************************************************************************** 169 ******************************************************************************** 170 Device Interface 171 ******************************************************************************** 172 ********************************************************************************/ 173 174/******************************************************************************** 175 * Initialise the controller and softc 176 */ 177int 178aac_attach(struct aac_softc *sc) 179{ 180 int error, unit; 181 182 debug_called(1); 183 184 /* 185 * Initialise per-controller queues. 186 */ 187 aac_initq_free(sc); 188 aac_initq_ready(sc); 189 aac_initq_busy(sc); 190 aac_initq_complete(sc); 191 aac_initq_bio(sc); 192 193#if __FreeBSD_version >= 500005 194 /* 195 * Initialise command-completion task. 196 */ 197 TASK_INIT(&sc->aac_task_complete, 0, aac_complete, sc); 198#endif 199 200 /* disable interrupts before we enable anything */ 201 AAC_MASK_INTERRUPTS(sc); 202 203 /* mark controller as suspended until we get ourselves organised */ 204 sc->aac_state |= AAC_STATE_SUSPEND; 205 206 /* 207 * Allocate command structures. 208 */ 209 if ((error = aac_alloc_commands(sc)) != 0) 210 return(error); 211 212 /* 213 * Initialise the adapter. 214 */ 215 if ((error = aac_init(sc)) != 0) 216 return(error); 217 218 /* 219 * Print a little information about the controller. 220 */ 221 aac_describe_controller(sc); 222 223 /* 224 * Register to probe our containers later. 225 */ 226 sc->aac_ich.ich_func = aac_startup; 227 sc->aac_ich.ich_arg = sc; 228 if (config_intrhook_establish(&sc->aac_ich) != 0) { 229 device_printf(sc->aac_dev, "can't establish configuration hook\n"); 230 return(ENXIO); 231 } 232 233 /* 234 * Make the control device. 235 */ 236 unit = device_get_unit(sc->aac_dev); 237 sc->aac_dev_t = make_dev(&aac_cdevsw, unit, UID_ROOT, GID_WHEEL, 0644, "aac%d", unit); 238 (void)make_dev_alias(sc->aac_dev_t, "afa%d", unit); 239 (void)make_dev_alias(sc->aac_dev_t, "hpn%d", unit); 240 241 sc->aac_dev_t->si_drv1 = sc; 242 243 return(0); 244} 245 246/******************************************************************************** 247 * Probe for containers, create disks. 248 */ 249static void 250aac_startup(void *arg) 251{ 252 struct aac_softc *sc = (struct aac_softc *)arg; 253 struct aac_mntinfo mi; 254 struct aac_mntinforesponse mir; 255 device_t child; 256 u_int16_t rsize; 257 int i; 258 259 debug_called(1); 260 261 /* disconnect ourselves from the intrhook chain */ 262 config_intrhook_disestablish(&sc->aac_ich); 263 264 /* loop over possible containers */ 265 mi.Command = VM_NameServe; 266 mi.MntType = FT_FILESYS; 267 for (i = 0; i < AAC_MAX_CONTAINERS; i++) { 268 /* request information on this container */ 269 mi.MntCount = i; 270 if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(struct aac_mntinfo), &mir, &rsize)) { 271 debug(2, "error probing container %d", i); 272 continue; 273 } 274 /* check response size */ 275 if (rsize != sizeof(mir)) { 276 debug(2, "container info response wrong size (%d should be %d)", rsize, sizeof(mir)); 277 continue; 278 } 279 /* 280 * Check container volume type for validity. Note that many of the possible types 281 * may never show up. 282 */ 283 if ((mir.Status == ST_OK) && (mir.MntTable[0].VolType != CT_NONE)) { 284 debug(1, "%d: id %x name '%.16s' size %u type %d", 285 i, mir.MntTable[0].ObjectId, 286 mir.MntTable[0].FileSystemName, mir.MntTable[0].Capacity, 287 mir.MntTable[0].VolType); 288 289 if ((child = device_add_child(sc->aac_dev, NULL, -1)) == NULL) { 290 device_printf(sc->aac_dev, "device_add_child failed\n"); 291 } else { 292 device_set_ivars(child, &sc->aac_container[i]); 293 } 294 device_set_desc(child, aac_describe_code(aac_container_types, mir.MntTable[0].VolType)); 295 sc->aac_container[i].co_disk = child; 296 sc->aac_container[i].co_mntobj = mir.MntTable[0]; 297 } 298 } 299 300 /* poke the bus to actually attach the child devices */ 301 if (bus_generic_attach(sc->aac_dev)) 302 device_printf(sc->aac_dev, "bus_generic_attach failed\n"); 303 304 /* mark the controller up */ 305 sc->aac_state &= ~AAC_STATE_SUSPEND; 306 307 /* enable interrupts now */ 308 AAC_UNMASK_INTERRUPTS(sc); 309 310 /* enable the timeout watchdog */ 311 timeout((timeout_t*)aac_timeout, sc, AAC_PERIODIC_INTERVAL * hz); 312} 313 314/******************************************************************************** 315 * Free all of the resources associated with (sc) 316 * 317 * Should not be called if the controller is active. 318 */ 319void 320aac_free(struct aac_softc *sc) 321{ 322 debug_called(1); 323 324 /* remove the control device */ 325 if (sc->aac_dev_t != NULL) 326 destroy_dev(sc->aac_dev_t); 327 328 /* throw away any FIB buffers, discard the FIB DMA tag */ 329 if (sc->aac_fibs != NULL) 330 aac_free_commands(sc); 331 if (sc->aac_fib_dmat) 332 bus_dma_tag_destroy(sc->aac_fib_dmat); 333 334 /* destroy the common area */ 335 if (sc->aac_common) { 336 bus_dmamap_unload(sc->aac_common_dmat, sc->aac_common_dmamap); 337 bus_dmamem_free(sc->aac_common_dmat, sc->aac_common, sc->aac_common_dmamap); 338 } 339 if (sc->aac_common_dmat) 340 bus_dma_tag_destroy(sc->aac_common_dmat); 341 342 /* disconnect the interrupt handler */ 343 if (sc->aac_intr) 344 bus_teardown_intr(sc->aac_dev, sc->aac_irq, sc->aac_intr); 345 if (sc->aac_irq != NULL) 346 bus_release_resource(sc->aac_dev, SYS_RES_IRQ, sc->aac_irq_rid, sc->aac_irq); 347 348 /* destroy data-transfer DMA tag */ 349 if (sc->aac_buffer_dmat) 350 bus_dma_tag_destroy(sc->aac_buffer_dmat); 351 352 /* destroy the parent DMA tag */ 353 if (sc->aac_parent_dmat) 354 bus_dma_tag_destroy(sc->aac_parent_dmat); 355 356 /* release the register window mapping */ 357 if (sc->aac_regs_resource != NULL) 358 bus_release_resource(sc->aac_dev, SYS_RES_MEMORY, sc->aac_regs_rid, sc->aac_regs_resource); 359} 360 361/******************************************************************************** 362 * Disconnect from the controller completely, in preparation for unload. 363 */ 364int 365aac_detach(device_t dev) 366{ 367 struct aac_softc *sc = device_get_softc(dev); 368 int error; 369 370 debug_called(1); 371 372 if (sc->aac_state & AAC_STATE_OPEN) 373 return(EBUSY); 374 375 if ((error = aac_shutdown(dev))) 376 return(error); 377 378 aac_free(sc); 379 380 return(0); 381} 382 383/******************************************************************************** 384 * Bring the controller down to a dormant state and detach all child devices. 385 * 386 * This function is called before detach or system shutdown. 387 * 388 * Note that we can assume that the bioq on the controller is empty, as we won't 389 * allow shutdown if any device is open. 390 */ 391int 392aac_shutdown(device_t dev) 393{ 394 struct aac_softc *sc = device_get_softc(dev); 395 struct aac_close_command cc; 396 int s, i; 397 398 debug_called(1); 399 400 s = splbio(); 401 402 sc->aac_state |= AAC_STATE_SUSPEND; 403 404 /* 405 * Send a Container shutdown followed by a HostShutdown FIB to the 406 * controller to convince it that we don't want to talk to it anymore. 407 * We've been closed and all I/O completed already 408 */ 409 device_printf(sc->aac_dev, "shutting down controller..."); 410 411 cc.Command = VM_CloseAll; 412 cc.ContainerId = 0xffffffff; 413 if (aac_sync_fib(sc, ContainerCommand, 0, &cc, sizeof(cc), NULL, NULL)) { 414 printf("FAILED.\n"); 415 } else { 416 i = 0; 417 if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN, &i, sizeof(i), NULL, NULL)) { 418 printf("FAILED.\n"); 419 } else { 420 printf("done.\n"); 421 } 422 } 423 424 AAC_MASK_INTERRUPTS(sc); 425 426 splx(s); 427 return(0); 428} 429 430/******************************************************************************** 431 * Bring the controller to a quiescent state, ready for system suspend. 432 */ 433int 434aac_suspend(device_t dev) 435{ 436 struct aac_softc *sc = device_get_softc(dev); 437 int s; 438 439 debug_called(1); 440 s = splbio(); 441 442 sc->aac_state |= AAC_STATE_SUSPEND; 443 444 AAC_MASK_INTERRUPTS(sc); 445 splx(s); 446 return(0); 447} 448 449/******************************************************************************** 450 * Bring the controller back to a state ready for operation. 451 */ 452int 453aac_resume(device_t dev) 454{ 455 struct aac_softc *sc = device_get_softc(dev); 456 457 debug_called(1); 458 sc->aac_state &= ~AAC_STATE_SUSPEND; 459 AAC_UNMASK_INTERRUPTS(sc); 460 return(0); 461} 462 463/******************************************************************************* 464 * Take an interrupt. 465 */ 466void 467aac_intr(void *arg) 468{ 469 struct aac_softc *sc = (struct aac_softc *)arg; 470 u_int16_t reason; 471 472 debug_called(2); 473 474 reason = AAC_GET_ISTATUS(sc); 475 476 /* controller wants to talk to the log? XXX should we defer this? */ 477 if (reason & AAC_DB_PRINTF) { 478 if (sc->aac_common->ac_printf[0]) { 479 device_printf(sc->aac_dev, "** %.*s", AAC_PRINTF_BUFSIZE, sc->aac_common->ac_printf); 480 sc->aac_common->ac_printf[0] = 0; 481 } 482 AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF); 483 AAC_QNOTIFY(sc, AAC_DB_PRINTF); 484 } 485 486 /* controller has a message for us? */ 487 if (reason & AAC_DB_COMMAND_READY) { 488 AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY); 489 aac_host_command(sc); 490 } 491 492 /* controller has a response for us? */ 493 if (reason & AAC_DB_RESPONSE_READY) { 494 AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY); 495 aac_host_response(sc); 496 } 497 498 /* spurious interrupts that we don't use - reset the mask and clear the interrupts */ 499 if (reason & (AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL)) { 500 AAC_UNMASK_INTERRUPTS(sc); 501 AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL); 502 } 503}; 504 505/******************************************************************************** 506 ******************************************************************************** 507 Command Processing 508 ******************************************************************************** 509 ********************************************************************************/ 510 511/******************************************************************************** 512 * Start as much queued I/O as possible on the controller 513 */ 514static void 515aac_startio(struct aac_softc *sc) 516{ 517 struct aac_command *cm; 518 519 debug_called(2); 520 521 for(;;) { 522 /* try to get a command that's been put off for lack of resources */ 523 cm = aac_dequeue_ready(sc); 524 525 /* try to build a command off the bio queue (ignore error return) */ 526 if (cm == NULL) 527 aac_bio_command(sc, &cm); 528 529 /* nothing to do? */ 530 if (cm == NULL) 531 break; 532 533 /* try to give the command to the controller */ 534 if (aac_start(cm) == EBUSY) { 535 /* put it on the ready queue for later */ 536 aac_requeue_ready(cm); 537 break; 538 } 539 } 540} 541 542/******************************************************************************** 543 * Deliver a command to the controller; allocate controller resources at the 544 * last moment when possible. 545 */ 546static int 547aac_start(struct aac_command *cm) 548{ 549 struct aac_softc *sc = cm->cm_sc; 550 int error; 551 552 debug_called(2); 553 554 /* get the command mapped */ 555 aac_map_command(cm); 556 557 /* fix up the address values in the FIB */ 558 cm->cm_fib->Header.SenderFibAddress = (u_int32_t)cm->cm_fib; 559 cm->cm_fib->Header.ReceiverFibAddress = cm->cm_fibphys; 560 561 /* save a pointer to the command for speedy reverse-lookup */ 562 cm->cm_fib->Header.SenderData = (u_int32_t)cm; /* XXX 64-bit physical address issue */ 563 564 /* put the FIB on the outbound queue */ 565 if (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, cm->cm_fib->Header.Size, 566 cm->cm_fib->Header.ReceiverFibAddress)) { 567 error = EBUSY; 568 } else { 569 aac_enqueue_busy(cm); 570 error = 0; 571 } 572 return(error); 573} 574 575/******************************************************************************** 576 * Handle notification of one or more FIBs coming from the controller. 577 */ 578static void 579aac_host_command(struct aac_softc *sc) 580{ 581 struct aac_fib *fib; 582 u_int32_t fib_size; 583 584 debug_called(1); 585 586 for (;;) { 587 if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size, &fib)) 588 break; /* nothing to do */ 589 590 switch(fib->Header.Command) { 591 case AifRequest: 592 aac_handle_aif(sc, (struct aac_aif_command *)&fib->data[0]); 593 break; 594 default: 595 device_printf(sc->aac_dev, "unknown command from controller\n"); 596 AAC_PRINT_FIB(sc, fib); 597 break; 598 } 599 600 /* XXX reply to FIBs requesting responses ?? */ 601 /* XXX how do we return these FIBs to the controller? */ 602 } 603} 604 605/******************************************************************************** 606 * Handle notification of one or more FIBs completed by the controller 607 */ 608static void 609aac_host_response(struct aac_softc *sc) 610{ 611 struct aac_command *cm; 612 struct aac_fib *fib; 613 u_int32_t fib_size; 614 615 debug_called(2); 616 617 for (;;) { 618 /* look for completed FIBs on our queue */ 619 if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size, &fib)) 620 break; /* nothing to do */ 621 622 /* get the command, unmap and queue for later processing */ 623 cm = (struct aac_command *)fib->Header.SenderData; 624 if (cm == NULL) { 625 AAC_PRINT_FIB(sc, fib); 626 } else { 627 aac_remove_busy(cm); 628 aac_unmap_command(cm); /* XXX defer? */ 629 aac_enqueue_complete(cm); 630 } 631 } 632 633 /* handle completion processing */ 634#if __FreeBSD_version >= 500005 635 taskqueue_enqueue(taskqueue_swi, &sc->aac_task_complete); 636#else 637 aac_complete(sc, 0); 638#endif 639} 640 641/******************************************************************************** 642 * Process completed commands. 643 */ 644static void 645aac_complete(void *context, int pending) 646{ 647 struct aac_softc *sc = (struct aac_softc *)context; 648 struct aac_command *cm; 649 650 debug_called(2); 651 652 /* pull completed commands off the queue */ 653 for (;;) { 654 cm = aac_dequeue_complete(sc); 655 if (cm == NULL) 656 break; 657 cm->cm_flags |= AAC_CMD_COMPLETED; 658 659 /* is there a completion handler? */ 660 if (cm->cm_complete != NULL) { 661 cm->cm_complete(cm); 662 } else { 663 /* assume that someone is sleeping on this command */ 664 wakeup(cm); 665 } 666 } 667 668 /* see if we can start some more I/O */ 669 aac_startio(sc); 670} 671 672/******************************************************************************** 673 * Handle a bio submitted from a disk device. 674 */ 675void 676aac_submit_bio(struct bio *bp) 677{ 678 struct aac_disk *ad = (struct aac_disk *)bp->bio_dev->si_drv1; 679 struct aac_softc *sc = ad->ad_controller; 680 681 debug_called(2); 682 683 /* queue the BIO and try to get some work done */ 684 aac_enqueue_bio(sc, bp); 685 aac_startio(sc); 686} 687 688/******************************************************************************** 689 * Get a bio and build a command to go with it. 690 */ 691static int 692aac_bio_command(struct aac_softc *sc, struct aac_command **cmp) 693{ 694 struct aac_command *cm; 695 struct aac_fib *fib; 696 struct aac_blockread *br; 697 struct aac_blockwrite *bw; 698 struct aac_disk *ad; 699 struct bio *bp; 700 701 debug_called(2); 702 703 /* get the resources we will need */ 704 cm = NULL; 705 if ((bp = aac_dequeue_bio(sc)) == NULL) 706 goto fail; 707 if (aac_alloc_command(sc, &cm)) /* get a command */ 708 goto fail; 709 710 /* fill out the command */ 711 cm->cm_data = (void *)bp->bio_data; 712 cm->cm_datalen = bp->bio_bcount; 713 cm->cm_complete = aac_bio_complete; 714 cm->cm_private = bp; 715 cm->cm_timestamp = time_second; 716 717 /* build the FIB */ 718 fib = cm->cm_fib; 719 fib->Header.XferState = 720 AAC_FIBSTATE_HOSTOWNED | 721 AAC_FIBSTATE_INITIALISED | 722 AAC_FIBSTATE_FROMHOST | 723 AAC_FIBSTATE_REXPECTED | 724 AAC_FIBSTATE_NORM; 725 fib->Header.Command = ContainerCommand; 726 fib->Header.Size = sizeof(struct aac_fib_header); 727 728 /* build the read/write request */ 729 ad = (struct aac_disk *)bp->bio_dev->si_drv1; 730 if (BIO_IS_READ(bp)) { 731 br = (struct aac_blockread *)&fib->data[0]; 732 br->Command = VM_CtBlockRead; 733 br->ContainerId = ad->ad_container->co_mntobj.ObjectId; 734 br->BlockNumber = bp->bio_pblkno; 735 br->ByteCount = bp->bio_bcount; 736 fib->Header.Size += sizeof(struct aac_blockread); 737 cm->cm_sgtable = &br->SgMap; 738 cm->cm_flags |= AAC_CMD_DATAIN; 739 } else { 740 bw = (struct aac_blockwrite *)&fib->data[0]; 741 bw->Command = VM_CtBlockWrite; 742 bw->ContainerId = ad->ad_container->co_mntobj.ObjectId; 743 bw->BlockNumber = bp->bio_pblkno; 744 bw->ByteCount = bp->bio_bcount; 745 bw->Stable = CUNSTABLE; /* XXX what's appropriate here? */ 746 fib->Header.Size += sizeof(struct aac_blockwrite); 747 cm->cm_flags |= AAC_CMD_DATAOUT; 748 cm->cm_sgtable = &bw->SgMap; 749 } 750 751 *cmp = cm; 752 return(0); 753 754fail: 755 if (bp != NULL) 756 aac_enqueue_bio(sc, bp); 757 if (cm != NULL) 758 aac_release_command(cm); 759 return(ENOMEM); 760} 761 762/******************************************************************************** 763 * Handle a bio-instigated command that has been completed. 764 */ 765static void 766aac_bio_complete(struct aac_command *cm) 767{ 768 struct aac_blockread_response *brr; 769 struct aac_blockwrite_response *bwr; 770 struct bio *bp; 771 AAC_FSAStatus status; 772 773 /* fetch relevant status and then release the command */ 774 bp = (struct bio *)cm->cm_private; 775 if (BIO_IS_READ(bp)) { 776 brr = (struct aac_blockread_response *)&cm->cm_fib->data[0]; 777 status = brr->Status; 778 } else { 779 bwr = (struct aac_blockwrite_response *)&cm->cm_fib->data[0]; 780 status = bwr->Status; 781 } 782 aac_release_command(cm); 783 784 /* fix up the bio based on status */ 785 if (status == ST_OK) { 786 bp->bio_resid = 0; 787 } else { 788 bp->bio_error = EIO; 789 bp->bio_flags |= BIO_ERROR; 790 /* pass an error string out to the disk layer */ 791 bp->bio_driver1 = aac_describe_code(aac_command_status_table, status); 792 } 793 aac_biodone(bp); 794} 795 796/******************************************************************************** 797 * Submit a command to the controller, return when it completes. 798 */ 799static int 800aac_wait_command(struct aac_command *cm, int timeout) 801{ 802 int s, error = 0; 803 804 debug_called(2); 805 806 /* Put the command on the ready queue and get things going */ 807 aac_enqueue_ready(cm); 808 aac_startio(cm->cm_sc); 809 s = splbio(); 810 while(!(cm->cm_flags & AAC_CMD_COMPLETED) && (error != EWOULDBLOCK)) { 811 error = tsleep(cm, PRIBIO, "aacwait", timeout * hz); 812 } 813 splx(s); 814 return(error); 815} 816 817/******************************************************************************** 818 ******************************************************************************** 819 Command Buffer Management 820 ******************************************************************************** 821 ********************************************************************************/ 822 823/******************************************************************************** 824 * Allocate a command. 825 */ 826static int 827aac_alloc_command(struct aac_softc *sc, struct aac_command **cmp) 828{ 829 struct aac_command *cm; 830 831 debug_called(3); 832 833 if ((cm = aac_dequeue_free(sc)) == NULL) 834 return(ENOMEM); 835 836 *cmp = cm; 837 return(0); 838} 839 840/******************************************************************************** 841 * Release a command back to the freelist. 842 */ 843static void 844aac_release_command(struct aac_command *cm) 845{ 846 debug_called(3); 847 848 /* (re)initialise the command/FIB */ 849 cm->cm_sgtable = NULL; 850 cm->cm_flags = 0; 851 cm->cm_complete = NULL; 852 cm->cm_private = NULL; 853 cm->cm_fib->Header.XferState = AAC_FIBSTATE_EMPTY; 854 cm->cm_fib->Header.StructType = AAC_FIBTYPE_TFIB; 855 cm->cm_fib->Header.Flags = 0; 856 cm->cm_fib->Header.SenderSize = sizeof(struct aac_fib); 857 858 /* 859 * These are duplicated in aac_start to cover the case where an 860 * intermediate stage may have destroyed them. They're left 861 * initialised here for debugging purposes only. 862 */ 863 cm->cm_fib->Header.SenderFibAddress = (u_int32_t)cm->cm_fib; 864 cm->cm_fib->Header.ReceiverFibAddress = cm->cm_fibphys; 865 866 aac_enqueue_free(cm); 867} 868 869/******************************************************************************** 870 * Map helper for command/FIB allocation. 871 */ 872static void 873aac_map_command_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error) 874{ 875 struct aac_softc *sc = (struct aac_softc *)arg; 876 877 debug_called(3); 878 879 sc->aac_fibphys = segs[0].ds_addr; 880} 881 882/******************************************************************************** 883 * Allocate and initialise commands/FIBs for this adapter. 884 */ 885static int 886aac_alloc_commands(struct aac_softc *sc) 887{ 888 struct aac_command *cm; 889 int i; 890 891 debug_called(1); 892 893 /* allocate the FIBs in DMAable memory and load them */ 894 if (bus_dmamem_alloc(sc->aac_fib_dmat, (void **)&sc->aac_fibs, BUS_DMA_NOWAIT, &sc->aac_fibmap)) { 895 return(ENOMEM); 896 } 897 bus_dmamap_load(sc->aac_fib_dmat, sc->aac_fibmap, sc->aac_fibs, 898 AAC_FIB_COUNT * sizeof(struct aac_fib), aac_map_command_helper, sc, 0); 899 900 /* initialise constant fields in the command structure */ 901 for (i = 0; i < AAC_FIB_COUNT; i++) { 902 cm = &sc->aac_command[i]; 903 cm->cm_sc = sc; 904 cm->cm_fib = sc->aac_fibs + i; 905 cm->cm_fibphys = sc->aac_fibphys + (i * sizeof(struct aac_fib)); 906 907 if (!bus_dmamap_create(sc->aac_buffer_dmat, 0, &cm->cm_datamap)) 908 aac_release_command(cm); 909 } 910 return(0); 911} 912 913/******************************************************************************** 914 * Free FIBs owned by this adapter. 915 */ 916static void 917aac_free_commands(struct aac_softc *sc) 918{ 919 int i; 920 921 debug_called(1); 922 923 for (i = 0; i < AAC_FIB_COUNT; i++) 924 bus_dmamap_destroy(sc->aac_buffer_dmat, sc->aac_command[i].cm_datamap); 925 bus_dmamap_unload(sc->aac_fib_dmat, sc->aac_fibmap); 926 bus_dmamem_free(sc->aac_fib_dmat, sc->aac_fibs, sc->aac_fibmap); 927} 928 929/******************************************************************************** 930 * Command-mapping helper function - populate this command's s/g table. 931 */ 932static void 933aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) 934{ 935 struct aac_command *cm = (struct aac_command *)arg; 936 struct aac_fib *fib = cm->cm_fib; 937 struct aac_sg_table *sg; 938 int i; 939 940 debug_called(3); 941 942 /* find the s/g table */ 943 sg = cm->cm_sgtable; 944 945 /* copy into the FIB */ 946 if (sg != NULL) { 947 sg->SgCount = nseg; 948 for (i = 0; i < nseg; i++) { 949 sg->SgEntry[i].SgAddress = segs[i].ds_addr; 950 sg->SgEntry[i].SgByteCount = segs[i].ds_len; 951 } 952 /* update the FIB size for the s/g count */ 953 fib->Header.Size += nseg * sizeof(struct aac_sg_entry); 954 } 955 956} 957 958/******************************************************************************** 959 * Map a command into controller-visible space. 960 */ 961static void 962aac_map_command(struct aac_command *cm) 963{ 964 struct aac_softc *sc = cm->cm_sc; 965 966 debug_called(2); 967 968 /* don't map more than once */ 969 if (cm->cm_flags & AAC_CMD_MAPPED) 970 return; 971 972 if (cm->cm_datalen != 0) { 973 bus_dmamap_load(sc->aac_buffer_dmat, cm->cm_datamap, cm->cm_data, 974 cm->cm_datalen, aac_map_command_sg, cm, 0); 975 976 if (cm->cm_flags & AAC_CMD_DATAIN) 977 bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, BUS_DMASYNC_PREREAD); 978 if (cm->cm_flags & AAC_CMD_DATAOUT) 979 bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, BUS_DMASYNC_PREWRITE); 980 } 981 cm->cm_flags |= AAC_CMD_MAPPED; 982} 983 984/******************************************************************************** 985 * Unmap a command from controller-visible space. 986 */ 987static void 988aac_unmap_command(struct aac_command *cm) 989{ 990 struct aac_softc *sc = cm->cm_sc; 991 992 debug_called(2); 993 994 if (!(cm->cm_flags & AAC_CMD_MAPPED)) 995 return; 996 997 if (cm->cm_datalen != 0) { 998 if (cm->cm_flags & AAC_CMD_DATAIN) 999 bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, BUS_DMASYNC_POSTREAD); 1000 if (cm->cm_flags & AAC_CMD_DATAOUT) 1001 bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, BUS_DMASYNC_POSTWRITE); 1002 1003 bus_dmamap_unload(sc->aac_buffer_dmat, cm->cm_datamap); 1004 } 1005 cm->cm_flags &= ~AAC_CMD_MAPPED; 1006} 1007 1008/******************************************************************************** 1009 ******************************************************************************** 1010 Hardware Interface 1011 ******************************************************************************** 1012 ********************************************************************************/ 1013 1014/******************************************************************************** 1015 * Initialise the adapter. 1016 */ 1017static void 1018aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1019{ 1020 struct aac_softc *sc = (struct aac_softc *)arg; 1021 1022 debug_called(1); 1023 1024 sc->aac_common_busaddr = segs[0].ds_addr; 1025} 1026 1027static int 1028aac_init(struct aac_softc *sc) 1029{ 1030 struct aac_adapter_init *ip; 1031 time_t then; 1032 u_int32_t code; 1033 u_int8_t *qaddr; 1034 1035 debug_called(1); 1036 1037 /* 1038 * First wait for the adapter to come ready. 1039 */ 1040 then = time_second; 1041 do { 1042 code = AAC_GET_FWSTATUS(sc); 1043 if (code & AAC_SELF_TEST_FAILED) { 1044 device_printf(sc->aac_dev, "FATAL: selftest failed\n"); 1045 return(ENXIO); 1046 } 1047 if (code & AAC_KERNEL_PANIC) { 1048 device_printf(sc->aac_dev, "FATAL: controller kernel panic\n"); 1049 return(ENXIO); 1050 } 1051 if (time_second > (then + AAC_BOOT_TIMEOUT)) { 1052 device_printf(sc->aac_dev, "FATAL: controller not coming ready, status %x\n", code); 1053 return(ENXIO); 1054 } 1055 } while (!(code & AAC_UP_AND_RUNNING)); 1056 1057 /* 1058 * Create DMA tag for the common structure and allocate it. 1059 */ 1060 if (bus_dma_tag_create(sc->aac_parent_dmat, /* parent */ 1061 1, 0, /* alignment, boundary */ 1062 BUS_SPACE_MAXADDR, /* lowaddr */ 1063 BUS_SPACE_MAXADDR, /* highaddr */ 1064 NULL, NULL, /* filter, filterarg */ 1065 sizeof(struct aac_common), 1,/* maxsize, nsegments */ 1066 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 1067 0, /* flags */ 1068 &sc->aac_common_dmat)) { 1069 device_printf(sc->aac_dev, "can't allocate common structure DMA tag\n"); 1070 return(ENOMEM); 1071 } 1072 if (bus_dmamem_alloc(sc->aac_common_dmat, (void **)&sc->aac_common, BUS_DMA_NOWAIT, &sc->aac_common_dmamap)) { 1073 device_printf(sc->aac_dev, "can't allocate common structure\n"); 1074 return(ENOMEM); 1075 } 1076 bus_dmamap_load(sc->aac_common_dmat, sc->aac_common_dmamap, sc->aac_common, sizeof(*sc->aac_common), 1077 aac_common_map, sc, 0); 1078 bzero(sc->aac_common, sizeof(*sc->aac_common)); 1079 1080 /* 1081 * Fill in the init structure. This tells the adapter about the physical location 1082 * of various important shared data structures. 1083 */ 1084 ip = &sc->aac_common->ac_init; 1085 ip->InitStructRevision = AAC_INIT_STRUCT_REVISION; 1086 1087 ip->AdapterFibsPhysicalAddress = sc->aac_common_busaddr + offsetof(struct aac_common, ac_fibs); 1088 ip->AdapterFibsVirtualAddress = &sc->aac_common->ac_fibs[0]; 1089 ip->AdapterFibsSize = AAC_ADAPTER_FIBS * sizeof(struct aac_fib); 1090 ip->AdapterFibAlign = sizeof(struct aac_fib); 1091 1092 ip->PrintfBufferAddress = sc->aac_common_busaddr + offsetof(struct aac_common, ac_printf); 1093 ip->PrintfBufferSize = AAC_PRINTF_BUFSIZE; 1094 1095 ip->HostPhysMemPages = 0; /* not used? */ 1096 ip->HostElapsedSeconds = time_second; /* reset later if invalid */ 1097 1098 /* 1099 * Initialise FIB queues. Note that it appears that the layout of the indexes 1100 * and the segmentation of the entries may be mandated by the adapter, which is 1101 * only told about the base of the queue index fields. 1102 * 1103 * The initial values of the indices are assumed to inform the adapter 1104 * of the sizes of the respective queues, and theoretically it could work out 1105 * the entire layout of the queue structures from this. We take the easy 1106 * route and just lay this area out like everyone else does. 1107 * 1108 * The Linux driver uses a much more complex scheme whereby several header 1109 * records are kept for each queue. We use a couple of generic list manipulation 1110 * functions which 'know' the size of each list by virtue of a table. 1111 */ 1112 qaddr = &sc->aac_common->ac_qbuf[0] + AAC_QUEUE_ALIGN; 1113 qaddr -= (u_int32_t)qaddr % AAC_QUEUE_ALIGN; 1114 sc->aac_queues = (struct aac_queue_table *)qaddr; 1115 ip->CommHeaderAddress = sc->aac_common_busaddr + ((u_int32_t)sc->aac_queues - (u_int32_t)sc->aac_common); 1116 bzero(sc->aac_queues, sizeof(struct aac_queue_table)); 1117 1118 sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = AAC_HOST_NORM_CMD_ENTRIES; 1119 sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] = AAC_HOST_NORM_CMD_ENTRIES; 1120 sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] = AAC_HOST_HIGH_CMD_ENTRIES; 1121 sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] = AAC_HOST_HIGH_CMD_ENTRIES; 1122 sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = AAC_ADAP_NORM_CMD_ENTRIES; 1123 sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] = AAC_ADAP_NORM_CMD_ENTRIES; 1124 sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] = AAC_ADAP_HIGH_CMD_ENTRIES; 1125 sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] = AAC_ADAP_HIGH_CMD_ENTRIES; 1126 sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = AAC_HOST_NORM_RESP_ENTRIES; 1127 sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = AAC_HOST_NORM_RESP_ENTRIES; 1128 sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = AAC_HOST_HIGH_RESP_ENTRIES; 1129 sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = AAC_HOST_HIGH_RESP_ENTRIES; 1130 sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = AAC_ADAP_NORM_RESP_ENTRIES; 1131 sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = AAC_ADAP_NORM_RESP_ENTRIES; 1132 sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = AAC_ADAP_HIGH_RESP_ENTRIES; 1133 sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = AAC_ADAP_HIGH_RESP_ENTRIES; 1134 sc->aac_qentries[AAC_HOST_NORM_CMD_QUEUE] = &sc->aac_queues->qt_HostNormCmdQueue[0]; 1135 sc->aac_qentries[AAC_HOST_HIGH_CMD_QUEUE] = &sc->aac_queues->qt_HostHighCmdQueue[0]; 1136 sc->aac_qentries[AAC_ADAP_NORM_CMD_QUEUE] = &sc->aac_queues->qt_AdapNormCmdQueue[0]; 1137 sc->aac_qentries[AAC_ADAP_HIGH_CMD_QUEUE] = &sc->aac_queues->qt_AdapHighCmdQueue[0]; 1138 sc->aac_qentries[AAC_HOST_NORM_RESP_QUEUE] = &sc->aac_queues->qt_HostNormRespQueue[0]; 1139 sc->aac_qentries[AAC_HOST_HIGH_RESP_QUEUE] = &sc->aac_queues->qt_HostHighRespQueue[0]; 1140 sc->aac_qentries[AAC_ADAP_NORM_RESP_QUEUE] = &sc->aac_queues->qt_AdapNormRespQueue[0]; 1141 sc->aac_qentries[AAC_ADAP_HIGH_RESP_QUEUE] = &sc->aac_queues->qt_AdapHighRespQueue[0]; 1142 1143 /* 1144 * Do controller-type-specific initialisation 1145 */ 1146 switch (sc->aac_hwif) { 1147 case AAC_HWIF_I960RX: 1148 AAC_SETREG4(sc, AAC_RX_ODBR, ~0); 1149 break; 1150 } 1151 1152 /* 1153 * Give the init structure to the controller. 1154 */ 1155 if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT, 1156 sc->aac_common_busaddr + offsetof(struct aac_common, ac_init), 1157 0, 0, 0, NULL)) { 1158 device_printf(sc->aac_dev, "error establishing init structure\n"); 1159 return(EIO); 1160 } 1161 1162 return(0); 1163} 1164 1165/******************************************************************************** 1166 * Send a synchronous command to the controller and wait for a result. 1167 */ 1168static int 1169aac_sync_command(struct aac_softc *sc, u_int32_t command, 1170 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, 1171 u_int32_t *sp) 1172{ 1173 time_t then; 1174 u_int32_t status; 1175 1176 debug_called(3); 1177 1178 /* populate the mailbox */ 1179 AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3); 1180 1181 /* ensure the sync command doorbell flag is cleared */ 1182 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); 1183 1184 /* then set it to signal the adapter */ 1185 AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND); 1186 1187 /* spin waiting for the command to complete */ 1188 then = time_second; 1189 do { 1190 if (time_second > (then + AAC_IMMEDIATE_TIMEOUT)) { 1191 debug(2, "timed out"); 1192 return(EIO); 1193 } 1194 } while (!(AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND)); 1195 1196 /* clear the completion flag */ 1197 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); 1198 1199 /* get the command status */ 1200 status = AAC_GET_MAILBOXSTATUS(sc); 1201 if (sp != NULL) 1202 *sp = status; 1203 return(0); 1204} 1205 1206/******************************************************************************** 1207 * Send a synchronous FIB to the controller and wait for a result. 1208 */ 1209static int 1210aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, 1211 void *data, u_int16_t datasize, 1212 void *result, u_int16_t *resultsize) 1213{ 1214 struct aac_fib *fib = &sc->aac_common->ac_sync_fib; 1215 1216 debug_called(3); 1217 1218 if (datasize > AAC_FIB_DATASIZE) 1219 return(EINVAL); 1220 1221 /* 1222 * Set up the sync FIB 1223 */ 1224 fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED | AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY; 1225 fib->Header.XferState |= xferstate; 1226 fib->Header.Command = command; 1227 fib->Header.StructType = AAC_FIBTYPE_TFIB; 1228 fib->Header.Size = sizeof(struct aac_fib) + datasize; 1229 fib->Header.SenderSize = sizeof(struct aac_fib); 1230 fib->Header.SenderFibAddress = (u_int32_t)fib; 1231 fib->Header.ReceiverFibAddress = sc->aac_common_busaddr + offsetof(struct aac_common, ac_sync_fib); 1232 1233 /* 1234 * Copy in data. 1235 */ 1236 if (data != NULL) { 1237 bcopy(data, fib->data, datasize); 1238 fib->Header.XferState |= AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM; 1239 } 1240 1241 /* 1242 * Give the FIB to the controller, wait for a response. 1243 */ 1244 if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fib->Header.ReceiverFibAddress, 1245 0, 0, 0, NULL)) { 1246 debug(2, "IO error"); 1247 return(EIO); 1248 } 1249 1250 /* 1251 * Copy out the result 1252 */ 1253 if (result != NULL) { 1254 *resultsize = fib->Header.Size - sizeof(struct aac_fib_header); 1255 bcopy(fib->data, result, *resultsize); 1256 } 1257 return(0); 1258} 1259 1260/******************************************************************************** 1261 * Adapter-space FIB queue manipulation 1262 * 1263 * Note that the queue implementation here is a little funky; neither the PI or 1264 * CI will ever be zero. This behaviour is a controller feature. 1265 */ 1266static struct { 1267 int size; 1268 int notify; 1269} aac_qinfo[] = { 1270 {AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL}, 1271 {AAC_HOST_HIGH_CMD_ENTRIES, 0}, 1272 {AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY}, 1273 {AAC_ADAP_HIGH_CMD_ENTRIES, 0}, 1274 {AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL}, 1275 {AAC_HOST_HIGH_RESP_ENTRIES, 0}, 1276 {AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY}, 1277 {AAC_ADAP_HIGH_RESP_ENTRIES, 0} 1278}; 1279 1280/* 1281 * Atomically insert an entry into the nominated queue, returns 0 on success or EBUSY 1282 * if the queue is full. 1283 * 1284 * Note: it would be more efficient to defer notifying the controller in 1285 * the case where we may be inserting several entries in rapid succession, but 1286 * implementing this usefully may be difficult (it would involve a separate 1287 * queue/notify interface). 1288 */ 1289static int 1290aac_enqueue_fib(struct aac_softc *sc, int queue, u_int32_t fib_size, u_int32_t fib_addr) 1291{ 1292 u_int32_t pi, ci; 1293 int s, error; 1294 1295 debug_called(3); 1296 1297 s = splbio(); 1298 1299 /* get the producer/consumer indices */ 1300 pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]; 1301 ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]; 1302 1303 /* wrap the queue? */ 1304 if (pi >= aac_qinfo[queue].size) 1305 pi = 0; 1306 1307 /* check for queue full */ 1308 if ((pi + 1) == ci) { 1309 error = EBUSY; 1310 goto out; 1311 } 1312 1313 /* populate queue entry */ 1314 (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size; 1315 (sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr; 1316 1317 /* update producer index */ 1318 sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1; 1319 1320 /* notify the adapter if we know how */ 1321 if (aac_qinfo[queue].notify != 0) 1322 AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 1323 1324 error = 0; 1325 1326out: 1327 splx(s); 1328 return(error); 1329} 1330 1331/* 1332 * Atomically remove one entry from the nominated queue, returns 0 on success or ENOENT 1333 * if the queue is empty. 1334 */ 1335static int 1336aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size, struct aac_fib **fib_addr) 1337{ 1338 u_int32_t pi, ci; 1339 int s, error; 1340 1341 debug_called(3); 1342 1343 s = splbio(); 1344 1345 /* get the producer/consumer indices */ 1346 pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]; 1347 ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]; 1348 1349 /* check for queue empty */ 1350 if (ci == pi) { 1351 error = ENOENT; 1352 goto out; 1353 } 1354 1355 /* wrap the queue? */ 1356 if (ci >= aac_qinfo[queue].size) 1357 ci = 0; 1358 1359 /* fetch the entry */ 1360 *fib_size = (sc->aac_qentries[queue] + ci)->aq_fib_size; 1361 *fib_addr = (struct aac_fib *)(sc->aac_qentries[queue] + ci)->aq_fib_addr; 1362 1363 /* update consumer index */ 1364 sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1; 1365 1366 /* if we have made the queue un-full, notify the adapter */ 1367 if (((pi + 1) == ci) && (aac_qinfo[queue].notify != 0)) 1368 AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 1369 error = 0; 1370 1371out: 1372 splx(s); 1373 return(error); 1374} 1375 1376/******************************************************************************** 1377 * Check for commands that have been outstanding for a suspiciously long time, 1378 * and complain about them. 1379 */ 1380static void 1381aac_timeout(struct aac_softc *sc) 1382{ 1383 int s; 1384 struct aac_command *cm; 1385 time_t deadline; 1386 1387 /* simulate an interrupt to handle possibly-missed interrupts */ 1388 aac_intr(sc); 1389 1390 /* kick the I/O queue to restart it in the case of deadlock */ 1391 aac_startio(sc); 1392 1393 /* traverse the busy command list, bitch about late commands once only */ 1394 deadline = time_second - AAC_CMD_TIMEOUT; 1395 s = splbio(); 1396 TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) { 1397 if ((cm->cm_timestamp < deadline) && !(cm->cm_flags & AAC_CMD_TIMEDOUT)) { 1398 cm->cm_flags |= AAC_CMD_TIMEDOUT; 1399 device_printf(sc->aac_dev, "COMMAND TIMED OUT AFTER %d SECONDS\n", 1400 (int)(time_second - cm->cm_timestamp)); 1401 AAC_PRINT_FIB(sc, cm->cm_fib); 1402 } 1403 } 1404 splx(s); 1405 1406 /* reset the timer for next time */ 1407 timeout((timeout_t*)aac_timeout, sc, AAC_PERIODIC_INTERVAL * hz); 1408 return; 1409} 1410 1411/******************************************************************************** 1412 ******************************************************************************** 1413 Interface Function Vectors 1414 ******************************************************************************** 1415 ********************************************************************************/ 1416 1417/******************************************************************************** 1418 * Read the current firmware status word. 1419 */ 1420static int 1421aac_sa_get_fwstatus(struct aac_softc *sc) 1422{ 1423 debug_called(3); 1424 1425 return(AAC_GETREG4(sc, AAC_SA_FWSTATUS)); 1426} 1427 1428static int 1429aac_rx_get_fwstatus(struct aac_softc *sc) 1430{ 1431 debug_called(3); 1432 1433 return(AAC_GETREG4(sc, AAC_RX_FWSTATUS)); 1434} 1435 1436/******************************************************************************** 1437 * Notify the controller of a change in a given queue 1438 */ 1439 1440static void 1441aac_sa_qnotify(struct aac_softc *sc, int qbit) 1442{ 1443 debug_called(3); 1444 1445 AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit); 1446} 1447 1448static void 1449aac_rx_qnotify(struct aac_softc *sc, int qbit) 1450{ 1451 debug_called(3); 1452 1453 AAC_SETREG4(sc, AAC_RX_IDBR, qbit); 1454} 1455 1456/******************************************************************************** 1457 * Get the interrupt reason bits 1458 */ 1459static int 1460aac_sa_get_istatus(struct aac_softc *sc) 1461{ 1462 debug_called(3); 1463 1464 return(AAC_GETREG2(sc, AAC_SA_DOORBELL0)); 1465} 1466 1467static int 1468aac_rx_get_istatus(struct aac_softc *sc) 1469{ 1470 debug_called(3); 1471 1472 return(AAC_GETREG4(sc, AAC_RX_ODBR)); 1473} 1474 1475/******************************************************************************** 1476 * Clear some interrupt reason bits 1477 */ 1478static void 1479aac_sa_clear_istatus(struct aac_softc *sc, int mask) 1480{ 1481 debug_called(3); 1482 1483 AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask); 1484} 1485 1486static void 1487aac_rx_clear_istatus(struct aac_softc *sc, int mask) 1488{ 1489 debug_called(3); 1490 1491 AAC_SETREG4(sc, AAC_RX_ODBR, mask); 1492} 1493 1494/******************************************************************************** 1495 * Populate the mailbox and set the command word 1496 */ 1497static void 1498aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command, 1499 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3) 1500{ 1501 debug_called(4); 1502 1503 AAC_SETREG4(sc, AAC_SA_MAILBOX, command); 1504 AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0); 1505 AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1); 1506 AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2); 1507 AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3); 1508} 1509 1510static void 1511aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command, 1512 u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3) 1513{ 1514 debug_called(4); 1515 1516 AAC_SETREG4(sc, AAC_RX_MAILBOX, command); 1517 AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0); 1518 AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1); 1519 AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2); 1520 AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3); 1521} 1522 1523/******************************************************************************** 1524 * Fetch the immediate command status word 1525 */ 1526static int 1527aac_sa_get_mailboxstatus(struct aac_softc *sc) 1528{ 1529 debug_called(4); 1530 1531 return(AAC_GETREG4(sc, AAC_SA_MAILBOX)); 1532} 1533 1534static int 1535aac_rx_get_mailboxstatus(struct aac_softc *sc) 1536{ 1537 debug_called(4); 1538 1539 return(AAC_GETREG4(sc, AAC_RX_MAILBOX)); 1540} 1541 1542/******************************************************************************** 1543 * Set/clear interrupt masks 1544 */ 1545static void 1546aac_sa_set_interrupts(struct aac_softc *sc, int enable) 1547{ 1548 debug(2, "%sable interrupts", enable ? "en" : "dis"); 1549 1550 if (enable) { 1551 AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS); 1552 } else { 1553 AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0); 1554 } 1555} 1556 1557static void 1558aac_rx_set_interrupts(struct aac_softc *sc, int enable) 1559{ 1560 debug(2, "%sable interrupts", enable ? "en" : "dis"); 1561 1562 if (enable) { 1563 AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS); 1564 } else { 1565 AAC_SETREG4(sc, AAC_RX_OIMR, ~0); 1566 } 1567} 1568 1569/******************************************************************************** 1570 ******************************************************************************** 1571 Debugging and Diagnostics 1572 ******************************************************************************** 1573 ********************************************************************************/ 1574 1575/******************************************************************************** 1576 * Print some information about the controller. 1577 */ 1578static void 1579aac_describe_controller(struct aac_softc *sc) 1580{ 1581 u_int8_t buf[AAC_FIB_DATASIZE]; /* XXX really a bit big for the stack */ 1582 u_int16_t bufsize; 1583 struct aac_adapter_info *info; 1584 u_int8_t arg; 1585 1586 debug_called(2); 1587 1588 arg = 0; 1589 if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &buf, &bufsize)) { 1590 device_printf(sc->aac_dev, "RequestAdapterInfo failed\n"); 1591 return; 1592 } 1593 if (bufsize != sizeof(*info)) { 1594 device_printf(sc->aac_dev, "RequestAdapterInfo returned wrong data size (%d != %d)\n", 1595 bufsize, sizeof(*info)); 1596 /*return;*/ 1597 } 1598 info = (struct aac_adapter_info *)&buf[0]; 1599 1600 device_printf(sc->aac_dev, "%s %dMHz, %dMB total memory, %s (%d)\n", 1601 aac_describe_code(aac_cpu_variant, info->CpuVariant), info->ClockSpeed, 1602 info->TotalMem / (1024 * 1024), 1603 aac_describe_code(aac_battery_platform, info->batteryPlatform), info->batteryPlatform); 1604 1605 /* save the kernel revision structure for later use */ 1606 sc->aac_revision = info->KernelRevision; 1607 device_printf(sc->aac_dev, "Kernel %d.%d-%d, S/N %llx\n", 1608 info->KernelRevision.external.comp.major, 1609 info->KernelRevision.external.comp.minor, 1610 info->KernelRevision.external.comp.dash, 1611 info->SerialNumber); /* XXX how is this meant to be formatted? */ 1612} 1613 1614/******************************************************************************** 1615 * Look up a text description of a numeric error code and return a pointer to 1616 * same. 1617 */ 1618static char * 1619aac_describe_code(struct aac_code_lookup *table, u_int32_t code) 1620{ 1621 int i; 1622 1623 for (i = 0; table[i].string != NULL; i++) 1624 if (table[i].code == code) 1625 return(table[i].string); 1626 return(table[i + 1].string); 1627} 1628 1629/***************************************************************************** 1630 ***************************************************************************** 1631 Management Interface 1632 ***************************************************************************** 1633 *****************************************************************************/ 1634 1635static int 1636aac_open(dev_t dev, int flags, int fmt, struct proc *p) 1637{ 1638 struct aac_softc *sc = dev->si_drv1; 1639 1640 debug_called(2); 1641 1642 /* Check to make sure the device isn't already open */ 1643 if (sc->aac_state & AAC_STATE_OPEN) { 1644 return EBUSY; 1645 } 1646 sc->aac_state |= AAC_STATE_OPEN; 1647 1648 return 0; 1649} 1650 1651static int 1652aac_close(dev_t dev, int flags, int fmt, struct proc *p) 1653{ 1654 struct aac_softc *sc = dev->si_drv1; 1655 1656 debug_called(2); 1657 1658 /* Mark this unit as no longer open */ 1659 sc->aac_state &= ~AAC_STATE_OPEN; 1660 1661 return 0; 1662} 1663 1664static int 1665aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p) 1666{ 1667 union aac_statrequest *as = (union aac_statrequest *)arg; 1668 struct aac_softc *sc = dev->si_drv1; 1669 int error = 0; 1670#ifdef AAC_COMPAT_LINUX 1671 int i; 1672#endif 1673 1674 debug_called(2); 1675 1676 switch (cmd) { 1677 case AACIO_STATS: 1678 switch (as->as_item) { 1679 case AACQ_FREE: 1680 case AACQ_BIO: 1681 case AACQ_READY: 1682 case AACQ_BUSY: 1683 case AACQ_COMPLETE: 1684 bcopy(&sc->aac_qstat[as->as_item], &as->as_qstat, sizeof(struct aac_qstat)); 1685 break; 1686 default: 1687 error = ENOENT; 1688 break; 1689 } 1690 break; 1691 1692#ifdef AAC_COMPAT_LINUX 1693 case FSACTL_SENDFIB: 1694 debug(1, "FSACTL_SENDFIB"); 1695 error = aac_ioctl_sendfib(sc, arg); 1696 break; 1697 case FSACTL_AIF_THREAD: 1698 debug(1, "FSACTL_AIF_THREAD"); 1699 error = EINVAL; 1700 break; 1701 case FSACTL_OPEN_GET_ADAPTER_FIB: 1702 debug(1, "FSACTL_OPEN_GET_ADAPTER_FIB"); 1703 /* 1704 * Pass the caller out an AdapterFibContext. 1705 * 1706 * Note that because we only support one opener, we 1707 * basically ignore this. Set the caller's context to a magic 1708 * number just in case. 1709 * 1710 * The Linux code hands the driver a pointer into kernel space, 1711 * and then trusts it when the caller hands it back. Aiee! 1712 */ 1713 i = AAC_AIF_SILLYMAGIC; 1714 error = copyout(&i, arg, sizeof(i)); 1715 break; 1716 case FSACTL_GET_NEXT_ADAPTER_FIB: 1717 debug(1, "FSACTL_GET_NEXT_ADAPTER_FIB"); 1718 error = aac_linux_getnext_aif(sc, arg); 1719 break; 1720 case FSACTL_CLOSE_GET_ADAPTER_FIB: 1721 debug(1, "FSACTL_CLOSE_GET_ADAPTER_FIB"); 1722 /* don't do anything here */ 1723 break; 1724 case FSACTL_MINIPORT_REV_CHECK: 1725 debug(1, "FSACTL_MINIPORT_REV_CHECK"); 1726 error = aac_linux_rev_check(sc, arg); 1727 break; 1728#endif 1729 default: 1730 device_printf(sc->aac_dev, "unsupported cmd 0x%lx\n", cmd); 1731 error = EINVAL; 1732 break; 1733 } 1734 return(error); 1735} 1736 1737/******************************************************************************** 1738 * Send a FIB supplied from userspace 1739 */ 1740static int 1741aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib) 1742{ 1743 struct aac_command *cm; 1744 int size, error; 1745 1746 debug_called(2); 1747 1748 cm = NULL; 1749 1750 /* 1751 * Get a command 1752 */ 1753 if (aac_alloc_command(sc, &cm)) { 1754 error = EBUSY; 1755 goto out; 1756 } 1757 1758 /* 1759 * Fetch the FIB header, then re-copy to get data as well. 1760 */ 1761 if ((error = copyin(ufib, cm->cm_fib, sizeof(struct aac_fib_header))) != 0) 1762 goto out; 1763 size = cm->cm_fib->Header.Size + sizeof(struct aac_fib_header); 1764 if (size > sizeof(struct aac_fib)) { 1765 device_printf(sc->aac_dev, "incoming FIB oversized (%d > %d)\n", size, sizeof(struct aac_fib)); 1766 size = sizeof(struct aac_fib); 1767 } 1768 if ((error = copyin(ufib, cm->cm_fib, size)) != 0) 1769 goto out; 1770 cm->cm_fib->Header.Size = size; 1771 1772 /* 1773 * Pass the FIB to the controller, wait for it to complete. 1774 */ 1775 if ((error = aac_wait_command(cm, 30)) != 0) /* XXX user timeout? */ 1776 goto out; 1777 1778 /* 1779 * Copy the FIB and data back out to the caller. 1780 */ 1781 size = cm->cm_fib->Header.Size; 1782 if (size > sizeof(struct aac_fib)) { 1783 device_printf(sc->aac_dev, "outbound FIB oversized (%d > %d)\n", size, sizeof(struct aac_fib)); 1784 size = sizeof(struct aac_fib); 1785 } 1786 error = copyout(cm->cm_fib, ufib, size); 1787 1788out: 1789 if (cm != NULL) 1790 aac_release_command(cm); 1791 return(error); 1792} 1793 1794/******************************************************************************** 1795 * Handle an AIF sent to us by the controller; queue it for later reference. 1796 * 1797 * XXX what's the right thing to do here when the queue is full? Drop the older 1798 * or newer entries? 1799 */ 1800static void 1801aac_handle_aif(struct aac_softc *sc, struct aac_aif_command *aif) 1802{ 1803 int next, s; 1804 1805 debug_called(2); 1806 1807 s = splbio(); 1808 next = (sc->aac_aifq_head + 1) % AAC_AIFQ_LENGTH; 1809 if (next != sc->aac_aifq_tail) { 1810 bcopy(aif, &sc->aac_aifq[next], sizeof(struct aac_aif_command)); 1811 sc->aac_aifq_head = next; 1812 if (sc->aac_state & AAC_STATE_AIF_SLEEPER) 1813 wakeup(sc->aac_aifq); 1814 } 1815 splx(s); 1816 aac_print_aif(sc, aif); 1817} 1818 1819/******************************************************************************** 1820 ******************************************************************************** 1821 Linux Management Interface 1822 ******************************************************************************** 1823 ********************************************************************************/ 1824 1825#ifdef AAC_COMPAT_LINUX 1826 1827#include <sys/proc.h> 1828#include <machine/../linux/linux.h> 1829#include <machine/../linux/linux_proto.h> 1830#include <compat/linux/linux_ioctl.h> 1831 1832#define AAC_LINUX_IOCTL_MIN 0x2000 1833#define AAC_LINUX_IOCTL_MAX 0x21ff 1834 1835static linux_ioctl_function_t aac_linux_ioctl; 1836static struct linux_ioctl_handler aac_handler = {aac_linux_ioctl, AAC_LINUX_IOCTL_MIN, AAC_LINUX_IOCTL_MAX}; 1837 1838SYSINIT (aac_register, SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_register_handler, &aac_handler); 1839SYSUNINIT(aac_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE, linux_ioctl_unregister_handler, &aac_handler); 1840 1841MODULE_DEPEND(aac, linux, 1, 1, 1); 1842 1843static int 1844aac_linux_ioctl(struct proc *p, struct linux_ioctl_args *args) 1845{ 1846 struct file *fp = p->p_fd->fd_ofiles[args->fd]; 1847 u_long cmd = args->cmd; 1848 1849 /* 1850 * Pass the ioctl off to our standard handler. 1851 */ 1852 return(fo_ioctl(fp, cmd, (caddr_t)args->arg, p)); 1853} 1854 1855/******************************************************************************** 1856 * Return the Revision of the driver to userspace and check to see if the 1857 * userspace app is possibly compatible. This is extremely bogus right now 1858 * because I have no idea how to handle the versioning of this driver. It is 1859 * needed, though, to get aaccli working. 1860 */ 1861static int 1862aac_linux_rev_check(struct aac_softc *sc, caddr_t udata) 1863{ 1864 struct aac_rev_check rev_check; 1865 struct aac_rev_check_resp rev_check_resp; 1866 int error = 0; 1867 1868 debug_called(2); 1869 1870 /* 1871 * Copyin the revision struct from userspace 1872 */ 1873 if ((error = copyin(udata, (caddr_t)&rev_check, sizeof(struct aac_rev_check))) != 0) { 1874 return error; 1875 } 1876 1877 debug(2, "Userland revision= %d\n", rev_check.callingRevision.buildNumber); 1878 1879 /* 1880 * Doctor up the response struct. 1881 */ 1882 rev_check_resp.possiblyCompatible = 1; 1883 rev_check_resp.adapterSWRevision.external.ul = sc->aac_revision.external.ul; 1884 rev_check_resp.adapterSWRevision.buildNumber = sc->aac_revision.buildNumber; 1885 1886 return(copyout((caddr_t)&rev_check_resp, udata, sizeof(struct aac_rev_check_resp))); 1887} 1888 1889/******************************************************************************** 1890 * Pass the caller the next AIF in their queue 1891 */ 1892static int 1893aac_linux_getnext_aif(struct aac_softc *sc, caddr_t arg) 1894{ 1895 struct get_adapter_fib_ioctl agf; 1896 int error, s; 1897 1898 debug_called(2); 1899 1900 if ((error = copyin(arg, &agf, sizeof(agf))) == 0) { 1901 1902 /* 1903 * Check the magic number that we gave the caller. 1904 */ 1905 if (agf.AdapterFibContext != AAC_AIF_SILLYMAGIC) { 1906 error = EFAULT; 1907 } else { 1908 1909 s = splbio(); 1910 error = aac_linux_return_aif(sc, agf.AifFib); 1911 1912 if ((error == EAGAIN) && (agf.Wait)) { 1913 sc->aac_state |= AAC_STATE_AIF_SLEEPER; 1914 while (error == EAGAIN) { 1915 error = tsleep(sc->aac_aifq, PRIBIO | PCATCH, "aacaif", 0); 1916 if (error == 0) 1917 error = aac_linux_return_aif(sc, agf.AifFib); 1918 } 1919 sc->aac_state &= ~AAC_STATE_AIF_SLEEPER; 1920 } 1921 splx(s); 1922 } 1923 } 1924 return(error); 1925} 1926 1927/******************************************************************************** 1928 * Hand the next AIF off the top of the queue out to userspace. 1929 */ 1930static int 1931aac_linux_return_aif(struct aac_softc *sc, caddr_t uptr) 1932{ 1933 int error, s; 1934 1935 debug_called(2); 1936 1937 s = splbio(); 1938 if (sc->aac_aifq_tail == sc->aac_aifq_head) { 1939 error = EAGAIN; 1940 } else { 1941 error = copyout(&sc->aac_aifq[sc->aac_aifq_tail], uptr, sizeof(struct aac_aif_command)); 1942 if (!error) 1943 sc->aac_aifq_tail = (sc->aac_aifq_tail + 1) % AAC_AIFQ_LENGTH; 1944 } 1945 splx(s); 1946 return(error); 1947} 1948 1949 1950#endif /* AAC_COMPAT_LINUX */ 1951