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