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