aac.c revision 177462
1169689Skan/*- 2169689Skan * Copyright (c) 2000 Michael Smith 3169689Skan * Copyright (c) 2001 Scott Long 4169689Skan * Copyright (c) 2000 BSDi 5169689Skan * Copyright (c) 2001 Adaptec, Inc. 6169689Skan * All rights reserved. 7169689Skan * 8169689Skan * Redistribution and use in source and binary forms, with or without 9169689Skan * modification, are permitted provided that the following conditions 10169689Skan * are met: 11169689Skan * 1. Redistributions of source code must retain the above copyright 12169689Skan * notice, this list of conditions and the following disclaimer. 13169689Skan * 2. Redistributions in binary form must reproduce the above copyright 14169689Skan * notice, this list of conditions and the following disclaimer in the 15169689Skan * documentation and/or other materials provided with the distribution. 16169689Skan * 17169689Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18169689Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20169689Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27169689Skan * SUCH DAMAGE. 28169689Skan */ 29169689Skan 30169689Skan#include <sys/cdefs.h> 31169689Skan__FBSDID("$FreeBSD: head/sys/dev/aac/aac.c 177462 2008-03-20 17:59:19Z emaste $"); 32169689Skan 33169689Skan/* 34169689Skan * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters. 35169689Skan */ 36169689Skan#define AAC_DRIVER_VERSION 0x02000000 37169689Skan#define AAC_DRIVERNAME "aac" 38169689Skan 39169689Skan#include "opt_aac.h" 40169689Skan 41169689Skan/* #include <stddef.h> */ 42169689Skan#include <sys/param.h> 43169689Skan#include <sys/systm.h> 44169689Skan#include <sys/malloc.h> 45169689Skan#include <sys/kernel.h> 46169689Skan#include <sys/kthread.h> 47169689Skan#include <sys/sysctl.h> 48169689Skan#include <sys/poll.h> 49169689Skan#include <sys/ioccom.h> 50169689Skan 51169689Skan#include <sys/bus.h> 52169689Skan#include <sys/conf.h> 53169689Skan#include <sys/signalvar.h> 54169689Skan#include <sys/time.h> 55169689Skan#include <sys/eventhandler.h> 56169689Skan#include <sys/rman.h> 57169689Skan 58169689Skan#include <machine/bus.h> 59169689Skan#include <sys/bus_dma.h> 60169689Skan#include <machine/resource.h> 61169689Skan 62169689Skan#include <dev/pci/pcireg.h> 63169689Skan#include <dev/pci/pcivar.h> 64169689Skan 65169689Skan#include <dev/aac/aacreg.h> 66169689Skan#include <sys/aac_ioctl.h> 67169689Skan#include <dev/aac/aacvar.h> 68169689Skan#include <dev/aac/aac_tables.h> 69169689Skan 70169689Skanstatic void aac_startup(void *arg); 71169689Skanstatic void aac_add_container(struct aac_softc *sc, 72169689Skan struct aac_mntinforesp *mir, int f); 73169689Skanstatic void aac_get_bus_info(struct aac_softc *sc); 74169689Skan 75169689Skan/* Command Processing */ 76169689Skanstatic void aac_timeout(struct aac_softc *sc); 77169689Skanstatic void aac_complete(void *context, int pending); 78169689Skanstatic int aac_bio_command(struct aac_softc *sc, struct aac_command **cmp); 79169689Skanstatic void aac_bio_complete(struct aac_command *cm); 80169689Skanstatic int aac_wait_command(struct aac_command *cm); 81169689Skanstatic void aac_command_thread(struct aac_softc *sc); 82169689Skan 83169689Skan/* Command Buffer Management */ 84169689Skanstatic void aac_map_command_sg(void *arg, bus_dma_segment_t *segs, 85169689Skan int nseg, int error); 86169689Skanstatic void aac_map_command_helper(void *arg, bus_dma_segment_t *segs, 87169689Skan int nseg, int error); 88169689Skanstatic int aac_alloc_commands(struct aac_softc *sc); 89169689Skanstatic void aac_free_commands(struct aac_softc *sc); 90169689Skanstatic void aac_unmap_command(struct aac_command *cm); 91169689Skan 92169689Skan/* Hardware Interface */ 93169689Skanstatic void aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, 94169689Skan int error); 95169689Skanstatic int aac_check_firmware(struct aac_softc *sc); 96169689Skanstatic int aac_init(struct aac_softc *sc); 97169689Skanstatic int aac_sync_command(struct aac_softc *sc, u_int32_t command, 98169689Skan u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, 99169689Skan u_int32_t arg3, u_int32_t *sp); 100169689Skanstatic int aac_enqueue_fib(struct aac_softc *sc, int queue, 101169689Skan struct aac_command *cm); 102169689Skanstatic int aac_dequeue_fib(struct aac_softc *sc, int queue, 103169689Skan u_int32_t *fib_size, struct aac_fib **fib_addr); 104169689Skanstatic int aac_enqueue_response(struct aac_softc *sc, int queue, 105169689Skan struct aac_fib *fib); 106169689Skan 107169689Skan/* Falcon/PPC interface */ 108169689Skanstatic int aac_fa_get_fwstatus(struct aac_softc *sc); 109169689Skanstatic void aac_fa_qnotify(struct aac_softc *sc, int qbit); 110169689Skanstatic int aac_fa_get_istatus(struct aac_softc *sc); 111169689Skanstatic void aac_fa_clear_istatus(struct aac_softc *sc, int mask); 112169689Skanstatic void aac_fa_set_mailbox(struct aac_softc *sc, u_int32_t command, 113169689Skan u_int32_t arg0, u_int32_t arg1, 114169689Skan u_int32_t arg2, u_int32_t arg3); 115169689Skanstatic int aac_fa_get_mailbox(struct aac_softc *sc, int mb); 116169689Skanstatic void aac_fa_set_interrupts(struct aac_softc *sc, int enable); 117169689Skan 118169689Skanstruct aac_interface aac_fa_interface = { 119169689Skan aac_fa_get_fwstatus, 120169689Skan aac_fa_qnotify, 121169689Skan aac_fa_get_istatus, 122169689Skan aac_fa_clear_istatus, 123169689Skan aac_fa_set_mailbox, 124169689Skan aac_fa_get_mailbox, 125169689Skan aac_fa_set_interrupts, 126169689Skan NULL, NULL, NULL 127169689Skan}; 128169689Skan 129169689Skan/* StrongARM interface */ 130169689Skanstatic int aac_sa_get_fwstatus(struct aac_softc *sc); 131169689Skanstatic void aac_sa_qnotify(struct aac_softc *sc, int qbit); 132169689Skanstatic int aac_sa_get_istatus(struct aac_softc *sc); 133169689Skanstatic void aac_sa_clear_istatus(struct aac_softc *sc, int mask); 134169689Skanstatic void aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command, 135169689Skan u_int32_t arg0, u_int32_t arg1, 136169689Skan u_int32_t arg2, u_int32_t arg3); 137169689Skanstatic int aac_sa_get_mailbox(struct aac_softc *sc, int mb); 138169689Skanstatic void aac_sa_set_interrupts(struct aac_softc *sc, int enable); 139169689Skan 140169689Skanstruct aac_interface aac_sa_interface = { 141169689Skan aac_sa_get_fwstatus, 142169689Skan aac_sa_qnotify, 143169689Skan aac_sa_get_istatus, 144169689Skan aac_sa_clear_istatus, 145169689Skan aac_sa_set_mailbox, 146169689Skan aac_sa_get_mailbox, 147169689Skan aac_sa_set_interrupts, 148169689Skan NULL, NULL, NULL 149169689Skan}; 150169689Skan 151169689Skan/* i960Rx interface */ 152169689Skanstatic int aac_rx_get_fwstatus(struct aac_softc *sc); 153169689Skanstatic void aac_rx_qnotify(struct aac_softc *sc, int qbit); 154169689Skanstatic int aac_rx_get_istatus(struct aac_softc *sc); 155169689Skanstatic void aac_rx_clear_istatus(struct aac_softc *sc, int mask); 156169689Skanstatic void aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command, 157169689Skan u_int32_t arg0, u_int32_t arg1, 158169689Skan u_int32_t arg2, u_int32_t arg3); 159169689Skanstatic int aac_rx_get_mailbox(struct aac_softc *sc, int mb); 160169689Skanstatic void aac_rx_set_interrupts(struct aac_softc *sc, int enable); 161169689Skanstatic int aac_rx_send_command(struct aac_softc *sc, struct aac_command *cm); 162169689Skanstatic int aac_rx_get_outb_queue(struct aac_softc *sc); 163169689Skanstatic void aac_rx_set_outb_queue(struct aac_softc *sc, int index); 164169689Skan 165169689Skanstruct aac_interface aac_rx_interface = { 166169689Skan aac_rx_get_fwstatus, 167169689Skan aac_rx_qnotify, 168169689Skan aac_rx_get_istatus, 169169689Skan aac_rx_clear_istatus, 170169689Skan aac_rx_set_mailbox, 171169689Skan aac_rx_get_mailbox, 172169689Skan aac_rx_set_interrupts, 173169689Skan aac_rx_send_command, 174169689Skan aac_rx_get_outb_queue, 175169689Skan aac_rx_set_outb_queue 176169689Skan}; 177169689Skan 178169689Skan/* Rocket/MIPS interface */ 179169689Skanstatic int aac_rkt_get_fwstatus(struct aac_softc *sc); 180169689Skanstatic void aac_rkt_qnotify(struct aac_softc *sc, int qbit); 181169689Skanstatic int aac_rkt_get_istatus(struct aac_softc *sc); 182169689Skanstatic void aac_rkt_clear_istatus(struct aac_softc *sc, int mask); 183169689Skanstatic void aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command, 184169689Skan u_int32_t arg0, u_int32_t arg1, 185169689Skan u_int32_t arg2, u_int32_t arg3); 186169689Skanstatic int aac_rkt_get_mailbox(struct aac_softc *sc, int mb); 187169689Skanstatic void aac_rkt_set_interrupts(struct aac_softc *sc, int enable); 188169689Skanstatic int aac_rkt_send_command(struct aac_softc *sc, struct aac_command *cm); 189169689Skanstatic int aac_rkt_get_outb_queue(struct aac_softc *sc); 190169689Skanstatic void aac_rkt_set_outb_queue(struct aac_softc *sc, int index); 191169689Skan 192169689Skanstruct aac_interface aac_rkt_interface = { 193169689Skan aac_rkt_get_fwstatus, 194169689Skan aac_rkt_qnotify, 195169689Skan aac_rkt_get_istatus, 196169689Skan aac_rkt_clear_istatus, 197169689Skan aac_rkt_set_mailbox, 198169689Skan aac_rkt_get_mailbox, 199169689Skan aac_rkt_set_interrupts, 200169689Skan aac_rkt_send_command, 201169689Skan aac_rkt_get_outb_queue, 202169689Skan aac_rkt_set_outb_queue 203169689Skan}; 204169689Skan 205169689Skan/* Debugging and Diagnostics */ 206169689Skanstatic void aac_describe_controller(struct aac_softc *sc); 207169689Skanstatic char *aac_describe_code(struct aac_code_lookup *table, 208169689Skan u_int32_t code); 209169689Skan 210169689Skan/* Management Interface */ 211169689Skanstatic d_open_t aac_open; 212169689Skanstatic d_close_t aac_close; 213169689Skanstatic d_ioctl_t aac_ioctl; 214169689Skanstatic d_poll_t aac_poll; 215169689Skanstatic int aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib); 216169689Skanstatic int aac_ioctl_send_raw_srb(struct aac_softc *sc, caddr_t arg); 217169689Skanstatic void aac_handle_aif(struct aac_softc *sc, 218169689Skan struct aac_fib *fib); 219169689Skanstatic int aac_rev_check(struct aac_softc *sc, caddr_t udata); 220169689Skanstatic int aac_open_aif(struct aac_softc *sc, caddr_t arg); 221169689Skanstatic int aac_close_aif(struct aac_softc *sc, caddr_t arg); 222169689Skanstatic int aac_getnext_aif(struct aac_softc *sc, caddr_t arg); 223169689Skanstatic int aac_return_aif(struct aac_softc *sc, 224169689Skan struct aac_fib_context *ctx, caddr_t uptr); 225169689Skanstatic int aac_query_disk(struct aac_softc *sc, caddr_t uptr); 226169689Skanstatic int aac_get_pci_info(struct aac_softc *sc, caddr_t uptr); 227169689Skanstatic void aac_ioctl_event(struct aac_softc *sc, 228169689Skan struct aac_event *event, void *arg); 229169689Skan 230169689Skanstatic struct cdevsw aac_cdevsw = { 231169689Skan .d_version = D_VERSION, 232169689Skan .d_flags = D_NEEDGIANT, 233169689Skan .d_open = aac_open, 234169689Skan .d_close = aac_close, 235169689Skan .d_ioctl = aac_ioctl, 236169689Skan .d_poll = aac_poll, 237169689Skan .d_name = "aac", 238169689Skan}; 239169689Skan 240169689SkanMALLOC_DEFINE(M_AACBUF, "aacbuf", "Buffers for the AAC driver"); 241169689Skan 242169689Skan/* sysctl node */ 243169689SkanSYSCTL_NODE(_hw, OID_AUTO, aac, CTLFLAG_RD, 0, "AAC driver parameters"); 244169689Skan 245169689Skan/* 246169689Skan * Device Interface 247169689Skan */ 248169689Skan 249169689Skan/* 250169689Skan * Initialize the controller and softc 251169689Skan */ 252169689Skanint 253169689Skanaac_attach(struct aac_softc *sc) 254169689Skan{ 255169689Skan int error, unit; 256169689Skan 257169689Skan debug_called(1); 258169689Skan 259169689Skan /* 260169689Skan * Initialize per-controller queues. 261169689Skan */ 262169689Skan aac_initq_free(sc); 263169689Skan aac_initq_ready(sc); 264169689Skan aac_initq_busy(sc); 265169689Skan aac_initq_bio(sc); 266169689Skan 267169689Skan /* 268169689Skan * Initialize command-completion task. 269169689Skan */ 270169689Skan TASK_INIT(&sc->aac_task_complete, 0, aac_complete, sc); 271169689Skan 272169689Skan /* mark controller as suspended until we get ourselves organised */ 273169689Skan sc->aac_state |= AAC_STATE_SUSPEND; 274169689Skan 275169689Skan /* 276169689Skan * Check that the firmware on the card is supported. 277169689Skan */ 278169689Skan if ((error = aac_check_firmware(sc)) != 0) 279169689Skan return(error); 280169689Skan 281169689Skan /* 282169689Skan * Initialize locks 283169689Skan */ 284169689Skan mtx_init(&sc->aac_aifq_lock, "AAC AIF lock", NULL, MTX_DEF); 285169689Skan mtx_init(&sc->aac_io_lock, "AAC I/O lock", NULL, MTX_DEF); 286169689Skan mtx_init(&sc->aac_container_lock, "AAC container lock", NULL, MTX_DEF); 287169689Skan TAILQ_INIT(&sc->aac_container_tqh); 288169689Skan TAILQ_INIT(&sc->aac_ev_cmfree); 289169689Skan 290169689Skan /* 291169689Skan * Initialize the adapter. 292169689Skan */ 293169689Skan if ((error = aac_init(sc)) != 0) 294169689Skan return(error); 295169689Skan 296169689Skan /* 297169689Skan * Allocate and connect our interrupt. 298169689Skan */ 299169689Skan sc->aac_irq_rid = 0; 300169689Skan if ((sc->aac_irq = bus_alloc_resource_any(sc->aac_dev, SYS_RES_IRQ, 301169689Skan &sc->aac_irq_rid, 302169689Skan RF_SHAREABLE | 303169689Skan RF_ACTIVE)) == NULL) { 304169689Skan device_printf(sc->aac_dev, "can't allocate interrupt\n"); 305169689Skan return (EINVAL); 306169689Skan } 307169689Skan if (sc->flags & AAC_FLAGS_NEW_COMM) { 308169689Skan if (bus_setup_intr(sc->aac_dev, sc->aac_irq, 309169689Skan INTR_MPSAFE|INTR_TYPE_BIO, NULL, 310169689Skan aac_new_intr, sc, &sc->aac_intr)) { 311169689Skan device_printf(sc->aac_dev, "can't set up interrupt\n"); 312169689Skan return (EINVAL); 313169689Skan } 314169689Skan } else { 315169689Skan if (bus_setup_intr(sc->aac_dev, sc->aac_irq, 316169689Skan INTR_TYPE_BIO, aac_fast_intr, NULL, 317169689Skan sc, &sc->aac_intr)) { 318169689Skan device_printf(sc->aac_dev, 319169689Skan "can't set up FAST interrupt\n"); 320169689Skan if (bus_setup_intr(sc->aac_dev, sc->aac_irq, 321169689Skan INTR_MPSAFE|INTR_TYPE_BIO, 322169689Skan NULL, (driver_intr_t *)aac_fast_intr, 323169689Skan sc, &sc->aac_intr)) { 324169689Skan device_printf(sc->aac_dev, 325169689Skan "can't set up MPSAFE interrupt\n"); 326169689Skan return (EINVAL); 327169689Skan } 328169689Skan } 329169689Skan } 330169689Skan 331169689Skan /* 332169689Skan * Print a little information about the controller. 333169689Skan */ 334169689Skan aac_describe_controller(sc); 335169689Skan 336169689Skan /* 337169689Skan * Register to probe our containers later. 338169689Skan */ 339169689Skan sc->aac_ich.ich_func = aac_startup; 340169689Skan sc->aac_ich.ich_arg = sc; 341169689Skan if (config_intrhook_establish(&sc->aac_ich) != 0) { 342169689Skan device_printf(sc->aac_dev, 343169689Skan "can't establish configuration hook\n"); 344169689Skan return(ENXIO); 345169689Skan } 346169689Skan 347169689Skan /* 348169689Skan * Make the control device. 349169689Skan */ 350169689Skan unit = device_get_unit(sc->aac_dev); 351169689Skan sc->aac_dev_t = make_dev(&aac_cdevsw, unit, UID_ROOT, GID_OPERATOR, 352169689Skan 0640, "aac%d", unit); 353169689Skan (void)make_dev_alias(sc->aac_dev_t, "afa%d", unit); 354169689Skan (void)make_dev_alias(sc->aac_dev_t, "hpn%d", unit); 355169689Skan sc->aac_dev_t->si_drv1 = sc; 356169689Skan 357169689Skan /* Create the AIF thread */ 358169689Skan if (kproc_create((void(*)(void *))aac_command_thread, sc, 359169689Skan &sc->aifthread, 0, 0, "aac%daif", unit)) 360169689Skan panic("Could not create AIF thread\n"); 361169689Skan 362169689Skan /* Register the shutdown method to only be called post-dump */ 363169689Skan if ((sc->eh = EVENTHANDLER_REGISTER(shutdown_final, aac_shutdown, 364169689Skan sc->aac_dev, SHUTDOWN_PRI_DEFAULT)) == NULL) 365169689Skan device_printf(sc->aac_dev, 366169689Skan "shutdown event registration failed\n"); 367169689Skan 368169689Skan /* Register with CAM for the non-DASD devices */ 369169689Skan if ((sc->flags & AAC_FLAGS_ENABLE_CAM) != 0) { 370169689Skan TAILQ_INIT(&sc->aac_sim_tqh); 371169689Skan aac_get_bus_info(sc); 372169689Skan } 373169689Skan 374169689Skan return(0); 375169689Skan} 376169689Skan 377169689Skanvoid 378169689Skanaac_add_event(struct aac_softc *sc, struct aac_event *event) 379169689Skan{ 380169689Skan 381169689Skan switch (event->ev_type & AAC_EVENT_MASK) { 382169689Skan case AAC_EVENT_CMFREE: 383169689Skan TAILQ_INSERT_TAIL(&sc->aac_ev_cmfree, event, ev_links); 384169689Skan break; 385169689Skan default: 386169689Skan device_printf(sc->aac_dev, "aac_add event: unknown event %d\n", 387169689Skan event->ev_type); 388169689Skan break; 389169689Skan } 390169689Skan 391169689Skan return; 392169689Skan} 393169689Skan 394169689Skan/* 395169689Skan * Probe for containers, create disks. 396169689Skan */ 397169689Skanstatic void 398169689Skanaac_startup(void *arg) 399169689Skan{ 400169689Skan struct aac_softc *sc; 401169689Skan struct aac_fib *fib; 402169689Skan struct aac_mntinfo *mi; 403169689Skan struct aac_mntinforesp *mir = NULL; 404169689Skan int count = 0, i = 0; 405169689Skan 406169689Skan debug_called(1); 407169689Skan 408169689Skan sc = (struct aac_softc *)arg; 409169689Skan 410169689Skan /* disconnect ourselves from the intrhook chain */ 411169689Skan config_intrhook_disestablish(&sc->aac_ich); 412169689Skan 413169689Skan mtx_lock(&sc->aac_io_lock); 414169689Skan aac_alloc_sync_fib(sc, &fib); 415169689Skan mi = (struct aac_mntinfo *)&fib->data[0]; 416169689Skan 417169689Skan /* loop over possible containers */ 418169689Skan do { 419169689Skan /* request information on this container */ 420169689Skan bzero(mi, sizeof(struct aac_mntinfo)); 421169689Skan mi->Command = VM_NameServe; 422169689Skan mi->MntType = FT_FILESYS; 423169689Skan mi->MntCount = i; 424169689Skan if (aac_sync_fib(sc, ContainerCommand, 0, fib, 425169689Skan sizeof(struct aac_mntinfo))) { 426169689Skan printf("error probing container %d", i); 427169689Skan continue; 428169689Skan } 429169689Skan 430169689Skan mir = (struct aac_mntinforesp *)&fib->data[0]; 431169689Skan /* XXX Need to check if count changed */ 432169689Skan count = mir->MntRespCount; 433169689Skan aac_add_container(sc, mir, 0); 434169689Skan i++; 435169689Skan } while ((i < count) && (i < AAC_MAX_CONTAINERS)); 436169689Skan 437169689Skan aac_release_sync_fib(sc); 438169689Skan mtx_unlock(&sc->aac_io_lock); 439169689Skan 440169689Skan /* poke the bus to actually attach the child devices */ 441169689Skan if (bus_generic_attach(sc->aac_dev)) 442169689Skan device_printf(sc->aac_dev, "bus_generic_attach failed\n"); 443169689Skan 444169689Skan /* mark the controller up */ 445169689Skan sc->aac_state &= ~AAC_STATE_SUSPEND; 446169689Skan 447169689Skan /* enable interrupts now */ 448169689Skan AAC_UNMASK_INTERRUPTS(sc); 449169689Skan} 450169689Skan 451169689Skan/* 452169689Skan * Create a device to represent a new container 453169689Skan */ 454169689Skanstatic void 455169689Skanaac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f) 456169689Skan{ 457169689Skan struct aac_container *co; 458169689Skan device_t child; 459169689Skan 460169689Skan /* 461169689Skan * Check container volume type for validity. Note that many of 462169689Skan * the possible types may never show up. 463169689Skan */ 464169689Skan if ((mir->Status == ST_OK) && (mir->MntTable[0].VolType != CT_NONE)) { 465169689Skan co = (struct aac_container *)malloc(sizeof *co, M_AACBUF, 466169689Skan M_NOWAIT | M_ZERO); 467169689Skan if (co == NULL) 468169689Skan panic("Out of memory?!\n"); 469169689Skan debug(1, "id %x name '%.16s' size %u type %d", 470169689Skan mir->MntTable[0].ObjectId, 471169689Skan mir->MntTable[0].FileSystemName, 472169689Skan mir->MntTable[0].Capacity, mir->MntTable[0].VolType); 473169689Skan 474169689Skan if ((child = device_add_child(sc->aac_dev, "aacd", -1)) == NULL) 475169689Skan device_printf(sc->aac_dev, "device_add_child failed\n"); 476169689Skan else 477169689Skan device_set_ivars(child, co); 478169689Skan device_set_desc(child, aac_describe_code(aac_container_types, 479169689Skan mir->MntTable[0].VolType)); 480169689Skan co->co_disk = child; 481169689Skan co->co_found = f; 482169689Skan bcopy(&mir->MntTable[0], &co->co_mntobj, 483169689Skan sizeof(struct aac_mntobj)); 484169689Skan mtx_lock(&sc->aac_container_lock); 485169689Skan TAILQ_INSERT_TAIL(&sc->aac_container_tqh, co, co_link); 486169689Skan mtx_unlock(&sc->aac_container_lock); 487169689Skan } 488169689Skan} 489169689Skan 490169689Skan/* 491169689Skan * Free all of the resources associated with (sc) 492169689Skan * 493169689Skan * Should not be called if the controller is active. 494169689Skan */ 495169689Skanvoid 496169689Skanaac_free(struct aac_softc *sc) 497169689Skan{ 498169689Skan 499169689Skan debug_called(1); 500169689Skan 501169689Skan /* remove the control device */ 502169689Skan if (sc->aac_dev_t != NULL) 503169689Skan destroy_dev(sc->aac_dev_t); 504169689Skan 505169689Skan /* throw away any FIB buffers, discard the FIB DMA tag */ 506169689Skan aac_free_commands(sc); 507169689Skan if (sc->aac_fib_dmat) 508169689Skan bus_dma_tag_destroy(sc->aac_fib_dmat); 509169689Skan 510169689Skan free(sc->aac_commands, M_AACBUF); 511169689Skan 512169689Skan /* destroy the common area */ 513169689Skan if (sc->aac_common) { 514169689Skan bus_dmamap_unload(sc->aac_common_dmat, sc->aac_common_dmamap); 515169689Skan bus_dmamem_free(sc->aac_common_dmat, sc->aac_common, 516169689Skan sc->aac_common_dmamap); 517169689Skan } 518169689Skan if (sc->aac_common_dmat) 519169689Skan bus_dma_tag_destroy(sc->aac_common_dmat); 520169689Skan 521169689Skan /* disconnect the interrupt handler */ 522169689Skan if (sc->aac_intr) 523169689Skan bus_teardown_intr(sc->aac_dev, sc->aac_irq, sc->aac_intr); 524169689Skan if (sc->aac_irq != NULL) 525169689Skan bus_release_resource(sc->aac_dev, SYS_RES_IRQ, sc->aac_irq_rid, 526169689Skan sc->aac_irq); 527169689Skan 528169689Skan /* destroy data-transfer DMA tag */ 529169689Skan if (sc->aac_buffer_dmat) 530169689Skan bus_dma_tag_destroy(sc->aac_buffer_dmat); 531169689Skan 532169689Skan /* destroy the parent DMA tag */ 533169689Skan if (sc->aac_parent_dmat) 534169689Skan bus_dma_tag_destroy(sc->aac_parent_dmat); 535169689Skan 536169689Skan /* release the register window mapping */ 537169689Skan if (sc->aac_regs_resource != NULL) 538169689Skan bus_release_resource(sc->aac_dev, SYS_RES_MEMORY, 539169689Skan sc->aac_regs_rid, sc->aac_regs_resource); 540169689Skan} 541169689Skan 542169689Skan/* 543169689Skan * Disconnect from the controller completely, in preparation for unload. 544169689Skan */ 545169689Skanint 546169689Skanaac_detach(device_t dev) 547169689Skan{ 548169689Skan struct aac_softc *sc; 549169689Skan struct aac_container *co; 550169689Skan struct aac_sim *sim; 551169689Skan int error; 552169689Skan 553169689Skan debug_called(1); 554169689Skan 555169689Skan sc = device_get_softc(dev); 556169689Skan 557169689Skan if (sc->aac_state & AAC_STATE_OPEN) 558169689Skan return(EBUSY); 559169689Skan 560169689Skan /* Remove the child containers */ 561169689Skan while ((co = TAILQ_FIRST(&sc->aac_container_tqh)) != NULL) { 562169689Skan error = device_delete_child(dev, co->co_disk); 563169689Skan if (error) 564169689Skan return (error); 565169689Skan TAILQ_REMOVE(&sc->aac_container_tqh, co, co_link); 566169689Skan free(co, M_AACBUF); 567169689Skan } 568169689Skan 569169689Skan /* Remove the CAM SIMs */ 570169689Skan while ((sim = TAILQ_FIRST(&sc->aac_sim_tqh)) != NULL) { 571169689Skan TAILQ_REMOVE(&sc->aac_sim_tqh, sim, sim_link); 572169689Skan error = device_delete_child(dev, sim->sim_dev); 573169689Skan if (error) 574169689Skan return (error); 575169689Skan free(sim, M_AACBUF); 576169689Skan } 577169689Skan 578169689Skan if (sc->aifflags & AAC_AIFFLAGS_RUNNING) { 579169689Skan sc->aifflags |= AAC_AIFFLAGS_EXIT; 580169689Skan wakeup(sc->aifthread); 581169689Skan tsleep(sc->aac_dev, PUSER | PCATCH, "aacdch", 30 * hz); 582169689Skan } 583169689Skan 584169689Skan if (sc->aifflags & AAC_AIFFLAGS_RUNNING) 585169689Skan panic("Cannot shutdown AIF thread\n"); 586169689Skan 587169689Skan if ((error = aac_shutdown(dev))) 588169689Skan return(error); 589169689Skan 590169689Skan EVENTHANDLER_DEREGISTER(shutdown_final, sc->eh); 591169689Skan 592169689Skan aac_free(sc); 593169689Skan 594169689Skan mtx_destroy(&sc->aac_aifq_lock); 595169689Skan mtx_destroy(&sc->aac_io_lock); 596169689Skan mtx_destroy(&sc->aac_container_lock); 597169689Skan 598169689Skan return(0); 599169689Skan} 600169689Skan 601169689Skan/* 602169689Skan * Bring the controller down to a dormant state and detach all child devices. 603169689Skan * 604169689Skan * This function is called before detach or system shutdown. 605169689Skan * 606169689Skan * Note that we can assume that the bioq on the controller is empty, as we won't 607169689Skan * allow shutdown if any device is open. 608169689Skan */ 609169689Skanint 610169689Skanaac_shutdown(device_t dev) 611169689Skan{ 612169689Skan struct aac_softc *sc; 613169689Skan struct aac_fib *fib; 614169689Skan struct aac_close_command *cc; 615169689Skan 616169689Skan debug_called(1); 617169689Skan 618169689Skan sc = device_get_softc(dev); 619169689Skan 620169689Skan sc->aac_state |= AAC_STATE_SUSPEND; 621169689Skan 622169689Skan /* 623169689Skan * Send a Container shutdown followed by a HostShutdown FIB to the 624169689Skan * controller to convince it that we don't want to talk to it anymore. 625169689Skan * We've been closed and all I/O completed already 626169689Skan */ 627169689Skan device_printf(sc->aac_dev, "shutting down controller..."); 628169689Skan 629169689Skan mtx_lock(&sc->aac_io_lock); 630169689Skan aac_alloc_sync_fib(sc, &fib); 631169689Skan cc = (struct aac_close_command *)&fib->data[0]; 632169689Skan 633169689Skan bzero(cc, sizeof(struct aac_close_command)); 634169689Skan cc->Command = VM_CloseAll; 635169689Skan cc->ContainerId = 0xffffffff; 636169689Skan if (aac_sync_fib(sc, ContainerCommand, 0, fib, 637169689Skan sizeof(struct aac_close_command))) 638169689Skan printf("FAILED.\n"); 639169689Skan else 640169689Skan printf("done\n"); 641169689Skan#if 0 642169689Skan else { 643169689Skan fib->data[0] = 0; 644169689Skan /* 645169689Skan * XXX Issuing this command to the controller makes it shut down 646169689Skan * but also keeps it from coming back up without a reset of the 647169689Skan * PCI bus. This is not desirable if you are just unloading the 648169689Skan * driver module with the intent to reload it later. 649169689Skan */ 650169689Skan if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN, 651169689Skan fib, 1)) { 652169689Skan printf("FAILED.\n"); 653169689Skan } else { 654169689Skan printf("done.\n"); 655169689Skan } 656169689Skan } 657169689Skan#endif 658169689Skan 659169689Skan AAC_MASK_INTERRUPTS(sc); 660169689Skan aac_release_sync_fib(sc); 661169689Skan mtx_unlock(&sc->aac_io_lock); 662169689Skan 663169689Skan return(0); 664169689Skan} 665169689Skan 666169689Skan/* 667169689Skan * Bring the controller to a quiescent state, ready for system suspend. 668169689Skan */ 669169689Skanint 670169689Skanaac_suspend(device_t dev) 671169689Skan{ 672169689Skan struct aac_softc *sc; 673169689Skan 674169689Skan debug_called(1); 675169689Skan 676169689Skan sc = device_get_softc(dev); 677169689Skan 678169689Skan sc->aac_state |= AAC_STATE_SUSPEND; 679169689Skan 680169689Skan AAC_MASK_INTERRUPTS(sc); 681169689Skan return(0); 682169689Skan} 683169689Skan 684169689Skan/* 685169689Skan * Bring the controller back to a state ready for operation. 686169689Skan */ 687169689Skanint 688169689Skanaac_resume(device_t dev) 689169689Skan{ 690169689Skan struct aac_softc *sc; 691169689Skan 692169689Skan debug_called(1); 693169689Skan 694169689Skan sc = device_get_softc(dev); 695169689Skan 696169689Skan sc->aac_state &= ~AAC_STATE_SUSPEND; 697169689Skan AAC_UNMASK_INTERRUPTS(sc); 698169689Skan return(0); 699169689Skan} 700169689Skan 701169689Skan/* 702169689Skan * Interrupt handler for NEW_COMM interface. 703169689Skan */ 704169689Skanvoid 705169689Skanaac_new_intr(void *arg) 706169689Skan{ 707169689Skan struct aac_softc *sc; 708169689Skan u_int32_t index, fast; 709169689Skan struct aac_command *cm; 710169689Skan struct aac_fib *fib; 711169689Skan int i; 712169689Skan 713169689Skan debug_called(2); 714169689Skan 715169689Skan sc = (struct aac_softc *)arg; 716208737Sjmallett 717169689Skan mtx_lock(&sc->aac_io_lock); 718169689Skan while (1) { 719169689Skan index = AAC_GET_OUTB_QUEUE(sc); 720169689Skan if (index == 0xffffffff) 721169689Skan index = AAC_GET_OUTB_QUEUE(sc); 722169689Skan if (index == 0xffffffff) 723169689Skan break; 724169689Skan if (index & 2) { 725169689Skan if (index == 0xfffffffe) { 726169689Skan /* XXX This means that the controller wants 727169689Skan * more work. Ignore it for now. 728169689Skan */ 729169689Skan continue; 730169689Skan } 731169689Skan /* AIF */ 732169689Skan fib = (struct aac_fib *)malloc(sizeof *fib, M_AACBUF, 733169689Skan M_NOWAIT | M_ZERO); 734169689Skan if (fib == NULL) { 735169689Skan /* If we're really this short on memory, 736169689Skan * hopefully breaking out of the handler will 737169689Skan * allow something to get freed. This 738169689Skan * actually sucks a whole lot. 739169689Skan */ 740169689Skan break; 741169689Skan } 742169689Skan index &= ~2; 743169689Skan for (i = 0; i < sizeof(struct aac_fib)/4; ++i) 744169689Skan ((u_int32_t *)fib)[i] = AAC_GETREG4(sc, index + i*4); 745169689Skan aac_handle_aif(sc, fib); 746169689Skan free(fib, M_AACBUF); 747169689Skan 748169689Skan /* 749169689Skan * AIF memory is owned by the adapter, so let it 750169689Skan * know that we are done with it. 751169689Skan */ 752169689Skan AAC_SET_OUTB_QUEUE(sc, index); 753169689Skan AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY); 754169689Skan } else { 755169689Skan fast = index & 1; 756169689Skan cm = sc->aac_commands + (index >> 2); 757169689Skan fib = cm->cm_fib; 758169689Skan if (fast) { 759169689Skan fib->Header.XferState |= AAC_FIBSTATE_DONEADAP; 760169689Skan *((u_int32_t *)(fib->data)) = AAC_ERROR_NORMAL; 761169689Skan } 762169689Skan aac_remove_busy(cm); 763169689Skan aac_unmap_command(cm); 764169689Skan cm->cm_flags |= AAC_CMD_COMPLETED; 765169689Skan 766208737Sjmallett /* is there a completion handler? */ 767208737Sjmallett if (cm->cm_complete != NULL) { 768208737Sjmallett cm->cm_complete(cm); 769169689Skan } else { 770169689Skan /* assume that someone is sleeping on this 771169689Skan * command 772169689Skan */ 773169689Skan wakeup(cm); 774169689Skan } 775169689Skan sc->flags &= ~AAC_QUEUE_FRZN; 776169689Skan } 777169689Skan } 778169689Skan /* see if we can start some more I/O */ 779169689Skan if ((sc->flags & AAC_QUEUE_FRZN) == 0) 780169689Skan aac_startio(sc); 781169689Skan 782169689Skan mtx_unlock(&sc->aac_io_lock); 783169689Skan} 784169689Skan 785169689Skanint 786169689Skanaac_fast_intr(void *arg) 787169689Skan{ 788169689Skan struct aac_softc *sc; 789169689Skan u_int16_t reason; 790169689Skan 791169689Skan debug_called(2); 792169689Skan 793169689Skan sc = (struct aac_softc *)arg; 794169689Skan 795169689Skan /* 796169689Skan * Read the status register directly. This is faster than taking the 797169689Skan * driver lock and reading the queues directly. It also saves having 798169689Skan * to turn parts of the driver lock into a spin mutex, which would be 799169689Skan * ugly. 800169689Skan */ 801169689Skan reason = AAC_GET_ISTATUS(sc); 802169689Skan AAC_CLEAR_ISTATUS(sc, reason); 803169689Skan 804169689Skan /* handle completion processing */ 805169689Skan if (reason & AAC_DB_RESPONSE_READY) 806169689Skan taskqueue_enqueue_fast(taskqueue_fast, &sc->aac_task_complete); 807169689Skan 808169689Skan /* controller wants to talk to us */ 809169689Skan if (reason & (AAC_DB_PRINTF | AAC_DB_COMMAND_READY)) { 810169689Skan /* 811169689Skan * XXX Make sure that we don't get fooled by strange messages 812169689Skan * that start with a NULL. 813169689Skan */ 814169689Skan if ((reason & AAC_DB_PRINTF) && 815169689Skan (sc->aac_common->ac_printf[0] == 0)) 816169689Skan sc->aac_common->ac_printf[0] = 32; 817169689Skan 818169689Skan /* 819169689Skan * This might miss doing the actual wakeup. However, the 820169689Skan * msleep that this is waking up has a timeout, so it will 821169689Skan * wake up eventually. AIFs and printfs are low enough 822169689Skan * priority that they can handle hanging out for a few seconds 823169689Skan * if needed. 824169689Skan */ 825169689Skan wakeup(sc->aifthread); 826169689Skan } 827169689Skan return (FILTER_HANDLED); 828169689Skan} 829169689Skan 830169689Skan/* 831169689Skan * Command Processing 832169689Skan */ 833169689Skan 834169689Skan/* 835169689Skan * Start as much queued I/O as possible on the controller 836169689Skan */ 837169689Skanvoid 838169689Skanaac_startio(struct aac_softc *sc) 839169689Skan{ 840169689Skan struct aac_command *cm; 841169689Skan int error; 842169689Skan 843169689Skan debug_called(2); 844169689Skan 845169689Skan for (;;) { 846169689Skan /* 847169689Skan * This flag might be set if the card is out of resources. 848169689Skan * Checking it here prevents an infinite loop of deferrals. 849169689Skan */ 850169689Skan if (sc->flags & AAC_QUEUE_FRZN) 851169689Skan break; 852169689Skan 853169689Skan /* 854169689Skan * Try to get a command that's been put off for lack of 855169689Skan * resources 856169689Skan */ 857169689Skan cm = aac_dequeue_ready(sc); 858169689Skan 859169689Skan /* 860169689Skan * Try to build a command off the bio queue (ignore error 861169689Skan * return) 862169689Skan */ 863169689Skan if (cm == NULL) 864169689Skan aac_bio_command(sc, &cm); 865169689Skan 866169689Skan /* nothing to do? */ 867169689Skan if (cm == NULL) 868169689Skan break; 869169689Skan 870169689Skan /* don't map more than once */ 871169689Skan if (cm->cm_flags & AAC_CMD_MAPPED) 872169689Skan panic("aac: command %p already mapped", cm); 873169689Skan 874169689Skan /* 875169689Skan * Set up the command to go to the controller. If there are no 876169689Skan * data buffers associated with the command then it can bypass 877169689Skan * busdma. 878169689Skan */ 879169689Skan if (cm->cm_datalen != 0) { 880169689Skan error = bus_dmamap_load(sc->aac_buffer_dmat, 881169689Skan cm->cm_datamap, cm->cm_data, 882169689Skan cm->cm_datalen, 883169689Skan aac_map_command_sg, cm, 0); 884169689Skan if (error == EINPROGRESS) { 885169689Skan debug(1, "freezing queue\n"); 886169689Skan sc->flags |= AAC_QUEUE_FRZN; 887169689Skan error = 0; 888169689Skan } else if (error != 0) 889169689Skan panic("aac_startio: unexpected error %d from " 890169689Skan "busdma\n", error); 891169689Skan } else 892169689Skan aac_map_command_sg(cm, NULL, 0, 0); 893169689Skan } 894169689Skan} 895169689Skan 896169689Skan/* 897169689Skan * Handle notification of one or more FIBs coming from the controller. 898169689Skan */ 899169689Skanstatic void 900169689Skanaac_command_thread(struct aac_softc *sc) 901169689Skan{ 902169689Skan struct aac_fib *fib; 903169689Skan u_int32_t fib_size; 904169689Skan int size, retval; 905169689Skan 906169689Skan debug_called(2); 907169689Skan 908169689Skan mtx_lock(&sc->aac_io_lock); 909169689Skan sc->aifflags = AAC_AIFFLAGS_RUNNING; 910169689Skan 911169689Skan while ((sc->aifflags & AAC_AIFFLAGS_EXIT) == 0) { 912169689Skan 913169689Skan retval = 0; 914169689Skan if ((sc->aifflags & AAC_AIFFLAGS_PENDING) == 0) 915169689Skan retval = msleep(sc->aifthread, &sc->aac_io_lock, PRIBIO, 916169689Skan "aifthd", AAC_PERIODIC_INTERVAL * hz); 917169689Skan 918169689Skan /* 919169689Skan * First see if any FIBs need to be allocated. This needs 920169689Skan * to be called without the driver lock because contigmalloc 921169689Skan * will grab Giant, and would result in an LOR. 922169689Skan */ 923169689Skan if ((sc->aifflags & AAC_AIFFLAGS_ALLOCFIBS) != 0) { 924169689Skan mtx_unlock(&sc->aac_io_lock); 925169689Skan aac_alloc_commands(sc); 926169689Skan mtx_lock(&sc->aac_io_lock); 927169689Skan sc->aifflags &= ~AAC_AIFFLAGS_ALLOCFIBS; 928169689Skan aac_startio(sc); 929169689Skan } 930169689Skan 931169689Skan /* 932169689Skan * While we're here, check to see if any commands are stuck. 933169689Skan * This is pretty low-priority, so it's ok if it doesn't 934169689Skan * always fire. 935169689Skan */ 936169689Skan if (retval == EWOULDBLOCK) 937169689Skan aac_timeout(sc); 938169689Skan 939169689Skan /* Check the hardware printf message buffer */ 940169689Skan if (sc->aac_common->ac_printf[0] != 0) 941169689Skan aac_print_printf(sc); 942169689Skan 943169689Skan /* Also check to see if the adapter has a command for us. */ 944169689Skan if (sc->flags & AAC_FLAGS_NEW_COMM) 945169689Skan continue; 946169689Skan for (;;) { 947169689Skan if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, 948169689Skan &fib_size, &fib)) 949169689Skan break; 950169689Skan 951169689Skan AAC_PRINT_FIB(sc, fib); 952169689Skan 953169689Skan switch (fib->Header.Command) { 954169689Skan case AifRequest: 955169689Skan aac_handle_aif(sc, fib); 956169689Skan break; 957169689Skan default: 958169689Skan device_printf(sc->aac_dev, "unknown command " 959169689Skan "from controller\n"); 960169689Skan break; 961169689Skan } 962169689Skan 963169689Skan if ((fib->Header.XferState == 0) || 964169689Skan (fib->Header.StructType != AAC_FIBTYPE_TFIB)) { 965169689Skan break; 966169689Skan } 967169689Skan 968169689Skan /* Return the AIF to the controller. */ 969169689Skan if (fib->Header.XferState & AAC_FIBSTATE_FROMADAP) { 970169689Skan fib->Header.XferState |= AAC_FIBSTATE_DONEHOST; 971169689Skan *(AAC_FSAStatus*)fib->data = ST_OK; 972169689Skan 973169689Skan /* XXX Compute the Size field? */ 974169689Skan size = fib->Header.Size; 975169689Skan if (size > sizeof(struct aac_fib)) { 976169689Skan size = sizeof(struct aac_fib); 977169689Skan fib->Header.Size = size; 978169689Skan } 979169689Skan /* 980169689Skan * Since we did not generate this command, it 981169689Skan * cannot go through the normal 982169689Skan * enqueue->startio chain. 983169689Skan */ 984169689Skan aac_enqueue_response(sc, 985169689Skan AAC_ADAP_NORM_RESP_QUEUE, 986169689Skan fib); 987169689Skan } 988169689Skan } 989169689Skan } 990169689Skan sc->aifflags &= ~AAC_AIFFLAGS_RUNNING; 991169689Skan mtx_unlock(&sc->aac_io_lock); 992169689Skan wakeup(sc->aac_dev); 993169689Skan 994169689Skan kproc_exit(0); 995169689Skan} 996169689Skan 997169689Skan/* 998169689Skan * Process completed commands. 999169689Skan */ 1000169689Skanstatic void 1001169689Skanaac_complete(void *context, int pending) 1002169689Skan{ 1003169689Skan struct aac_softc *sc; 1004169689Skan struct aac_command *cm; 1005169689Skan struct aac_fib *fib; 1006169689Skan u_int32_t fib_size; 1007169689Skan 1008169689Skan debug_called(2); 1009169689Skan 1010169689Skan sc = (struct aac_softc *)context; 1011169689Skan 1012169689Skan mtx_lock(&sc->aac_io_lock); 1013169689Skan 1014169689Skan /* pull completed commands off the queue */ 1015169689Skan for (;;) { 1016169689Skan /* look for completed FIBs on our queue */ 1017169689Skan if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size, 1018169689Skan &fib)) 1019169689Skan break; /* nothing to do */ 1020169689Skan 1021169689Skan /* get the command, unmap and hand off for processing */ 1022169689Skan cm = sc->aac_commands + fib->Header.SenderData; 1023169689Skan if (cm == NULL) { 1024169689Skan AAC_PRINT_FIB(sc, fib); 1025169689Skan break; 1026169689Skan } 1027169689Skan aac_remove_busy(cm); 1028169689Skan 1029169689Skan aac_unmap_command(cm); 1030169689Skan cm->cm_flags |= AAC_CMD_COMPLETED; 1031169689Skan 1032169689Skan /* is there a completion handler? */ 1033169689Skan if (cm->cm_complete != NULL) { 1034169689Skan cm->cm_complete(cm); 1035169689Skan } else { 1036169689Skan /* assume that someone is sleeping on this command */ 1037169689Skan wakeup(cm); 1038169689Skan } 1039169689Skan } 1040169689Skan 1041169689Skan /* see if we can start some more I/O */ 1042169689Skan sc->flags &= ~AAC_QUEUE_FRZN; 1043169689Skan aac_startio(sc); 1044169689Skan 1045169689Skan mtx_unlock(&sc->aac_io_lock); 1046169689Skan} 1047169689Skan 1048169689Skan/* 1049169689Skan * Handle a bio submitted from a disk device. 1050169689Skan */ 1051169689Skanvoid 1052169689Skanaac_submit_bio(struct bio *bp) 1053169689Skan{ 1054169689Skan struct aac_disk *ad; 1055169689Skan struct aac_softc *sc; 1056169689Skan 1057169689Skan debug_called(2); 1058169689Skan 1059169689Skan ad = (struct aac_disk *)bp->bio_disk->d_drv1; 1060169689Skan sc = ad->ad_controller; 1061169689Skan 1062169689Skan /* queue the BIO and try to get some work done */ 1063169689Skan aac_enqueue_bio(sc, bp); 1064169689Skan aac_startio(sc); 1065169689Skan} 1066169689Skan 1067169689Skan/* 1068169689Skan * Get a bio and build a command to go with it. 1069169689Skan */ 1070169689Skanstatic int 1071169689Skanaac_bio_command(struct aac_softc *sc, struct aac_command **cmp) 1072169689Skan{ 1073169689Skan struct aac_command *cm; 1074169689Skan struct aac_fib *fib; 1075169689Skan struct aac_disk *ad; 1076169689Skan struct bio *bp; 1077169689Skan 1078169689Skan debug_called(2); 1079169689Skan 1080169689Skan /* get the resources we will need */ 1081169689Skan cm = NULL; 1082169689Skan bp = NULL; 1083169689Skan if (aac_alloc_command(sc, &cm)) /* get a command */ 1084169689Skan goto fail; 1085169689Skan if ((bp = aac_dequeue_bio(sc)) == NULL) 1086169689Skan goto fail; 1087169689Skan 1088169689Skan /* fill out the command */ 1089169689Skan cm->cm_data = (void *)bp->bio_data; 1090169689Skan cm->cm_datalen = bp->bio_bcount; 1091169689Skan cm->cm_complete = aac_bio_complete; 1092169689Skan cm->cm_private = bp; 1093169689Skan cm->cm_timestamp = time_uptime; 1094169689Skan cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE; 1095169689Skan 1096169689Skan /* build the FIB */ 1097169689Skan fib = cm->cm_fib; 1098169689Skan fib->Header.Size = sizeof(struct aac_fib_header); 1099169689Skan fib->Header.XferState = 1100169689Skan AAC_FIBSTATE_HOSTOWNED | 1101169689Skan AAC_FIBSTATE_INITIALISED | 1102169689Skan AAC_FIBSTATE_EMPTY | 1103169689Skan AAC_FIBSTATE_FROMHOST | 1104169689Skan AAC_FIBSTATE_REXPECTED | 1105169689Skan AAC_FIBSTATE_NORM | 1106169689Skan AAC_FIBSTATE_ASYNC | 1107169689Skan AAC_FIBSTATE_FAST_RESPONSE; 1108169689Skan 1109169689Skan /* build the read/write request */ 1110169689Skan ad = (struct aac_disk *)bp->bio_disk->d_drv1; 1111169689Skan 1112169689Skan if (sc->flags & AAC_FLAGS_RAW_IO) { 1113169689Skan struct aac_raw_io *raw; 1114169689Skan raw = (struct aac_raw_io *)&fib->data[0]; 1115169689Skan fib->Header.Command = RawIo; 1116169689Skan raw->BlockNumber = (u_int64_t)bp->bio_pblkno; 1117169689Skan raw->ByteCount = bp->bio_bcount; 1118169689Skan raw->ContainerId = ad->ad_container->co_mntobj.ObjectId; 1119169689Skan raw->BpTotal = 0; 1120169689Skan raw->BpComplete = 0; 1121169689Skan fib->Header.Size += sizeof(struct aac_raw_io); 1122169689Skan cm->cm_sgtable = (struct aac_sg_table *)&raw->SgMapRaw; 1123169689Skan if (bp->bio_cmd == BIO_READ) { 1124169689Skan raw->Flags = 1; 1125169689Skan cm->cm_flags |= AAC_CMD_DATAIN; 1126169689Skan } else { 1127169689Skan raw->Flags = 0; 1128169689Skan cm->cm_flags |= AAC_CMD_DATAOUT; 1129169689Skan } 1130169689Skan } else if ((sc->flags & AAC_FLAGS_SG_64BIT) == 0) { 1131169689Skan fib->Header.Command = ContainerCommand; 1132169689Skan if (bp->bio_cmd == BIO_READ) { 1133169689Skan struct aac_blockread *br; 1134169689Skan br = (struct aac_blockread *)&fib->data[0]; 1135169689Skan br->Command = VM_CtBlockRead; 1136169689Skan br->ContainerId = ad->ad_container->co_mntobj.ObjectId; 1137169689Skan br->BlockNumber = bp->bio_pblkno; 1138169689Skan br->ByteCount = bp->bio_bcount; 1139169689Skan fib->Header.Size += sizeof(struct aac_blockread); 1140169689Skan cm->cm_sgtable = &br->SgMap; 1141169689Skan cm->cm_flags |= AAC_CMD_DATAIN; 1142169689Skan } else { 1143169689Skan struct aac_blockwrite *bw; 1144169689Skan bw = (struct aac_blockwrite *)&fib->data[0]; 1145169689Skan bw->Command = VM_CtBlockWrite; 1146169689Skan bw->ContainerId = ad->ad_container->co_mntobj.ObjectId; 1147169689Skan bw->BlockNumber = bp->bio_pblkno; 1148169689Skan bw->ByteCount = bp->bio_bcount; 1149169689Skan bw->Stable = CUNSTABLE; 1150169689Skan fib->Header.Size += sizeof(struct aac_blockwrite); 1151169689Skan cm->cm_flags |= AAC_CMD_DATAOUT; 1152169689Skan cm->cm_sgtable = &bw->SgMap; 1153169689Skan } 1154169689Skan } else { 1155169689Skan fib->Header.Command = ContainerCommand64; 1156169689Skan if (bp->bio_cmd == BIO_READ) { 1157169689Skan struct aac_blockread64 *br; 1158169689Skan br = (struct aac_blockread64 *)&fib->data[0]; 1159169689Skan br->Command = VM_CtHostRead64; 1160169689Skan br->ContainerId = ad->ad_container->co_mntobj.ObjectId; 1161169689Skan br->SectorCount = bp->bio_bcount / AAC_BLOCK_SIZE; 1162169689Skan br->BlockNumber = bp->bio_pblkno; 1163169689Skan br->Pad = 0; 1164169689Skan br->Flags = 0; 1165169689Skan fib->Header.Size += sizeof(struct aac_blockread64); 1166169689Skan cm->cm_flags |= AAC_CMD_DATAOUT; 1167169689Skan cm->cm_sgtable = (struct aac_sg_table *)&br->SgMap64; 1168169689Skan } else { 1169169689Skan struct aac_blockwrite64 *bw; 1170169689Skan bw = (struct aac_blockwrite64 *)&fib->data[0]; 1171169689Skan bw->Command = VM_CtHostWrite64; 1172169689Skan bw->ContainerId = ad->ad_container->co_mntobj.ObjectId; 1173169689Skan bw->SectorCount = bp->bio_bcount / AAC_BLOCK_SIZE; 1174169689Skan bw->BlockNumber = bp->bio_pblkno; 1175169689Skan bw->Pad = 0; 1176169689Skan bw->Flags = 0; 1177169689Skan fib->Header.Size += sizeof(struct aac_blockwrite64); 1178169689Skan cm->cm_flags |= AAC_CMD_DATAIN; 1179169689Skan cm->cm_sgtable = (struct aac_sg_table *)&bw->SgMap64; 1180169689Skan } 1181169689Skan } 1182169689Skan 1183169689Skan *cmp = cm; 1184169689Skan return(0); 1185169689Skan 1186169689Skanfail: 1187169689Skan if (bp != NULL) 1188169689Skan aac_enqueue_bio(sc, bp); 1189169689Skan if (cm != NULL) 1190169689Skan aac_release_command(cm); 1191169689Skan return(ENOMEM); 1192169689Skan} 1193169689Skan 1194169689Skan/* 1195169689Skan * Handle a bio-instigated command that has been completed. 1196169689Skan */ 1197169689Skanstatic void 1198169689Skanaac_bio_complete(struct aac_command *cm) 1199169689Skan{ 1200169689Skan struct aac_blockread_response *brr; 1201169689Skan struct aac_blockwrite_response *bwr; 1202169689Skan struct bio *bp; 1203169689Skan AAC_FSAStatus status; 1204169689Skan 1205169689Skan /* fetch relevant status and then release the command */ 1206169689Skan bp = (struct bio *)cm->cm_private; 1207169689Skan if (bp->bio_cmd == BIO_READ) { 1208169689Skan brr = (struct aac_blockread_response *)&cm->cm_fib->data[0]; 1209169689Skan status = brr->Status; 1210169689Skan } else { 1211169689Skan bwr = (struct aac_blockwrite_response *)&cm->cm_fib->data[0]; 1212169689Skan status = bwr->Status; 1213169689Skan } 1214169689Skan aac_release_command(cm); 1215169689Skan 1216169689Skan /* fix up the bio based on status */ 1217169689Skan if (status == ST_OK) { 1218169689Skan bp->bio_resid = 0; 1219169689Skan } else { 1220169689Skan bp->bio_error = EIO; 1221169689Skan bp->bio_flags |= BIO_ERROR; 1222169689Skan /* pass an error string out to the disk layer */ 1223169689Skan bp->bio_driver1 = aac_describe_code(aac_command_status_table, 1224169689Skan status); 1225169689Skan } 1226169689Skan aac_biodone(bp); 1227169689Skan} 1228169689Skan 1229169689Skan/* 1230169689Skan * Submit a command to the controller, return when it completes. 1231169689Skan * XXX This is very dangerous! If the card has gone out to lunch, we could 1232169689Skan * be stuck here forever. At the same time, signals are not caught 1233169689Skan * because there is a risk that a signal could wakeup the sleep before 1234169689Skan * the card has a chance to complete the command. Since there is no way 1235169689Skan * to cancel a command that is in progress, we can't protect against the 1236169689Skan * card completing a command late and spamming the command and data 1237169689Skan * memory. So, we are held hostage until the command completes. 1238169689Skan */ 1239169689Skanstatic int 1240169689Skanaac_wait_command(struct aac_command *cm) 1241169689Skan{ 1242169689Skan struct aac_softc *sc; 1243169689Skan int error; 1244169689Skan 1245169689Skan debug_called(2); 1246169689Skan 1247169689Skan sc = cm->cm_sc; 1248169689Skan 1249169689Skan /* Put the command on the ready queue and get things going */ 1250169689Skan cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE; 1251169689Skan aac_enqueue_ready(cm); 1252169689Skan aac_startio(sc); 1253169689Skan error = msleep(cm, &sc->aac_io_lock, PRIBIO, "aacwait", 0); 1254169689Skan return(error); 1255169689Skan} 1256169689Skan 1257169689Skan/* 1258169689Skan *Command Buffer Management 1259169689Skan */ 1260169689Skan 1261169689Skan/* 1262169689Skan * Allocate a command. 1263169689Skan */ 1264169689Skanint 1265169689Skanaac_alloc_command(struct aac_softc *sc, struct aac_command **cmp) 1266169689Skan{ 1267169689Skan struct aac_command *cm; 1268169689Skan 1269169689Skan debug_called(3); 1270169689Skan 1271169689Skan if ((cm = aac_dequeue_free(sc)) == NULL) { 1272169689Skan if (sc->total_fibs < sc->aac_max_fibs) { 1273169689Skan sc->aifflags |= AAC_AIFFLAGS_ALLOCFIBS; 1274169689Skan wakeup(sc->aifthread); 1275169689Skan } 1276169689Skan return (EBUSY); 1277169689Skan } 1278169689Skan 1279169689Skan *cmp = cm; 1280169689Skan return(0); 1281169689Skan} 1282169689Skan 1283169689Skan/* 1284169689Skan * Release a command back to the freelist. 1285169689Skan */ 1286169689Skanvoid 1287169689Skanaac_release_command(struct aac_command *cm) 1288169689Skan{ 1289169689Skan struct aac_event *event; 1290169689Skan struct aac_softc *sc; 1291169689Skan 1292169689Skan debug_called(3); 1293169689Skan 1294169689Skan /* (re)initialize the command/FIB */ 1295169689Skan cm->cm_sgtable = NULL; 1296169689Skan cm->cm_flags = 0; 1297169689Skan cm->cm_complete = NULL; 1298169689Skan cm->cm_private = NULL; 1299169689Skan cm->cm_fib->Header.XferState = AAC_FIBSTATE_EMPTY; 1300234855Sgonzo cm->cm_fib->Header.StructType = AAC_FIBTYPE_TFIB; 1301234855Sgonzo cm->cm_fib->Header.Flags = 0; 1302169689Skan cm->cm_fib->Header.SenderSize = cm->cm_sc->aac_max_fib_size; 1303234855Sgonzo 1304234855Sgonzo /* 1305234855Sgonzo * These are duplicated in aac_start to cover the case where an 1306234855Sgonzo * intermediate stage may have destroyed them. They're left 1307234855Sgonzo * initialized here for debugging purposes only. 1308234855Sgonzo */ 1309234855Sgonzo cm->cm_fib->Header.ReceiverFibAddress = (u_int32_t)cm->cm_fibphys; 1310234855Sgonzo cm->cm_fib->Header.SenderData = 0; 1311234855Sgonzo 1312234855Sgonzo aac_enqueue_free(cm); 1313234855Sgonzo 1314234855Sgonzo /* 1315169689Skan * Dequeue all events so that there's no risk of events getting 1316169689Skan * stranded. 1317169689Skan */ 1318169689Skan sc = cm->cm_sc; 1319169689Skan while ((event = TAILQ_FIRST(&sc->aac_ev_cmfree)) != NULL) { 1320169689Skan TAILQ_REMOVE(&sc->aac_ev_cmfree, event, ev_links); 1321169689Skan event->ev_callback(sc, event, event->ev_arg); 1322169689Skan } 1323169689Skan} 1324169689Skan 1325169689Skan/* 1326169689Skan * Map helper for command/FIB allocation. 1327169689Skan */ 1328169689Skanstatic void 1329169689Skanaac_map_command_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1330169689Skan{ 1331169689Skan uint64_t *fibphys; 1332169689Skan 1333169689Skan fibphys = (uint64_t *)arg; 1334169689Skan 1335169689Skan debug_called(3); 1336169689Skan 1337169689Skan *fibphys = segs[0].ds_addr; 1338169689Skan} 1339169689Skan 1340169689Skan/* 1341169689Skan * Allocate and initialize commands/FIBs for this adapter. 1342169689Skan */ 1343169689Skanstatic int 1344169689Skanaac_alloc_commands(struct aac_softc *sc) 1345169689Skan{ 1346169689Skan struct aac_command *cm; 1347169689Skan struct aac_fibmap *fm; 1348169689Skan uint64_t fibphys; 1349169689Skan int i, error; 1350169689Skan 1351169689Skan debug_called(2); 1352169689Skan 1353169689Skan if (sc->total_fibs + sc->aac_max_fibs_alloc > sc->aac_max_fibs) 1354169689Skan return (ENOMEM); 1355169689Skan 1356169689Skan fm = malloc(sizeof(struct aac_fibmap), M_AACBUF, M_NOWAIT|M_ZERO); 1357169689Skan if (fm == NULL) 1358169689Skan return (ENOMEM); 1359169689Skan 1360169689Skan /* allocate the FIBs in DMAable memory and load them */ 1361169689Skan if (bus_dmamem_alloc(sc->aac_fib_dmat, (void **)&fm->aac_fibs, 1362169689Skan BUS_DMA_NOWAIT, &fm->aac_fibmap)) { 1363169689Skan device_printf(sc->aac_dev, 1364169689Skan "Not enough contiguous memory available.\n"); 1365169689Skan free(fm, M_AACBUF); 1366169689Skan return (ENOMEM); 1367169689Skan } 1368169689Skan 1369169689Skan /* Ignore errors since this doesn't bounce */ 1370169689Skan (void)bus_dmamap_load(sc->aac_fib_dmat, fm->aac_fibmap, fm->aac_fibs, 1371169689Skan sc->aac_max_fibs_alloc * sc->aac_max_fib_size, 1372169689Skan aac_map_command_helper, &fibphys, 0); 1373169689Skan 1374169689Skan /* initialize constant fields in the command structure */ 1375169689Skan bzero(fm->aac_fibs, sc->aac_max_fibs_alloc * sc->aac_max_fib_size); 1376169689Skan for (i = 0; i < sc->aac_max_fibs_alloc; i++) { 1377169689Skan cm = sc->aac_commands + sc->total_fibs; 1378169689Skan fm->aac_commands = cm; 1379169689Skan cm->cm_sc = sc; 1380169689Skan cm->cm_fib = (struct aac_fib *) 1381169689Skan ((u_int8_t *)fm->aac_fibs + i*sc->aac_max_fib_size); 1382169689Skan cm->cm_fibphys = fibphys + i*sc->aac_max_fib_size; 1383169689Skan cm->cm_index = sc->total_fibs; 1384169689Skan 1385169689Skan if ((error = bus_dmamap_create(sc->aac_buffer_dmat, 0, 1386169689Skan &cm->cm_datamap)) != 0) 1387169689Skan break; 1388169689Skan mtx_lock(&sc->aac_io_lock); 1389169689Skan aac_release_command(cm); 1390169689Skan sc->total_fibs++; 1391169689Skan mtx_unlock(&sc->aac_io_lock); 1392169689Skan } 1393169689Skan 1394169689Skan if (i > 0) { 1395169689Skan mtx_lock(&sc->aac_io_lock); 1396169689Skan TAILQ_INSERT_TAIL(&sc->aac_fibmap_tqh, fm, fm_link); 1397169689Skan debug(1, "total_fibs= %d\n", sc->total_fibs); 1398169689Skan mtx_unlock(&sc->aac_io_lock); 1399169689Skan return (0); 1400169689Skan } 1401169689Skan 1402169689Skan bus_dmamap_unload(sc->aac_fib_dmat, fm->aac_fibmap); 1403169689Skan bus_dmamem_free(sc->aac_fib_dmat, fm->aac_fibs, fm->aac_fibmap); 1404169689Skan free(fm, M_AACBUF); 1405169689Skan return (ENOMEM); 1406169689Skan} 1407169689Skan 1408169689Skan/* 1409169689Skan * Free FIBs owned by this adapter. 1410169689Skan */ 1411169689Skanstatic void 1412169689Skanaac_free_commands(struct aac_softc *sc) 1413169689Skan{ 1414169689Skan struct aac_fibmap *fm; 1415169689Skan struct aac_command *cm; 1416169689Skan int i; 1417169689Skan 1418169689Skan debug_called(1); 1419169689Skan 1420169689Skan while ((fm = TAILQ_FIRST(&sc->aac_fibmap_tqh)) != NULL) { 1421169689Skan 1422169689Skan TAILQ_REMOVE(&sc->aac_fibmap_tqh, fm, fm_link); 1423169689Skan /* 1424169689Skan * We check against total_fibs to handle partially 1425169689Skan * allocated blocks. 1426169689Skan */ 1427169689Skan for (i = 0; i < sc->aac_max_fibs_alloc && sc->total_fibs--; i++) { 1428169689Skan cm = fm->aac_commands + i; 1429169689Skan bus_dmamap_destroy(sc->aac_buffer_dmat, cm->cm_datamap); 1430169689Skan } 1431169689Skan bus_dmamap_unload(sc->aac_fib_dmat, fm->aac_fibmap); 1432169689Skan bus_dmamem_free(sc->aac_fib_dmat, fm->aac_fibs, fm->aac_fibmap); 1433169689Skan free(fm, M_AACBUF); 1434169689Skan } 1435169689Skan} 1436169689Skan 1437169689Skan/* 1438169689Skan * Command-mapping helper function - populate this command's s/g table. 1439169689Skan */ 1440169689Skanstatic void 1441169689Skanaac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1442169689Skan{ 1443169689Skan struct aac_softc *sc; 1444169689Skan struct aac_command *cm; 1445169689Skan struct aac_fib *fib; 1446169689Skan int i; 1447169689Skan 1448169689Skan debug_called(3); 1449169689Skan 1450169689Skan cm = (struct aac_command *)arg; 1451169689Skan sc = cm->cm_sc; 1452169689Skan fib = cm->cm_fib; 1453169689Skan 1454169689Skan /* copy into the FIB */ 1455169689Skan if (cm->cm_sgtable != NULL) { 1456169689Skan if (fib->Header.Command == RawIo) { 1457169689Skan struct aac_sg_tableraw *sg; 1458169689Skan sg = (struct aac_sg_tableraw *)cm->cm_sgtable; 1459169689Skan sg->SgCount = nseg; 1460169689Skan for (i = 0; i < nseg; i++) { 1461169689Skan sg->SgEntryRaw[i].SgAddress = segs[i].ds_addr; 1462169689Skan sg->SgEntryRaw[i].SgByteCount = segs[i].ds_len; 1463169689Skan sg->SgEntryRaw[i].Next = 0; 1464169689Skan sg->SgEntryRaw[i].Prev = 0; 1465169689Skan sg->SgEntryRaw[i].Flags = 0; 1466169689Skan } 1467169689Skan /* update the FIB size for the s/g count */ 1468169689Skan fib->Header.Size += nseg*sizeof(struct aac_sg_entryraw); 1469169689Skan } else if ((cm->cm_sc->flags & AAC_FLAGS_SG_64BIT) == 0) { 1470169689Skan struct aac_sg_table *sg; 1471169689Skan sg = cm->cm_sgtable; 1472169689Skan sg->SgCount = nseg; 1473169689Skan for (i = 0; i < nseg; i++) { 1474169689Skan sg->SgEntry[i].SgAddress = segs[i].ds_addr; 1475169689Skan sg->SgEntry[i].SgByteCount = segs[i].ds_len; 1476169689Skan } 1477169689Skan /* update the FIB size for the s/g count */ 1478169689Skan fib->Header.Size += nseg*sizeof(struct aac_sg_entry); 1479169689Skan } else { 1480169689Skan struct aac_sg_table64 *sg; 1481169689Skan sg = (struct aac_sg_table64 *)cm->cm_sgtable; 1482169689Skan sg->SgCount = nseg; 1483169689Skan for (i = 0; i < nseg; i++) { 1484169689Skan sg->SgEntry64[i].SgAddress = segs[i].ds_addr; 1485169689Skan sg->SgEntry64[i].SgByteCount = segs[i].ds_len; 1486169689Skan } 1487169689Skan /* update the FIB size for the s/g count */ 1488169689Skan fib->Header.Size += nseg*sizeof(struct aac_sg_entry64); 1489169689Skan } 1490169689Skan } 1491169689Skan 1492169689Skan /* Fix up the address values in the FIB. Use the command array index 1493169689Skan * instead of a pointer since these fields are only 32 bits. Shift 1494169689Skan * the SenderFibAddress over to make room for the fast response bit 1495169689Skan * and for the AIF bit 1496169689Skan */ 1497169689Skan cm->cm_fib->Header.SenderFibAddress = (cm->cm_index << 2); 1498169689Skan cm->cm_fib->Header.ReceiverFibAddress = (u_int32_t)cm->cm_fibphys; 1499169689Skan 1500169689Skan /* save a pointer to the command for speedy reverse-lookup */ 1501169689Skan cm->cm_fib->Header.SenderData = cm->cm_index; 1502169689Skan 1503169689Skan if (cm->cm_flags & AAC_CMD_DATAIN) 1504169689Skan bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, 1505169689Skan BUS_DMASYNC_PREREAD); 1506169689Skan if (cm->cm_flags & AAC_CMD_DATAOUT) 1507169689Skan bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, 1508169689Skan BUS_DMASYNC_PREWRITE); 1509169689Skan cm->cm_flags |= AAC_CMD_MAPPED; 1510169689Skan 1511169689Skan if (sc->flags & AAC_FLAGS_NEW_COMM) { 1512169689Skan int count = 10000000L; 1513169689Skan while (AAC_SEND_COMMAND(sc, cm) != 0) { 1514169689Skan if (--count == 0) { 1515169689Skan aac_unmap_command(cm); 1516169689Skan sc->flags |= AAC_QUEUE_FRZN; 1517169689Skan aac_requeue_ready(cm); 1518169689Skan } 1519169689Skan DELAY(5); /* wait 5 usec. */ 1520169689Skan } 1521169689Skan } else { 1522169689Skan /* Put the FIB on the outbound queue */ 1523169689Skan if (aac_enqueue_fib(sc, cm->cm_queue, cm) == EBUSY) { 1524169689Skan aac_unmap_command(cm); 1525169689Skan sc->flags |= AAC_QUEUE_FRZN; 1526169689Skan aac_requeue_ready(cm); 1527169689Skan } 1528169689Skan } 1529169689Skan 1530169689Skan return; 1531169689Skan} 1532169689Skan 1533169689Skan/* 1534169689Skan * Unmap a command from controller-visible space. 1535169689Skan */ 1536169689Skanstatic void 1537169689Skanaac_unmap_command(struct aac_command *cm) 1538169689Skan{ 1539169689Skan struct aac_softc *sc; 1540169689Skan 1541169689Skan debug_called(2); 1542169689Skan 1543169689Skan sc = cm->cm_sc; 1544169689Skan 1545169689Skan if (!(cm->cm_flags & AAC_CMD_MAPPED)) 1546169689Skan return; 1547169689Skan 1548169689Skan if (cm->cm_datalen != 0) { 1549169689Skan if (cm->cm_flags & AAC_CMD_DATAIN) 1550169689Skan bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, 1551234855Sgonzo BUS_DMASYNC_POSTREAD); 1552234855Sgonzo if (cm->cm_flags & AAC_CMD_DATAOUT) 1553234855Sgonzo bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, 1554234855Sgonzo BUS_DMASYNC_POSTWRITE); 1555234855Sgonzo 1556234855Sgonzo bus_dmamap_unload(sc->aac_buffer_dmat, cm->cm_datamap); 1557234855Sgonzo } 1558234855Sgonzo cm->cm_flags &= ~AAC_CMD_MAPPED; 1559234855Sgonzo} 1560234855Sgonzo 1561169689Skan/* 1562169689Skan * Hardware Interface 1563169689Skan */ 1564169689Skan 1565169689Skan/* 1566169689Skan * Initialize the adapter. 1567169689Skan */ 1568169689Skanstatic void 1569169689Skanaac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1570169689Skan{ 1571169689Skan struct aac_softc *sc; 1572169689Skan 1573169689Skan debug_called(1); 1574169689Skan 1575169689Skan sc = (struct aac_softc *)arg; 1576169689Skan 1577169689Skan sc->aac_common_busaddr = segs[0].ds_addr; 1578169689Skan} 1579169689Skan 1580169689Skanstatic int 1581169689Skanaac_check_firmware(struct aac_softc *sc) 1582169689Skan{ 1583169689Skan u_int32_t major, minor, options = 0, atu_size = 0; 1584169689Skan int status; 1585169689Skan 1586169689Skan debug_called(1); 1587169689Skan 1588169689Skan /* 1589169689Skan * Retrieve the firmware version numbers. Dell PERC2/QC cards with 1590169689Skan * firmware version 1.x are not compatible with this driver. 1591169689Skan */ 1592169689Skan if (sc->flags & AAC_FLAGS_PERC2QC) { 1593169689Skan if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0, 1594169689Skan NULL)) { 1595169689Skan device_printf(sc->aac_dev, 1596169689Skan "Error reading firmware version\n"); 1597169689Skan return (EIO); 1598169689Skan } 1599169689Skan 1600169689Skan /* These numbers are stored as ASCII! */ 1601169689Skan major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30; 1602169689Skan minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30; 1603169689Skan if (major == 1) { 1604169689Skan device_printf(sc->aac_dev, 1605169689Skan "Firmware version %d.%d is not supported.\n", 1606169689Skan major, minor); 1607169689Skan return (EINVAL); 1608169689Skan } 1609169689Skan } 1610169689Skan 1611169689Skan /* 1612169689Skan * Retrieve the capabilities/supported options word so we know what 1613169689Skan * work-arounds to enable. Some firmware revs don't support this 1614169689Skan * command. 1615169689Skan */ 1616169689Skan if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, &status)) { 1617169689Skan if (status != AAC_SRB_STS_INVALID_REQUEST) { 1618169689Skan device_printf(sc->aac_dev, 1619169689Skan "RequestAdapterInfo failed\n"); 1620169689Skan return (EIO); 1621169689Skan } 1622169689Skan } else { 1623169689Skan options = AAC_GET_MAILBOX(sc, 1); 1624169689Skan atu_size = AAC_GET_MAILBOX(sc, 2); 1625169689Skan sc->supported_options = options; 1626169689Skan 1627169689Skan if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 && 1628169689Skan (sc->flags & AAC_FLAGS_NO4GB) == 0) 1629169689Skan sc->flags |= AAC_FLAGS_4GB_WINDOW; 1630169689Skan if (options & AAC_SUPPORTED_NONDASD) 1631169689Skan sc->flags |= AAC_FLAGS_ENABLE_CAM; 1632169689Skan if ((options & AAC_SUPPORTED_SGMAP_HOST64) != 0 1633169689Skan && (sizeof(bus_addr_t) > 4)) { 1634169689Skan device_printf(sc->aac_dev, 1635169689Skan "Enabling 64-bit address support\n"); 1636169689Skan sc->flags |= AAC_FLAGS_SG_64BIT; 1637169689Skan } 1638169689Skan if ((options & AAC_SUPPORTED_NEW_COMM) 1639169689Skan && sc->aac_if.aif_send_command) 1640169689Skan sc->flags |= AAC_FLAGS_NEW_COMM; 1641169689Skan if (options & AAC_SUPPORTED_64BIT_ARRAYSIZE) 1642169689Skan sc->flags |= AAC_FLAGS_ARRAY_64BIT; 1643169689Skan } 1644169689Skan 1645169689Skan /* Check for broken hardware that does a lower number of commands */ 1646169689Skan sc->aac_max_fibs = (sc->flags & AAC_FLAGS_256FIBS ? 256:512); 1647169689Skan 1648169689Skan /* Remap mem. resource, if required */ 1649169689Skan if ((sc->flags & AAC_FLAGS_NEW_COMM) && 1650169689Skan atu_size > rman_get_size(sc->aac_regs_resource)) { 1651169689Skan bus_release_resource( 1652169689Skan sc->aac_dev, SYS_RES_MEMORY, 1653169689Skan sc->aac_regs_rid, sc->aac_regs_resource); 1654169689Skan sc->aac_regs_resource = bus_alloc_resource( 1655169689Skan sc->aac_dev, SYS_RES_MEMORY, &sc->aac_regs_rid, 1656169689Skan 0ul, ~0ul, atu_size, RF_ACTIVE); 1657169689Skan if (sc->aac_regs_resource == NULL) { 1658169689Skan sc->aac_regs_resource = bus_alloc_resource_any( 1659169689Skan sc->aac_dev, SYS_RES_MEMORY, 1660169689Skan &sc->aac_regs_rid, RF_ACTIVE); 1661169689Skan if (sc->aac_regs_resource == NULL) { 1662169689Skan device_printf(sc->aac_dev, 1663169689Skan "couldn't allocate register window\n"); 1664169689Skan return (ENXIO); 1665169689Skan } 1666169689Skan sc->flags &= ~AAC_FLAGS_NEW_COMM; 1667169689Skan } 1668169689Skan sc->aac_btag = rman_get_bustag(sc->aac_regs_resource); 1669169689Skan sc->aac_bhandle = rman_get_bushandle(sc->aac_regs_resource); 1670169689Skan } 1671169689Skan 1672169689Skan /* Read preferred settings */ 1673169689Skan sc->aac_max_fib_size = sizeof(struct aac_fib); 1674169689Skan sc->aac_max_sectors = 128; /* 64KB */ 1675169689Skan if (sc->flags & AAC_FLAGS_SG_64BIT) 1676169689Skan sc->aac_sg_tablesize = (AAC_FIB_DATASIZE 1677169689Skan - sizeof(struct aac_blockwrite64)) 1678169689Skan / sizeof(struct aac_sg_entry64); 1679169689Skan else 1680169689Skan sc->aac_sg_tablesize = (AAC_FIB_DATASIZE 1681169689Skan - sizeof(struct aac_blockwrite)) 1682169689Skan / sizeof(struct aac_sg_entry); 1683169689Skan 1684169689Skan if (!aac_sync_command(sc, AAC_MONKER_GETCOMMPREF, 0, 0, 0, 0, NULL)) { 1685169689Skan options = AAC_GET_MAILBOX(sc, 1); 1686169689Skan sc->aac_max_fib_size = (options & 0xFFFF); 1687169689Skan sc->aac_max_sectors = (options >> 16) << 1; 1688169689Skan options = AAC_GET_MAILBOX(sc, 2); 1689169689Skan sc->aac_sg_tablesize = (options >> 16); 1690169689Skan options = AAC_GET_MAILBOX(sc, 3); 1691169689Skan sc->aac_max_fibs = (options & 0xFFFF); 1692169689Skan } 1693169689Skan if (sc->aac_max_fib_size > PAGE_SIZE) 1694169689Skan sc->aac_max_fib_size = PAGE_SIZE; 1695169689Skan sc->aac_max_fibs_alloc = PAGE_SIZE / sc->aac_max_fib_size; 1696169689Skan 1697169689Skan if (sc->aac_max_fib_size > sizeof(struct aac_fib)) { 1698169689Skan sc->flags |= AAC_FLAGS_RAW_IO; 1699169689Skan device_printf(sc->aac_dev, "Enable Raw I/O\n"); 1700169689Skan } 1701169689Skan 1702169689Skan return (0); 1703169689Skan} 1704169689Skan 1705169689Skanstatic int 1706169689Skanaac_init(struct aac_softc *sc) 1707169689Skan{ 1708169689Skan struct aac_adapter_init *ip; 1709169689Skan time_t then; 1710169689Skan u_int32_t code, qoffset; 1711169689Skan int error; 1712169689Skan 1713169689Skan debug_called(1); 1714169689Skan 1715169689Skan /* 1716169689Skan * First wait for the adapter to come ready. 1717169689Skan */ 1718169689Skan then = time_uptime; 1719169689Skan do { 1720169689Skan code = AAC_GET_FWSTATUS(sc); 1721169689Skan if (code & AAC_SELF_TEST_FAILED) { 1722169689Skan device_printf(sc->aac_dev, "FATAL: selftest failed\n"); 1723169689Skan return(ENXIO); 1724169689Skan } 1725169689Skan if (code & AAC_KERNEL_PANIC) { 1726169689Skan device_printf(sc->aac_dev, 1727169689Skan "FATAL: controller kernel panic\n"); 1728169689Skan return(ENXIO); 1729169689Skan } 1730169689Skan if (time_uptime > (then + AAC_BOOT_TIMEOUT)) { 1731169689Skan device_printf(sc->aac_dev, 1732169689Skan "FATAL: controller not coming ready, " 1733169689Skan "status %x\n", code); 1734169689Skan return(ENXIO); 1735169689Skan } 1736169689Skan } while (!(code & AAC_UP_AND_RUNNING)); 1737169689Skan 1738169689Skan error = ENOMEM; 1739169689Skan /* 1740169689Skan * Create DMA tag for mapping buffers into controller-addressable space. 1741169689Skan */ 1742169689Skan if (bus_dma_tag_create(sc->aac_parent_dmat, /* parent */ 1743169689Skan 1, 0, /* algnmnt, boundary */ 1744169689Skan (sc->flags & AAC_FLAGS_SG_64BIT) ? 1745169689Skan BUS_SPACE_MAXADDR : 1746169689Skan BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 1747169689Skan BUS_SPACE_MAXADDR, /* highaddr */ 1748169689Skan NULL, NULL, /* filter, filterarg */ 1749169689Skan MAXBSIZE, /* maxsize */ 1750169689Skan sc->aac_sg_tablesize, /* nsegments */ 1751169689Skan MAXBSIZE, /* maxsegsize */ 1752169689Skan BUS_DMA_ALLOCNOW, /* flags */ 1753169689Skan busdma_lock_mutex, /* lockfunc */ 1754169689Skan &sc->aac_io_lock, /* lockfuncarg */ 1755169689Skan &sc->aac_buffer_dmat)) { 1756169689Skan device_printf(sc->aac_dev, "can't allocate buffer DMA tag\n"); 1757169689Skan goto out; 1758169689Skan } 1759169689Skan 1760169689Skan /* 1761169689Skan * Create DMA tag for mapping FIBs into controller-addressable space.. 1762169689Skan */ 1763169689Skan if (bus_dma_tag_create(sc->aac_parent_dmat, /* parent */ 1764169689Skan 1, 0, /* algnmnt, boundary */ 1765169689Skan (sc->flags & AAC_FLAGS_4GB_WINDOW) ? 1766169689Skan BUS_SPACE_MAXADDR_32BIT : 1767169689Skan 0x7fffffff, /* lowaddr */ 1768169689Skan BUS_SPACE_MAXADDR, /* highaddr */ 1769169689Skan NULL, NULL, /* filter, filterarg */ 1770169689Skan sc->aac_max_fibs_alloc * 1771169689Skan sc->aac_max_fib_size, /* maxsize */ 1772169689Skan 1, /* nsegments */ 1773169689Skan sc->aac_max_fibs_alloc * 1774169689Skan sc->aac_max_fib_size, /* maxsegsize */ 1775169689Skan 0, /* flags */ 1776169689Skan NULL, NULL, /* No locking needed */ 1777169689Skan &sc->aac_fib_dmat)) { 1778169689Skan device_printf(sc->aac_dev, "can't allocate FIB DMA tag\n");; 1779169689Skan goto out; 1780169689Skan } 1781169689Skan 1782169689Skan /* 1783169689Skan * Create DMA tag for the common structure and allocate it. 1784169689Skan */ 1785169689Skan if (bus_dma_tag_create(sc->aac_parent_dmat, /* parent */ 1786169689Skan 1, 0, /* algnmnt, boundary */ 1787169689Skan (sc->flags & AAC_FLAGS_4GB_WINDOW) ? 1788169689Skan BUS_SPACE_MAXADDR_32BIT : 1789169689Skan 0x7fffffff, /* lowaddr */ 1790169689Skan BUS_SPACE_MAXADDR, /* highaddr */ 1791169689Skan NULL, NULL, /* filter, filterarg */ 1792169689Skan 8192 + sizeof(struct aac_common), /* maxsize */ 1793169689Skan 1, /* nsegments */ 1794169689Skan BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 1795169689Skan 0, /* flags */ 1796169689Skan NULL, NULL, /* No locking needed */ 1797169689Skan &sc->aac_common_dmat)) { 1798169689Skan device_printf(sc->aac_dev, 1799169689Skan "can't allocate common structure DMA tag\n"); 1800169689Skan goto out; 1801169689Skan } 1802169689Skan if (bus_dmamem_alloc(sc->aac_common_dmat, (void **)&sc->aac_common, 1803169689Skan BUS_DMA_NOWAIT, &sc->aac_common_dmamap)) { 1804169689Skan device_printf(sc->aac_dev, "can't allocate common structure\n"); 1805169689Skan goto out; 1806169689Skan } 1807169689Skan 1808169689Skan /* 1809169689Skan * Work around a bug in the 2120 and 2200 that cannot DMA commands 1810169689Skan * below address 8192 in physical memory. 1811169689Skan * XXX If the padding is not needed, can it be put to use instead 1812169689Skan * of ignored? 1813169689Skan */ 1814169689Skan (void)bus_dmamap_load(sc->aac_common_dmat, sc->aac_common_dmamap, 1815169689Skan sc->aac_common, 8192 + sizeof(*sc->aac_common), 1816169689Skan aac_common_map, sc, 0); 1817169689Skan 1818169689Skan if (sc->aac_common_busaddr < 8192) { 1819169689Skan sc->aac_common = (struct aac_common *) 1820169689Skan ((uint8_t *)sc->aac_common + 8192); 1821169689Skan sc->aac_common_busaddr += 8192; 1822169689Skan } 1823169689Skan bzero(sc->aac_common, sizeof(*sc->aac_common)); 1824169689Skan 1825169689Skan /* Allocate some FIBs and associated command structs */ 1826169689Skan TAILQ_INIT(&sc->aac_fibmap_tqh); 1827169689Skan sc->aac_commands = malloc(sc->aac_max_fibs * sizeof(struct aac_command), 1828169689Skan M_AACBUF, M_WAITOK|M_ZERO); 1829169689Skan while (sc->total_fibs < AAC_PREALLOCATE_FIBS) { 1830169689Skan if (aac_alloc_commands(sc) != 0) 1831169689Skan break; 1832169689Skan } 1833169689Skan if (sc->total_fibs == 0) 1834169689Skan goto out; 1835169689Skan 1836169689Skan /* 1837169689Skan * Fill in the init structure. This tells the adapter about the 1838169689Skan * physical location of various important shared data structures. 1839169689Skan */ 1840169689Skan ip = &sc->aac_common->ac_init; 1841169689Skan ip->InitStructRevision = AAC_INIT_STRUCT_REVISION; 1842169689Skan if (sc->aac_max_fib_size > sizeof(struct aac_fib)) { 1843169689Skan ip->InitStructRevision = AAC_INIT_STRUCT_REVISION_4; 1844169689Skan sc->flags |= AAC_FLAGS_RAW_IO; 1845169689Skan } 1846169689Skan ip->MiniPortRevision = AAC_INIT_STRUCT_MINIPORT_REVISION; 1847169689Skan 1848169689Skan ip->AdapterFibsPhysicalAddress = sc->aac_common_busaddr + 1849169689Skan offsetof(struct aac_common, ac_fibs); 1850169689Skan ip->AdapterFibsVirtualAddress = 0; 1851169689Skan ip->AdapterFibsSize = AAC_ADAPTER_FIBS * sizeof(struct aac_fib); 1852169689Skan ip->AdapterFibAlign = sizeof(struct aac_fib); 1853169689Skan 1854169689Skan ip->PrintfBufferAddress = sc->aac_common_busaddr + 1855169689Skan offsetof(struct aac_common, ac_printf); 1856169689Skan ip->PrintfBufferSize = AAC_PRINTF_BUFSIZE; 1857169689Skan 1858169689Skan /* 1859169689Skan * The adapter assumes that pages are 4K in size, except on some 1860169689Skan * broken firmware versions that do the page->byte conversion twice, 1861169689Skan * therefore 'assuming' that this value is in 16MB units (2^24). 1862169689Skan * Round up since the granularity is so high. 1863169689Skan */ 1864169689Skan ip->HostPhysMemPages = ctob(physmem) / AAC_PAGE_SIZE; 1865169689Skan if (sc->flags & AAC_FLAGS_BROKEN_MEMMAP) { 1866169689Skan ip->HostPhysMemPages = 1867169689Skan (ip->HostPhysMemPages + AAC_PAGE_SIZE) / AAC_PAGE_SIZE; 1868169689Skan } 1869169689Skan ip->HostElapsedSeconds = time_uptime; /* reset later if invalid */ 1870169689Skan 1871169689Skan ip->InitFlags = 0; 1872169689Skan if (sc->flags & AAC_FLAGS_NEW_COMM) { 1873169689Skan ip->InitFlags = INITFLAGS_NEW_COMM_SUPPORTED; 1874169689Skan device_printf(sc->aac_dev, "New comm. interface enabled\n"); 1875169689Skan } 1876169689Skan 1877169689Skan ip->MaxIoCommands = sc->aac_max_fibs; 1878169689Skan ip->MaxIoSize = sc->aac_max_sectors << 9; 1879169689Skan ip->MaxFibSize = sc->aac_max_fib_size; 1880169689Skan 1881169689Skan /* 1882169689Skan * Initialize FIB queues. Note that it appears that the layout of the 1883169689Skan * indexes and the segmentation of the entries may be mandated by the 1884169689Skan * adapter, which is only told about the base of the queue index fields. 1885169689Skan * 1886169689Skan * The initial values of the indices are assumed to inform the adapter 1887169689Skan * of the sizes of the respective queues, and theoretically it could 1888169689Skan * work out the entire layout of the queue structures from this. We 1889169689Skan * take the easy route and just lay this area out like everyone else 1890169689Skan * does. 1891169689Skan * 1892169689Skan * The Linux driver uses a much more complex scheme whereby several 1893169689Skan * header records are kept for each queue. We use a couple of generic 1894169689Skan * list manipulation functions which 'know' the size of each list by 1895169689Skan * virtue of a table. 1896169689Skan */ 1897169689Skan qoffset = offsetof(struct aac_common, ac_qbuf) + AAC_QUEUE_ALIGN; 1898169689Skan qoffset &= ~(AAC_QUEUE_ALIGN - 1); 1899169689Skan sc->aac_queues = 1900169689Skan (struct aac_queue_table *)((uintptr_t)sc->aac_common + qoffset); 1901169689Skan ip->CommHeaderAddress = sc->aac_common_busaddr + qoffset; 1902169689Skan 1903169689Skan sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = 1904169689Skan AAC_HOST_NORM_CMD_ENTRIES; 1905169689Skan sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] = 1906169689Skan AAC_HOST_NORM_CMD_ENTRIES; 1907169689Skan sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] = 1908169689Skan AAC_HOST_HIGH_CMD_ENTRIES; 1909169689Skan sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] = 1910169689Skan AAC_HOST_HIGH_CMD_ENTRIES; 1911169689Skan sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] = 1912169689Skan AAC_ADAP_NORM_CMD_ENTRIES; 1913169689Skan sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] = 1914169689Skan AAC_ADAP_NORM_CMD_ENTRIES; 1915169689Skan sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] = 1916169689Skan AAC_ADAP_HIGH_CMD_ENTRIES; 1917169689Skan sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] = 1918169689Skan AAC_ADAP_HIGH_CMD_ENTRIES; 1919169689Skan sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX]= 1920169689Skan AAC_HOST_NORM_RESP_ENTRIES; 1921169689Skan sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX]= 1922169689Skan AAC_HOST_NORM_RESP_ENTRIES; 1923169689Skan sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX]= 1924169689Skan AAC_HOST_HIGH_RESP_ENTRIES; 1925169689Skan sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX]= 1926169689Skan AAC_HOST_HIGH_RESP_ENTRIES; 1927169689Skan sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX]= 1928169689Skan AAC_ADAP_NORM_RESP_ENTRIES; 1929169689Skan sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX]= 1930169689Skan AAC_ADAP_NORM_RESP_ENTRIES; 1931169689Skan sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX]= 1932169689Skan AAC_ADAP_HIGH_RESP_ENTRIES; 1933169689Skan sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX]= 1934169689Skan AAC_ADAP_HIGH_RESP_ENTRIES; 1935169689Skan sc->aac_qentries[AAC_HOST_NORM_CMD_QUEUE] = 1936169689Skan &sc->aac_queues->qt_HostNormCmdQueue[0]; 1937169689Skan sc->aac_qentries[AAC_HOST_HIGH_CMD_QUEUE] = 1938169689Skan &sc->aac_queues->qt_HostHighCmdQueue[0]; 1939169689Skan sc->aac_qentries[AAC_ADAP_NORM_CMD_QUEUE] = 1940169689Skan &sc->aac_queues->qt_AdapNormCmdQueue[0]; 1941169689Skan sc->aac_qentries[AAC_ADAP_HIGH_CMD_QUEUE] = 1942169689Skan &sc->aac_queues->qt_AdapHighCmdQueue[0]; 1943169689Skan sc->aac_qentries[AAC_HOST_NORM_RESP_QUEUE] = 1944169689Skan &sc->aac_queues->qt_HostNormRespQueue[0]; 1945169689Skan sc->aac_qentries[AAC_HOST_HIGH_RESP_QUEUE] = 1946169689Skan &sc->aac_queues->qt_HostHighRespQueue[0]; 1947169689Skan sc->aac_qentries[AAC_ADAP_NORM_RESP_QUEUE] = 1948169689Skan &sc->aac_queues->qt_AdapNormRespQueue[0]; 1949169689Skan sc->aac_qentries[AAC_ADAP_HIGH_RESP_QUEUE] = 1950169689Skan &sc->aac_queues->qt_AdapHighRespQueue[0]; 1951169689Skan 1952169689Skan /* 1953169689Skan * Do controller-type-specific initialisation 1954169689Skan */ 1955169689Skan switch (sc->aac_hwif) { 1956169689Skan case AAC_HWIF_I960RX: 1957169689Skan AAC_SETREG4(sc, AAC_RX_ODBR, ~0); 1958169689Skan break; 1959169689Skan case AAC_HWIF_RKT: 1960169689Skan AAC_SETREG4(sc, AAC_RKT_ODBR, ~0); 1961169689Skan break; 1962169689Skan default: 1963169689Skan break; 1964169689Skan } 1965169689Skan 1966169689Skan /* 1967169689Skan * Give the init structure to the controller. 1968169689Skan */ 1969169689Skan if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT, 1970169689Skan sc->aac_common_busaddr + 1971169689Skan offsetof(struct aac_common, ac_init), 0, 0, 0, 1972169689Skan NULL)) { 1973169689Skan device_printf(sc->aac_dev, 1974169689Skan "error establishing init structure\n"); 1975169689Skan error = EIO; 1976169689Skan goto out; 1977169689Skan } 1978169689Skan 1979169689Skan error = 0; 1980169689Skanout: 1981169689Skan return(error); 1982169689Skan} 1983169689Skan 1984169689Skan/* 1985169689Skan * Send a synchronous command to the controller and wait for a result. 1986169689Skan * Indicate if the controller completed the command with an error status. 1987169689Skan */ 1988169689Skanstatic int 1989169689Skanaac_sync_command(struct aac_softc *sc, u_int32_t command, 1990169689Skan u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, 1991169689Skan u_int32_t *sp) 1992169689Skan{ 1993169689Skan time_t then; 1994169689Skan u_int32_t status; 1995169689Skan 1996169689Skan debug_called(3); 1997169689Skan 1998169689Skan /* populate the mailbox */ 1999169689Skan AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3); 2000169689Skan 2001169689Skan /* ensure the sync command doorbell flag is cleared */ 2002169689Skan AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); 2003169689Skan 2004169689Skan /* then set it to signal the adapter */ 2005169689Skan AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND); 2006169689Skan 2007169689Skan /* spin waiting for the command to complete */ 2008169689Skan then = time_uptime; 2009169689Skan do { 2010169689Skan if (time_uptime > (then + AAC_IMMEDIATE_TIMEOUT)) { 2011169689Skan debug(1, "timed out"); 2012169689Skan return(EIO); 2013169689Skan } 2014169689Skan } while (!(AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND)); 2015169689Skan 2016169689Skan /* clear the completion flag */ 2017169689Skan AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND); 2018169689Skan 2019169689Skan /* get the command status */ 2020169689Skan status = AAC_GET_MAILBOX(sc, 0); 2021169689Skan if (sp != NULL) 2022169689Skan *sp = status; 2023169689Skan 2024169689Skan if (status != AAC_SRB_STS_SUCCESS) 2025169689Skan return (-1); 2026169689Skan return(0); 2027169689Skan} 2028169689Skan 2029169689Skanint 2030169689Skanaac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, 2031169689Skan struct aac_fib *fib, u_int16_t datasize) 2032169689Skan{ 2033169689Skan debug_called(3); 2034169689Skan mtx_assert(&sc->aac_io_lock, MA_OWNED); 2035169689Skan 2036169689Skan if (datasize > AAC_FIB_DATASIZE) 2037169689Skan return(EINVAL); 2038169689Skan 2039169689Skan /* 2040169689Skan * Set up the sync FIB 2041169689Skan */ 2042169689Skan fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED | 2043169689Skan AAC_FIBSTATE_INITIALISED | 2044169689Skan AAC_FIBSTATE_EMPTY; 2045169689Skan fib->Header.XferState |= xferstate; 2046169689Skan fib->Header.Command = command; 2047169689Skan fib->Header.StructType = AAC_FIBTYPE_TFIB; 2048169689Skan fib->Header.Size = sizeof(struct aac_fib) + datasize; 2049169689Skan fib->Header.SenderSize = sizeof(struct aac_fib); 2050169689Skan fib->Header.SenderFibAddress = 0; /* Not needed */ 2051169689Skan fib->Header.ReceiverFibAddress = sc->aac_common_busaddr + 2052169689Skan offsetof(struct aac_common, 2053169689Skan ac_sync_fib); 2054169689Skan 2055169689Skan /* 2056169689Skan * Give the FIB to the controller, wait for a response. 2057169689Skan */ 2058169689Skan if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, 2059169689Skan fib->Header.ReceiverFibAddress, 0, 0, 0, NULL)) { 2060169689Skan debug(2, "IO error"); 2061169689Skan return(EIO); 2062169689Skan } 2063169689Skan 2064169689Skan return (0); 2065169689Skan} 2066169689Skan 2067169689Skan/* 2068169689Skan * Adapter-space FIB queue manipulation 2069169689Skan * 2070169689Skan * Note that the queue implementation here is a little funky; neither the PI or 2071169689Skan * CI will ever be zero. This behaviour is a controller feature. 2072169689Skan */ 2073169689Skanstatic struct { 2074169689Skan int size; 2075169689Skan int notify; 2076169689Skan} aac_qinfo[] = { 2077169689Skan {AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL}, 2078169689Skan {AAC_HOST_HIGH_CMD_ENTRIES, 0}, 2079169689Skan {AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY}, 2080169689Skan {AAC_ADAP_HIGH_CMD_ENTRIES, 0}, 2081169689Skan {AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL}, 2082169689Skan {AAC_HOST_HIGH_RESP_ENTRIES, 0}, 2083169689Skan {AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY}, 2084169689Skan {AAC_ADAP_HIGH_RESP_ENTRIES, 0} 2085169689Skan}; 2086169689Skan 2087169689Skan/* 2088169689Skan * Atomically insert an entry into the nominated queue, returns 0 on success or 2089169689Skan * EBUSY if the queue is full. 2090169689Skan * 2091169689Skan * Note: it would be more efficient to defer notifying the controller in 2092169689Skan * the case where we may be inserting several entries in rapid succession, 2093169689Skan * but implementing this usefully may be difficult (it would involve a 2094169689Skan * separate queue/notify interface). 2095169689Skan */ 2096169689Skanstatic int 2097169689Skanaac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm) 2098169689Skan{ 2099169689Skan u_int32_t pi, ci; 2100169689Skan int error; 2101169689Skan u_int32_t fib_size; 2102169689Skan u_int32_t fib_addr; 2103169689Skan 2104169689Skan debug_called(3); 2105169689Skan 2106169689Skan fib_size = cm->cm_fib->Header.Size; 2107169689Skan fib_addr = cm->cm_fib->Header.ReceiverFibAddress; 2108169689Skan 2109169689Skan /* get the producer/consumer indices */ 2110169689Skan pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]; 2111169689Skan ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]; 2112169689Skan 2113169689Skan /* wrap the queue? */ 2114169689Skan if (pi >= aac_qinfo[queue].size) 2115169689Skan pi = 0; 2116169689Skan 2117169689Skan /* check for queue full */ 2118169689Skan if ((pi + 1) == ci) { 2119169689Skan error = EBUSY; 2120169689Skan goto out; 2121169689Skan } 2122169689Skan 2123169689Skan /* 2124169689Skan * To avoid a race with its completion interrupt, place this command on 2125169689Skan * the busy queue prior to advertising it to the controller. 2126169689Skan */ 2127169689Skan aac_enqueue_busy(cm); 2128169689Skan 2129169689Skan /* populate queue entry */ 2130169689Skan (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size; 2131169689Skan (sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr; 2132169689Skan 2133169689Skan /* update producer index */ 2134169689Skan sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1; 2135169689Skan 2136169689Skan /* notify the adapter if we know how */ 2137169689Skan if (aac_qinfo[queue].notify != 0) 2138169689Skan AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 2139169689Skan 2140169689Skan error = 0; 2141169689Skan 2142169689Skanout: 2143169689Skan return(error); 2144169689Skan} 2145169689Skan 2146169689Skan/* 2147169689Skan * Atomically remove one entry from the nominated queue, returns 0 on 2148169689Skan * success or ENOENT if the queue is empty. 2149169689Skan */ 2150169689Skanstatic int 2151169689Skanaac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size, 2152169689Skan struct aac_fib **fib_addr) 2153169689Skan{ 2154169689Skan u_int32_t pi, ci; 2155169689Skan u_int32_t fib_index; 2156169689Skan int error; 2157169689Skan int notify; 2158169689Skan 2159169689Skan debug_called(3); 2160169689Skan 2161169689Skan /* get the producer/consumer indices */ 2162169689Skan pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]; 2163169689Skan ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]; 2164169689Skan 2165169689Skan /* check for queue empty */ 2166169689Skan if (ci == pi) { 2167169689Skan error = ENOENT; 2168169689Skan goto out; 2169169689Skan } 2170169689Skan 2171169689Skan /* wrap the pi so the following test works */ 2172169689Skan if (pi >= aac_qinfo[queue].size) 2173169689Skan pi = 0; 2174169689Skan 2175169689Skan notify = 0; 2176169689Skan if (ci == pi + 1) 2177169689Skan notify++; 2178169689Skan 2179169689Skan /* wrap the queue? */ 2180169689Skan if (ci >= aac_qinfo[queue].size) 2181169689Skan ci = 0; 2182169689Skan 2183169689Skan /* fetch the entry */ 2184169689Skan *fib_size = (sc->aac_qentries[queue] + ci)->aq_fib_size; 2185169689Skan 2186169689Skan switch (queue) { 2187169689Skan case AAC_HOST_NORM_CMD_QUEUE: 2188169689Skan case AAC_HOST_HIGH_CMD_QUEUE: 2189169689Skan /* 2190169689Skan * The aq_fib_addr is only 32 bits wide so it can't be counted 2191169689Skan * on to hold an address. For AIF's, the adapter assumes 2192169689Skan * that it's giving us an address into the array of AIF fibs. 2193169689Skan * Therefore, we have to convert it to an index. 2194169689Skan */ 2195169689Skan fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr / 2196169689Skan sizeof(struct aac_fib); 2197169689Skan *fib_addr = &sc->aac_common->ac_fibs[fib_index]; 2198169689Skan break; 2199169689Skan 2200169689Skan case AAC_HOST_NORM_RESP_QUEUE: 2201169689Skan case AAC_HOST_HIGH_RESP_QUEUE: 2202169689Skan { 2203169689Skan struct aac_command *cm; 2204169689Skan 2205169689Skan /* 2206169689Skan * As above, an index is used instead of an actual address. 2207169689Skan * Gotta shift the index to account for the fast response 2208169689Skan * bit. No other correction is needed since this value was 2209169689Skan * originally provided by the driver via the SenderFibAddress 2210169689Skan * field. 2211169689Skan */ 2212169689Skan fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr; 2213169689Skan cm = sc->aac_commands + (fib_index >> 2); 2214169689Skan *fib_addr = cm->cm_fib; 2215169689Skan 2216169689Skan /* 2217169689Skan * Is this a fast response? If it is, update the fib fields in 2218169689Skan * local memory since the whole fib isn't DMA'd back up. 2219169689Skan */ 2220169689Skan if (fib_index & 0x01) { 2221169689Skan (*fib_addr)->Header.XferState |= AAC_FIBSTATE_DONEADAP; 2222169689Skan *((u_int32_t*)((*fib_addr)->data)) = AAC_ERROR_NORMAL; 2223169689Skan } 2224169689Skan break; 2225169689Skan } 2226169689Skan default: 2227169689Skan panic("Invalid queue in aac_dequeue_fib()"); 2228169689Skan break; 2229169689Skan } 2230169689Skan 2231169689Skan /* update consumer index */ 2232169689Skan sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1; 2233169689Skan 2234169689Skan /* if we have made the queue un-full, notify the adapter */ 2235169689Skan if (notify && (aac_qinfo[queue].notify != 0)) 2236169689Skan AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 2237169689Skan error = 0; 2238169689Skan 2239169689Skanout: 2240169689Skan return(error); 2241169689Skan} 2242169689Skan 2243169689Skan/* 2244169689Skan * Put our response to an Adapter Initialed Fib on the response queue 2245169689Skan */ 2246169689Skanstatic int 2247169689Skanaac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib) 2248169689Skan{ 2249169689Skan u_int32_t pi, ci; 2250169689Skan int error; 2251169689Skan u_int32_t fib_size; 2252169689Skan u_int32_t fib_addr; 2253169689Skan 2254169689Skan debug_called(1); 2255169689Skan 2256169689Skan /* Tell the adapter where the FIB is */ 2257169689Skan fib_size = fib->Header.Size; 2258169689Skan fib_addr = fib->Header.SenderFibAddress; 2259169689Skan fib->Header.ReceiverFibAddress = fib_addr; 2260169689Skan 2261169689Skan /* get the producer/consumer indices */ 2262169689Skan pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]; 2263169689Skan ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]; 2264169689Skan 2265169689Skan /* wrap the queue? */ 2266169689Skan if (pi >= aac_qinfo[queue].size) 2267169689Skan pi = 0; 2268169689Skan 2269169689Skan /* check for queue full */ 2270169689Skan if ((pi + 1) == ci) { 2271169689Skan error = EBUSY; 2272169689Skan goto out; 2273169689Skan } 2274169689Skan 2275169689Skan /* populate queue entry */ 2276169689Skan (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size; 2277169689Skan (sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr; 2278169689Skan 2279169689Skan /* update producer index */ 2280169689Skan sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1; 2281169689Skan 2282169689Skan /* notify the adapter if we know how */ 2283169689Skan if (aac_qinfo[queue].notify != 0) 2284169689Skan AAC_QNOTIFY(sc, aac_qinfo[queue].notify); 2285169689Skan 2286169689Skan error = 0; 2287169689Skan 2288169689Skanout: 2289169689Skan return(error); 2290169689Skan} 2291169689Skan 2292169689Skan/* 2293169689Skan * Check for commands that have been outstanding for a suspiciously long time, 2294169689Skan * and complain about them. 2295169689Skan */ 2296169689Skanstatic void 2297169689Skanaac_timeout(struct aac_softc *sc) 2298169689Skan{ 2299169689Skan struct aac_command *cm; 2300169689Skan time_t deadline; 2301169689Skan int timedout, code; 2302169689Skan 2303169689Skan /* 2304169689Skan * Traverse the busy command list, bitch about late commands once 2305169689Skan * only. 2306169689Skan */ 2307169689Skan timedout = 0; 2308169689Skan deadline = time_uptime - AAC_CMD_TIMEOUT; 2309169689Skan TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) { 2310169689Skan if ((cm->cm_timestamp < deadline) 2311169689Skan /* && !(cm->cm_flags & AAC_CMD_TIMEDOUT) */) { 2312169689Skan cm->cm_flags |= AAC_CMD_TIMEDOUT; 2313169689Skan device_printf(sc->aac_dev, 2314169689Skan "COMMAND %p TIMEOUT AFTER %d SECONDS\n", 2315169689Skan cm, (int)(time_uptime-cm->cm_timestamp)); 2316169689Skan AAC_PRINT_FIB(sc, cm->cm_fib); 2317169689Skan timedout++; 2318169689Skan } 2319169689Skan } 2320169689Skan 2321169689Skan if (timedout) { 2322169689Skan code = AAC_GET_FWSTATUS(sc); 2323169689Skan if (code != AAC_UP_AND_RUNNING) { 2324169689Skan device_printf(sc->aac_dev, "WARNING! Controller is no " 2325169689Skan "longer running! code= 0x%x\n", code); 2326169689Skan } 2327169689Skan } 2328169689Skan return; 2329169689Skan} 2330169689Skan 2331169689Skan/* 2332169689Skan * Interface Function Vectors 2333169689Skan */ 2334169689Skan 2335169689Skan/* 2336169689Skan * Read the current firmware status word. 2337169689Skan */ 2338169689Skanstatic int 2339169689Skanaac_sa_get_fwstatus(struct aac_softc *sc) 2340169689Skan{ 2341169689Skan debug_called(3); 2342169689Skan 2343169689Skan return(AAC_GETREG4(sc, AAC_SA_FWSTATUS)); 2344169689Skan} 2345169689Skan 2346169689Skanstatic int 2347169689Skanaac_rx_get_fwstatus(struct aac_softc *sc) 2348169689Skan{ 2349169689Skan debug_called(3); 2350169689Skan 2351169689Skan return(AAC_GETREG4(sc, AAC_RX_FWSTATUS)); 2352169689Skan} 2353169689Skan 2354169689Skanstatic int 2355169689Skanaac_fa_get_fwstatus(struct aac_softc *sc) 2356169689Skan{ 2357169689Skan int val; 2358169689Skan 2359169689Skan debug_called(3); 2360169689Skan 2361169689Skan val = AAC_GETREG4(sc, AAC_FA_FWSTATUS); 2362169689Skan return (val); 2363169689Skan} 2364169689Skan 2365169689Skanstatic int 2366169689Skanaac_rkt_get_fwstatus(struct aac_softc *sc) 2367169689Skan{ 2368169689Skan debug_called(3); 2369169689Skan 2370169689Skan return(AAC_GETREG4(sc, AAC_RKT_FWSTATUS)); 2371169689Skan} 2372169689Skan 2373169689Skan/* 2374169689Skan * Notify the controller of a change in a given queue 2375169689Skan */ 2376169689Skan 2377169689Skanstatic void 2378169689Skanaac_sa_qnotify(struct aac_softc *sc, int qbit) 2379169689Skan{ 2380169689Skan debug_called(3); 2381169689Skan 2382169689Skan AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit); 2383169689Skan} 2384169689Skan 2385169689Skanstatic void 2386169689Skanaac_rx_qnotify(struct aac_softc *sc, int qbit) 2387169689Skan{ 2388169689Skan debug_called(3); 2389169689Skan 2390169689Skan AAC_SETREG4(sc, AAC_RX_IDBR, qbit); 2391169689Skan} 2392169689Skan 2393169689Skanstatic void 2394169689Skanaac_fa_qnotify(struct aac_softc *sc, int qbit) 2395169689Skan{ 2396169689Skan debug_called(3); 2397169689Skan 2398169689Skan AAC_SETREG2(sc, AAC_FA_DOORBELL1, qbit); 2399169689Skan AAC_FA_HACK(sc); 2400169689Skan} 2401169689Skan 2402169689Skanstatic void 2403169689Skanaac_rkt_qnotify(struct aac_softc *sc, int qbit) 2404169689Skan{ 2405169689Skan debug_called(3); 2406169689Skan 2407169689Skan AAC_SETREG4(sc, AAC_RKT_IDBR, qbit); 2408169689Skan} 2409169689Skan 2410169689Skan/* 2411169689Skan * Get the interrupt reason bits 2412169689Skan */ 2413169689Skanstatic int 2414169689Skanaac_sa_get_istatus(struct aac_softc *sc) 2415169689Skan{ 2416169689Skan debug_called(3); 2417169689Skan 2418169689Skan return(AAC_GETREG2(sc, AAC_SA_DOORBELL0)); 2419169689Skan} 2420169689Skan 2421169689Skanstatic int 2422169689Skanaac_rx_get_istatus(struct aac_softc *sc) 2423169689Skan{ 2424169689Skan debug_called(3); 2425169689Skan 2426169689Skan return(AAC_GETREG4(sc, AAC_RX_ODBR)); 2427169689Skan} 2428169689Skan 2429169689Skanstatic int 2430169689Skanaac_fa_get_istatus(struct aac_softc *sc) 2431169689Skan{ 2432169689Skan int val; 2433169689Skan 2434169689Skan debug_called(3); 2435169689Skan 2436169689Skan val = AAC_GETREG2(sc, AAC_FA_DOORBELL0); 2437169689Skan return (val); 2438169689Skan} 2439169689Skan 2440169689Skanstatic int 2441169689Skanaac_rkt_get_istatus(struct aac_softc *sc) 2442169689Skan{ 2443169689Skan debug_called(3); 2444169689Skan 2445169689Skan return(AAC_GETREG4(sc, AAC_RKT_ODBR)); 2446169689Skan} 2447169689Skan 2448169689Skan/* 2449169689Skan * Clear some interrupt reason bits 2450169689Skan */ 2451169689Skanstatic void 2452169689Skanaac_sa_clear_istatus(struct aac_softc *sc, int mask) 2453169689Skan{ 2454169689Skan debug_called(3); 2455169689Skan 2456169689Skan AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask); 2457169689Skan} 2458169689Skan 2459169689Skanstatic void 2460169689Skanaac_rx_clear_istatus(struct aac_softc *sc, int mask) 2461169689Skan{ 2462169689Skan debug_called(3); 2463169689Skan 2464169689Skan AAC_SETREG4(sc, AAC_RX_ODBR, mask); 2465169689Skan} 2466169689Skan 2467169689Skanstatic void 2468169689Skanaac_fa_clear_istatus(struct aac_softc *sc, int mask) 2469169689Skan{ 2470169689Skan debug_called(3); 2471169689Skan 2472169689Skan AAC_SETREG2(sc, AAC_FA_DOORBELL0_CLEAR, mask); 2473169689Skan AAC_FA_HACK(sc); 2474169689Skan} 2475169689Skan 2476169689Skanstatic void 2477169689Skanaac_rkt_clear_istatus(struct aac_softc *sc, int mask) 2478169689Skan{ 2479169689Skan debug_called(3); 2480169689Skan 2481169689Skan AAC_SETREG4(sc, AAC_RKT_ODBR, mask); 2482169689Skan} 2483169689Skan 2484169689Skan/* 2485169689Skan * Populate the mailbox and set the command word 2486169689Skan */ 2487169689Skanstatic void 2488169689Skanaac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command, 2489169689Skan u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3) 2490169689Skan{ 2491169689Skan debug_called(4); 2492169689Skan 2493169689Skan AAC_SETREG4(sc, AAC_SA_MAILBOX, command); 2494169689Skan AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0); 2495169689Skan AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1); 2496169689Skan AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2); 2497169689Skan AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3); 2498169689Skan} 2499169689Skan 2500169689Skanstatic void 2501169689Skanaac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command, 2502169689Skan u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3) 2503169689Skan{ 2504169689Skan debug_called(4); 2505169689Skan 2506169689Skan AAC_SETREG4(sc, AAC_RX_MAILBOX, command); 2507169689Skan AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0); 2508169689Skan AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1); 2509169689Skan AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2); 2510169689Skan AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3); 2511169689Skan} 2512169689Skan 2513169689Skanstatic void 2514169689Skanaac_fa_set_mailbox(struct aac_softc *sc, u_int32_t command, 2515169689Skan u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3) 2516169689Skan{ 2517169689Skan debug_called(4); 2518169689Skan 2519169689Skan AAC_SETREG4(sc, AAC_FA_MAILBOX, command); 2520169689Skan AAC_FA_HACK(sc); 2521169689Skan AAC_SETREG4(sc, AAC_FA_MAILBOX + 4, arg0); 2522169689Skan AAC_FA_HACK(sc); 2523169689Skan AAC_SETREG4(sc, AAC_FA_MAILBOX + 8, arg1); 2524169689Skan AAC_FA_HACK(sc); 2525169689Skan AAC_SETREG4(sc, AAC_FA_MAILBOX + 12, arg2); 2526169689Skan AAC_FA_HACK(sc); 2527169689Skan AAC_SETREG4(sc, AAC_FA_MAILBOX + 16, arg3); 2528169689Skan AAC_FA_HACK(sc); 2529169689Skan} 2530169689Skan 2531169689Skanstatic void 2532169689Skanaac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0, 2533169689Skan u_int32_t arg1, u_int32_t arg2, u_int32_t arg3) 2534169689Skan{ 2535169689Skan debug_called(4); 2536169689Skan 2537169689Skan AAC_SETREG4(sc, AAC_RKT_MAILBOX, command); 2538169689Skan AAC_SETREG4(sc, AAC_RKT_MAILBOX + 4, arg0); 2539169689Skan AAC_SETREG4(sc, AAC_RKT_MAILBOX + 8, arg1); 2540169689Skan AAC_SETREG4(sc, AAC_RKT_MAILBOX + 12, arg2); 2541169689Skan AAC_SETREG4(sc, AAC_RKT_MAILBOX + 16, arg3); 2542169689Skan} 2543169689Skan 2544169689Skan/* 2545169689Skan * Fetch the immediate command status word 2546169689Skan */ 2547169689Skanstatic int 2548169689Skanaac_sa_get_mailbox(struct aac_softc *sc, int mb) 2549169689Skan{ 2550169689Skan debug_called(4); 2551169689Skan 2552169689Skan return(AAC_GETREG4(sc, AAC_SA_MAILBOX + (mb * 4))); 2553169689Skan} 2554169689Skan 2555169689Skanstatic int 2556169689Skanaac_rx_get_mailbox(struct aac_softc *sc, int mb) 2557169689Skan{ 2558169689Skan debug_called(4); 2559169689Skan 2560169689Skan return(AAC_GETREG4(sc, AAC_RX_MAILBOX + (mb * 4))); 2561169689Skan} 2562169689Skan 2563169689Skanstatic int 2564169689Skanaac_fa_get_mailbox(struct aac_softc *sc, int mb) 2565169689Skan{ 2566169689Skan int val; 2567169689Skan 2568169689Skan debug_called(4); 2569169689Skan 2570169689Skan val = AAC_GETREG4(sc, AAC_FA_MAILBOX + (mb * 4)); 2571169689Skan return (val); 2572169689Skan} 2573169689Skan 2574169689Skanstatic int 2575169689Skanaac_rkt_get_mailbox(struct aac_softc *sc, int mb) 2576169689Skan{ 2577169689Skan debug_called(4); 2578169689Skan 2579169689Skan return(AAC_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4))); 2580169689Skan} 2581169689Skan 2582169689Skan/* 2583169689Skan * Set/clear interrupt masks 2584169689Skan */ 2585169689Skanstatic void 2586169689Skanaac_sa_set_interrupts(struct aac_softc *sc, int enable) 2587169689Skan{ 2588169689Skan debug(2, "%sable interrupts", enable ? "en" : "dis"); 2589169689Skan 2590169689Skan if (enable) { 2591169689Skan AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS); 2592169689Skan } else { 2593169689Skan AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0); 2594169689Skan } 2595169689Skan} 2596169689Skan 2597169689Skanstatic void 2598169689Skanaac_rx_set_interrupts(struct aac_softc *sc, int enable) 2599169689Skan{ 2600169689Skan debug(2, "%sable interrupts", enable ? "en" : "dis"); 2601169689Skan 2602169689Skan if (enable) { 2603169689Skan if (sc->flags & AAC_FLAGS_NEW_COMM) 2604169689Skan AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INT_NEW_COMM); 2605169689Skan else 2606169689Skan AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS); 2607169689Skan } else { 2608169689Skan AAC_SETREG4(sc, AAC_RX_OIMR, ~0); 2609169689Skan } 2610169689Skan} 2611169689Skan 2612169689Skanstatic void 2613169689Skanaac_fa_set_interrupts(struct aac_softc *sc, int enable) 2614169689Skan{ 2615169689Skan debug(2, "%sable interrupts", enable ? "en" : "dis"); 2616169689Skan 2617169689Skan if (enable) { 2618169689Skan AAC_SETREG2((sc), AAC_FA_MASK0_CLEAR, AAC_DB_INTERRUPTS); 2619169689Skan AAC_FA_HACK(sc); 2620169689Skan } else { 2621169689Skan AAC_SETREG2((sc), AAC_FA_MASK0, ~0); 2622169689Skan AAC_FA_HACK(sc); 2623169689Skan } 2624169689Skan} 2625169689Skan 2626169689Skanstatic void 2627169689Skanaac_rkt_set_interrupts(struct aac_softc *sc, int enable) 2628169689Skan{ 2629169689Skan debug(2, "%sable interrupts", enable ? "en" : "dis"); 2630169689Skan 2631169689Skan if (enable) { 2632169689Skan if (sc->flags & AAC_FLAGS_NEW_COMM) 2633169689Skan AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INT_NEW_COMM); 2634169689Skan else 2635169689Skan AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS); 2636169689Skan } else { 2637169689Skan AAC_SETREG4(sc, AAC_RKT_OIMR, ~0); 2638169689Skan } 2639169689Skan} 2640169689Skan 2641169689Skan/* 2642169689Skan * New comm. interface: Send command functions 2643169689Skan */ 2644169689Skanstatic int 2645169689Skanaac_rx_send_command(struct aac_softc *sc, struct aac_command *cm) 2646169689Skan{ 2647169689Skan u_int32_t index, device; 2648169689Skan 2649169689Skan debug(2, "send command (new comm.)"); 2650169689Skan 2651169689Skan index = AAC_GETREG4(sc, AAC_RX_IQUE); 2652169689Skan if (index == 0xffffffffL) 2653169689Skan index = AAC_GETREG4(sc, AAC_RX_IQUE); 2654169689Skan if (index == 0xffffffffL) 2655169689Skan return index; 2656169689Skan aac_enqueue_busy(cm); 2657169689Skan device = index; 2658169689Skan AAC_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys & 0xffffffffUL)); 2659169689Skan device += 4; 2660169689Skan AAC_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys >> 32)); 2661169689Skan device += 4; 2662169689Skan AAC_SETREG4(sc, device, cm->cm_fib->Header.Size); 2663169689Skan AAC_SETREG4(sc, AAC_RX_IQUE, index); 2664169689Skan return 0; 2665169689Skan} 2666169689Skan 2667169689Skanstatic int 2668169689Skanaac_rkt_send_command(struct aac_softc *sc, struct aac_command *cm) 2669169689Skan{ 2670169689Skan u_int32_t index, device; 2671169689Skan 2672169689Skan debug(2, "send command (new comm.)"); 2673169689Skan 2674169689Skan index = AAC_GETREG4(sc, AAC_RKT_IQUE); 2675169689Skan if (index == 0xffffffffL) 2676169689Skan index = AAC_GETREG4(sc, AAC_RKT_IQUE); 2677169689Skan if (index == 0xffffffffL) 2678169689Skan return index; 2679169689Skan aac_enqueue_busy(cm); 2680169689Skan device = index; 2681169689Skan AAC_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys & 0xffffffffUL)); 2682169689Skan device += 4; 2683169689Skan AAC_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys >> 32)); 2684169689Skan device += 4; 2685169689Skan AAC_SETREG4(sc, device, cm->cm_fib->Header.Size); 2686169689Skan AAC_SETREG4(sc, AAC_RKT_IQUE, index); 2687169689Skan return 0; 2688169689Skan} 2689169689Skan 2690169689Skan/* 2691169689Skan * New comm. interface: get, set outbound queue index 2692169689Skan */ 2693169689Skanstatic int 2694169689Skanaac_rx_get_outb_queue(struct aac_softc *sc) 2695169689Skan{ 2696169689Skan debug_called(3); 2697169689Skan 2698169689Skan return(AAC_GETREG4(sc, AAC_RX_OQUE)); 2699169689Skan} 2700169689Skan 2701169689Skanstatic int 2702169689Skanaac_rkt_get_outb_queue(struct aac_softc *sc) 2703169689Skan{ 2704169689Skan debug_called(3); 2705169689Skan 2706169689Skan return(AAC_GETREG4(sc, AAC_RKT_OQUE)); 2707169689Skan} 2708169689Skan 2709169689Skanstatic void 2710169689Skanaac_rx_set_outb_queue(struct aac_softc *sc, int index) 2711169689Skan{ 2712169689Skan debug_called(3); 2713169689Skan 2714169689Skan AAC_SETREG4(sc, AAC_RX_OQUE, index); 2715169689Skan} 2716169689Skan 2717169689Skanstatic void 2718169689Skanaac_rkt_set_outb_queue(struct aac_softc *sc, int index) 2719169689Skan{ 2720169689Skan debug_called(3); 2721169689Skan 2722169689Skan AAC_SETREG4(sc, AAC_RKT_OQUE, index); 2723169689Skan} 2724169689Skan 2725169689Skan/* 2726169689Skan * Debugging and Diagnostics 2727169689Skan */ 2728169689Skan 2729169689Skan/* 2730169689Skan * Print some information about the controller. 2731169689Skan */ 2732169689Skanstatic void 2733169689Skanaac_describe_controller(struct aac_softc *sc) 2734169689Skan{ 2735169689Skan struct aac_fib *fib; 2736169689Skan struct aac_adapter_info *info; 2737169689Skan char *adapter_type = "Adaptec RAID controller"; 2738169689Skan 2739169689Skan debug_called(2); 2740169689Skan 2741169689Skan mtx_lock(&sc->aac_io_lock); 2742169689Skan aac_alloc_sync_fib(sc, &fib); 2743169689Skan 2744169689Skan if (sc->supported_options & AAC_SUPPORTED_SUPPLEMENT_ADAPTER_INFO) { 2745169689Skan fib->data[0] = 0; 2746169689Skan if (aac_sync_fib(sc, RequestSupplementAdapterInfo, 0, fib, 1)) 2747169689Skan device_printf(sc->aac_dev, 2748169689Skan "RequestSupplementAdapterInfo failed\n"); 2749169689Skan else 2750169689Skan adapter_type = ((struct aac_supplement_adapter_info *) 2751169689Skan &fib->data[0])->AdapterTypeText; 2752169689Skan } 2753169689Skan device_printf(sc->aac_dev, "%s, aac driver %d.%d.%d-%d\n", 2754169689Skan adapter_type, 2755169689Skan AAC_DRIVER_VERSION >> 24, 2756169689Skan (AAC_DRIVER_VERSION >> 16) & 0xFF, 2757169689Skan AAC_DRIVER_VERSION & 0xFF, 2758169689Skan AAC_DRIVER_BUILD); 2759169689Skan 2760169689Skan fib->data[0] = 0; 2761169689Skan if (aac_sync_fib(sc, RequestAdapterInfo, 0, fib, 1)) { 2762169689Skan device_printf(sc->aac_dev, "RequestAdapterInfo failed\n"); 2763169689Skan aac_release_sync_fib(sc); 2764169689Skan mtx_unlock(&sc->aac_io_lock); 2765169689Skan return; 2766169689Skan } 2767169689Skan 2768169689Skan /* save the kernel revision structure for later use */ 2769169689Skan info = (struct aac_adapter_info *)&fib->data[0]; 2770169689Skan sc->aac_revision = info->KernelRevision; 2771169689Skan 2772169689Skan 2773169689Skan if (bootverbose) { 2774169689Skan device_printf(sc->aac_dev, "%s %dMHz, %dMB memory " 2775169689Skan "(%dMB cache, %dMB execution), %s\n", 2776169689Skan aac_describe_code(aac_cpu_variant, info->CpuVariant), 2777169689Skan info->ClockSpeed, info->TotalMem / (1024 * 1024), 2778169689Skan info->BufferMem / (1024 * 1024), 2779169689Skan info->ExecutionMem / (1024 * 1024), 2780169689Skan aac_describe_code(aac_battery_platform, 2781169689Skan info->batteryPlatform)); 2782169689Skan 2783169689Skan device_printf(sc->aac_dev, 2784169689Skan "Kernel %d.%d-%d, Build %d, S/N %6X\n", 2785169689Skan info->KernelRevision.external.comp.major, 2786169689Skan info->KernelRevision.external.comp.minor, 2787169689Skan info->KernelRevision.external.comp.dash, 2788169689Skan info->KernelRevision.buildNumber, 2789169689Skan (u_int32_t)(info->SerialNumber & 0xffffff)); 2790169689Skan 2791169689Skan device_printf(sc->aac_dev, "Supported Options=%b\n", 2792169689Skan sc->supported_options, 2793169689Skan "\20" 2794169689Skan "\1SNAPSHOT" 2795169689Skan "\2CLUSTERS" 2796169689Skan "\3WCACHE" 2797169689Skan "\4DATA64" 2798169689Skan "\5HOSTTIME" 2799169689Skan "\6RAID50" 2800169689Skan "\7WINDOW4GB" 2801169689Skan "\10SCSIUPGD" 2802169689Skan "\11SOFTERR" 2803169689Skan "\12NORECOND" 2804169689Skan "\13SGMAP64" 2805169689Skan "\14ALARM" 2806169689Skan "\15NONDASD" 2807169689Skan "\16SCSIMGT" 2808169689Skan "\17RAIDSCSI" 2809169689Skan "\21ADPTINFO" 2810169689Skan "\22NEWCOMM" 2811169689Skan "\23ARRAY64BIT" 2812169689Skan "\24HEATSENSOR"); 2813169689Skan } 2814169689Skan aac_release_sync_fib(sc); 2815169689Skan mtx_unlock(&sc->aac_io_lock); 2816169689Skan} 2817169689Skan 2818169689Skan/* 2819169689Skan * Look up a text description of a numeric error code and return a pointer to 2820169689Skan * same. 2821169689Skan */ 2822169689Skanstatic char * 2823169689Skanaac_describe_code(struct aac_code_lookup *table, u_int32_t code) 2824169689Skan{ 2825169689Skan int i; 2826169689Skan 2827169689Skan for (i = 0; table[i].string != NULL; i++) 2828169689Skan if (table[i].code == code) 2829169689Skan return(table[i].string); 2830169689Skan return(table[i + 1].string); 2831169689Skan} 2832169689Skan 2833169689Skan/* 2834169689Skan * Management Interface 2835169689Skan */ 2836169689Skan 2837169689Skanstatic int 2838169689Skanaac_open(struct cdev *dev, int flags, int fmt, d_thread_t *td) 2839169689Skan{ 2840169689Skan struct aac_softc *sc; 2841169689Skan 2842169689Skan debug_called(2); 2843169689Skan 2844169689Skan sc = dev->si_drv1; 2845169689Skan sc->aac_open_cnt++; 2846169689Skan sc->aac_state |= AAC_STATE_OPEN; 2847169689Skan 2848169689Skan return 0; 2849169689Skan} 2850169689Skan 2851169689Skanstatic int 2852169689Skanaac_close(struct cdev *dev, int flags, int fmt, d_thread_t *td) 2853169689Skan{ 2854169689Skan struct aac_softc *sc; 2855169689Skan 2856169689Skan debug_called(2); 2857169689Skan 2858169689Skan sc = dev->si_drv1; 2859169689Skan sc->aac_open_cnt--; 2860169689Skan /* Mark this unit as no longer open */ 2861169689Skan if (sc->aac_open_cnt == 0) 2862169689Skan sc->aac_state &= ~AAC_STATE_OPEN; 2863169689Skan 2864169689Skan return 0; 2865169689Skan} 2866169689Skan 2867169689Skanstatic int 2868169689Skanaac_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td) 2869169689Skan{ 2870169689Skan union aac_statrequest *as; 2871169689Skan struct aac_softc *sc; 2872169689Skan int error = 0; 2873169689Skan 2874169689Skan debug_called(2); 2875169689Skan 2876169689Skan as = (union aac_statrequest *)arg; 2877169689Skan sc = dev->si_drv1; 2878169689Skan 2879169689Skan switch (cmd) { 2880169689Skan case AACIO_STATS: 2881169689Skan switch (as->as_item) { 2882169689Skan case AACQ_FREE: 2883169689Skan case AACQ_BIO: 2884169689Skan case AACQ_READY: 2885169689Skan case AACQ_BUSY: 2886169689Skan bcopy(&sc->aac_qstat[as->as_item], &as->as_qstat, 2887169689Skan sizeof(struct aac_qstat)); 2888169689Skan break; 2889169689Skan default: 2890169689Skan error = ENOENT; 2891169689Skan break; 2892169689Skan } 2893169689Skan break; 2894169689Skan 2895169689Skan case FSACTL_SENDFIB: 2896169689Skan case FSACTL_SEND_LARGE_FIB: 2897169689Skan arg = *(caddr_t*)arg; 2898169689Skan case FSACTL_LNX_SENDFIB: 2899169689Skan case FSACTL_LNX_SEND_LARGE_FIB: 2900169689Skan debug(1, "FSACTL_SENDFIB"); 2901169689Skan error = aac_ioctl_sendfib(sc, arg); 2902169689Skan break; 2903169689Skan case FSACTL_SEND_RAW_SRB: 2904169689Skan arg = *(caddr_t*)arg; 2905169689Skan case FSACTL_LNX_SEND_RAW_SRB: 2906169689Skan debug(1, "FSACTL_SEND_RAW_SRB"); 2907169689Skan error = aac_ioctl_send_raw_srb(sc, arg); 2908169689Skan break; 2909169689Skan case FSACTL_AIF_THREAD: 2910169689Skan case FSACTL_LNX_AIF_THREAD: 2911169689Skan debug(1, "FSACTL_AIF_THREAD"); 2912169689Skan error = EINVAL; 2913169689Skan break; 2914169689Skan case FSACTL_OPEN_GET_ADAPTER_FIB: 2915169689Skan arg = *(caddr_t*)arg; 2916169689Skan case FSACTL_LNX_OPEN_GET_ADAPTER_FIB: 2917169689Skan debug(1, "FSACTL_OPEN_GET_ADAPTER_FIB"); 2918169689Skan error = aac_open_aif(sc, arg); 2919169689Skan break; 2920169689Skan case FSACTL_GET_NEXT_ADAPTER_FIB: 2921169689Skan arg = *(caddr_t*)arg; 2922169689Skan case FSACTL_LNX_GET_NEXT_ADAPTER_FIB: 2923169689Skan debug(1, "FSACTL_GET_NEXT_ADAPTER_FIB"); 2924169689Skan error = aac_getnext_aif(sc, arg); 2925169689Skan break; 2926169689Skan case FSACTL_CLOSE_GET_ADAPTER_FIB: 2927169689Skan arg = *(caddr_t*)arg; 2928169689Skan case FSACTL_LNX_CLOSE_GET_ADAPTER_FIB: 2929169689Skan debug(1, "FSACTL_CLOSE_GET_ADAPTER_FIB"); 2930169689Skan error = aac_close_aif(sc, arg); 2931169689Skan break; 2932169689Skan case FSACTL_MINIPORT_REV_CHECK: 2933169689Skan arg = *(caddr_t*)arg; 2934169689Skan case FSACTL_LNX_MINIPORT_REV_CHECK: 2935169689Skan debug(1, "FSACTL_MINIPORT_REV_CHECK"); 2936169689Skan error = aac_rev_check(sc, arg); 2937169689Skan break; 2938169689Skan case FSACTL_QUERY_DISK: 2939169689Skan arg = *(caddr_t*)arg; 2940169689Skan case FSACTL_LNX_QUERY_DISK: 2941169689Skan debug(1, "FSACTL_QUERY_DISK"); 2942169689Skan error = aac_query_disk(sc, arg); 2943169689Skan break; 2944169689Skan case FSACTL_DELETE_DISK: 2945169689Skan case FSACTL_LNX_DELETE_DISK: 2946169689Skan /* 2947169689Skan * We don't trust the underland to tell us when to delete a 2948169689Skan * container, rather we rely on an AIF coming from the 2949169689Skan * controller 2950169689Skan */ 2951169689Skan error = 0; 2952169689Skan break; 2953169689Skan case FSACTL_GET_PCI_INFO: 2954169689Skan arg = *(caddr_t*)arg; 2955169689Skan case FSACTL_LNX_GET_PCI_INFO: 2956169689Skan debug(1, "FSACTL_GET_PCI_INFO"); 2957169689Skan error = aac_get_pci_info(sc, arg); 2958169689Skan break; 2959169689Skan default: 2960169689Skan debug(1, "unsupported cmd 0x%lx\n", cmd); 2961169689Skan error = EINVAL; 2962169689Skan break; 2963169689Skan } 2964169689Skan return(error); 2965169689Skan} 2966169689Skan 2967169689Skanstatic int 2968169689Skanaac_poll(struct cdev *dev, int poll_events, d_thread_t *td) 2969169689Skan{ 2970169689Skan struct aac_softc *sc; 2971169689Skan int revents; 2972169689Skan 2973169689Skan sc = dev->si_drv1; 2974169689Skan revents = 0; 2975169689Skan 2976169689Skan mtx_lock(&sc->aac_aifq_lock); 2977169689Skan if ((poll_events & (POLLRDNORM | POLLIN)) != 0) { 2978169689Skan if (sc->aifq_idx != 0 || sc->aifq_filled) 2979169689Skan revents |= poll_events & (POLLIN | POLLRDNORM); 2980169689Skan } 2981169689Skan mtx_unlock(&sc->aac_aifq_lock); 2982169689Skan 2983169689Skan if (revents == 0) { 2984169689Skan if (poll_events & (POLLIN | POLLRDNORM)) 2985169689Skan selrecord(td, &sc->rcv_select); 2986169689Skan } 2987169689Skan 2988169689Skan return (revents); 2989169689Skan} 2990169689Skan 2991169689Skanstatic void 2992169689Skanaac_ioctl_event(struct aac_softc *sc, struct aac_event *event, void *arg) 2993169689Skan{ 2994169689Skan 2995169689Skan switch (event->ev_type) { 2996169689Skan case AAC_EVENT_CMFREE: 2997169689Skan mtx_assert(&sc->aac_io_lock, MA_OWNED); 2998169689Skan if (aac_alloc_command(sc, (struct aac_command **)arg)) { 2999169689Skan aac_add_event(sc, event); 3000169689Skan return; 3001169689Skan } 3002169689Skan free(event, M_AACBUF); 3003169689Skan wakeup(arg); 3004169689Skan break; 3005169689Skan default: 3006169689Skan break; 3007169689Skan } 3008169689Skan} 3009169689Skan 3010169689Skan/* 3011169689Skan * Send a FIB supplied from userspace 3012169689Skan */ 3013169689Skanstatic int 3014169689Skanaac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib) 3015169689Skan{ 3016169689Skan struct aac_command *cm; 3017169689Skan int size, error; 3018169689Skan 3019169689Skan debug_called(2); 3020169689Skan 3021169689Skan cm = NULL; 3022169689Skan 3023169689Skan /* 3024169689Skan * Get a command 3025169689Skan */ 3026169689Skan mtx_lock(&sc->aac_io_lock); 3027169689Skan if (aac_alloc_command(sc, &cm)) { 3028169689Skan struct aac_event *event; 3029169689Skan 3030169689Skan event = malloc(sizeof(struct aac_event), M_AACBUF, 3031169689Skan M_NOWAIT | M_ZERO); 3032169689Skan if (event == NULL) { 3033169689Skan error = EBUSY; 3034169689Skan mtx_unlock(&sc->aac_io_lock); 3035169689Skan goto out; 3036169689Skan } 3037169689Skan event->ev_type = AAC_EVENT_CMFREE; 3038169689Skan event->ev_callback = aac_ioctl_event; 3039169689Skan event->ev_arg = &cm; 3040169689Skan aac_add_event(sc, event); 3041169689Skan msleep(&cm, &sc->aac_io_lock, 0, "sendfib", 0); 3042169689Skan } 3043169689Skan mtx_unlock(&sc->aac_io_lock); 3044169689Skan 3045169689Skan /* 3046169689Skan * Fetch the FIB header, then re-copy to get data as well. 3047169689Skan */ 3048169689Skan if ((error = copyin(ufib, cm->cm_fib, 3049169689Skan sizeof(struct aac_fib_header))) != 0) 3050169689Skan goto out; 3051169689Skan size = cm->cm_fib->Header.Size + sizeof(struct aac_fib_header); 3052169689Skan if (size > sc->aac_max_fib_size) { 3053169689Skan device_printf(sc->aac_dev, "incoming FIB oversized (%d > %d)\n", 3054169689Skan size, sc->aac_max_fib_size); 3055169689Skan size = sc->aac_max_fib_size; 3056169689Skan } 3057169689Skan if ((error = copyin(ufib, cm->cm_fib, size)) != 0) 3058169689Skan goto out; 3059169689Skan cm->cm_fib->Header.Size = size; 3060169689Skan cm->cm_timestamp = time_uptime; 3061169689Skan 3062169689Skan /* 3063169689Skan * Pass the FIB to the controller, wait for it to complete. 3064169689Skan */ 3065169689Skan mtx_lock(&sc->aac_io_lock); 3066169689Skan error = aac_wait_command(cm); 3067169689Skan mtx_unlock(&sc->aac_io_lock); 3068169689Skan if (error != 0) { 3069169689Skan device_printf(sc->aac_dev, 3070169689Skan "aac_wait_command return %d\n", error); 3071169689Skan goto out; 3072169689Skan } 3073169689Skan 3074169689Skan /* 3075169689Skan * Copy the FIB and data back out to the caller. 3076169689Skan */ 3077169689Skan size = cm->cm_fib->Header.Size; 3078169689Skan if (size > sc->aac_max_fib_size) { 3079169689Skan device_printf(sc->aac_dev, "outbound FIB oversized (%d > %d)\n", 3080169689Skan size, sc->aac_max_fib_size); 3081169689Skan size = sc->aac_max_fib_size; 3082169689Skan } 3083169689Skan error = copyout(cm->cm_fib, ufib, size); 3084169689Skan 3085169689Skanout: 3086169689Skan if (cm != NULL) { 3087169689Skan mtx_lock(&sc->aac_io_lock); 3088169689Skan aac_release_command(cm); 3089169689Skan mtx_unlock(&sc->aac_io_lock); 3090169689Skan } 3091169689Skan return(error); 3092169689Skan} 3093169689Skan 3094169689Skan/* 3095169689Skan * Send a passthrough FIB supplied from userspace 3096169689Skan */ 3097169689Skanstatic int 3098169689Skanaac_ioctl_send_raw_srb(struct aac_softc *sc, caddr_t arg) 3099169689Skan{ 3100169689Skan return (EINVAL); 3101169689Skan} 3102169689Skan 3103169689Skan/* 3104169689Skan * Handle an AIF sent to us by the controller; queue it for later reference. 3105169689Skan * If the queue fills up, then drop the older entries. 3106169689Skan */ 3107169689Skanstatic void 3108169689Skanaac_handle_aif(struct aac_softc *sc, struct aac_fib *fib) 3109169689Skan{ 3110169689Skan struct aac_aif_command *aif; 3111169689Skan struct aac_container *co, *co_next; 3112169689Skan struct aac_fib_context *ctx; 3113169689Skan struct aac_mntinfo *mi; 3114169689Skan struct aac_mntinforesp *mir = NULL; 3115169689Skan u_int16_t rsize; 3116169689Skan int next, current, found; 3117169689Skan int count = 0, added = 0, i = 0; 3118169689Skan 3119169689Skan debug_called(2); 3120169689Skan 3121169689Skan aif = (struct aac_aif_command*)&fib->data[0]; 3122169689Skan aac_print_aif(sc, aif); 3123169689Skan 3124169689Skan /* Is it an event that we should care about? */ 3125169689Skan switch (aif->command) { 3126169689Skan case AifCmdEventNotify: 3127169689Skan switch (aif->data.EN.type) { 3128169689Skan case AifEnAddContainer: 3129169689Skan case AifEnDeleteContainer: 3130169689Skan /* 3131169689Skan * A container was added or deleted, but the message 3132169689Skan * doesn't tell us anything else! Re-enumerate the 3133169689Skan * containers and sort things out. 3134169689Skan */ 3135169689Skan aac_alloc_sync_fib(sc, &fib); 3136169689Skan mi = (struct aac_mntinfo *)&fib->data[0]; 3137169689Skan do { 3138169689Skan /* 3139169689Skan * Ask the controller for its containers one at 3140169689Skan * a time. 3141169689Skan * XXX What if the controller's list changes 3142169689Skan * midway through this enumaration? 3143169689Skan * XXX This should be done async. 3144169689Skan */ 3145169689Skan bzero(mi, sizeof(struct aac_mntinfo)); 3146169689Skan mi->Command = VM_NameServe; 3147169689Skan mi->MntType = FT_FILESYS; 3148169689Skan mi->MntCount = i; 3149169689Skan rsize = sizeof(mir); 3150169689Skan if (aac_sync_fib(sc, ContainerCommand, 0, fib, 3151169689Skan sizeof(struct aac_mntinfo))) { 3152169689Skan printf("Error probing container %d\n", 3153169689Skan i); 3154169689Skan continue; 3155169689Skan } 3156169689Skan mir = (struct aac_mntinforesp *)&fib->data[0]; 3157169689Skan /* XXX Need to check if count changed */ 3158169689Skan count = mir->MntRespCount; 3159169689Skan /* 3160169689Skan * Check the container against our list. 3161169689Skan * co->co_found was already set to 0 in a 3162169689Skan * previous run. 3163169689Skan */ 3164169689Skan if ((mir->Status == ST_OK) && 3165169689Skan (mir->MntTable[0].VolType != CT_NONE)) { 3166169689Skan found = 0; 3167169689Skan TAILQ_FOREACH(co, 3168169689Skan &sc->aac_container_tqh, 3169169689Skan co_link) { 3170169689Skan if (co->co_mntobj.ObjectId == 3171169689Skan mir->MntTable[0].ObjectId) { 3172169689Skan co->co_found = 1; 3173169689Skan found = 1; 3174169689Skan break; 3175169689Skan } 3176169689Skan } 3177169689Skan /* 3178169689Skan * If the container matched, continue 3179169689Skan * in the list. 3180169689Skan */ 3181169689Skan if (found) { 3182169689Skan i++; 3183169689Skan continue; 3184169689Skan } 3185169689Skan 3186169689Skan /* 3187169689Skan * This is a new container. Do all the 3188169689Skan * appropriate things to set it up. 3189169689Skan */ 3190169689Skan aac_add_container(sc, mir, 1); 3191169689Skan added = 1; 3192169689Skan } 3193169689Skan i++; 3194169689Skan } while ((i < count) && (i < AAC_MAX_CONTAINERS)); 3195169689Skan aac_release_sync_fib(sc); 3196169689Skan 3197169689Skan /* 3198169689Skan * Go through our list of containers and see which ones 3199169689Skan * were not marked 'found'. Since the controller didn't 3200169689Skan * list them they must have been deleted. Do the 3201169689Skan * appropriate steps to destroy the device. Also reset 3202169689Skan * the co->co_found field. 3203169689Skan */ 3204169689Skan co = TAILQ_FIRST(&sc->aac_container_tqh); 3205169689Skan while (co != NULL) { 3206169689Skan if (co->co_found == 0) { 3207169689Skan mtx_unlock(&sc->aac_io_lock); 3208169689Skan mtx_lock(&Giant); 3209169689Skan device_delete_child(sc->aac_dev, 3210169689Skan co->co_disk); 3211169689Skan mtx_unlock(&Giant); 3212169689Skan mtx_lock(&sc->aac_io_lock); 3213169689Skan co_next = TAILQ_NEXT(co, co_link); 3214169689Skan mtx_lock(&sc->aac_container_lock); 3215169689Skan TAILQ_REMOVE(&sc->aac_container_tqh, co, 3216169689Skan co_link); 3217169689Skan mtx_unlock(&sc->aac_container_lock); 3218169689Skan free(co, M_AACBUF); 3219169689Skan co = co_next; 3220169689Skan } else { 3221169689Skan co->co_found = 0; 3222169689Skan co = TAILQ_NEXT(co, co_link); 3223169689Skan } 3224169689Skan } 3225169689Skan 3226169689Skan /* Attach the newly created containers */ 3227169689Skan if (added) { 3228169689Skan mtx_unlock(&sc->aac_io_lock); 3229169689Skan mtx_lock(&Giant); 3230169689Skan bus_generic_attach(sc->aac_dev); 3231169689Skan mtx_unlock(&Giant); 3232169689Skan mtx_lock(&sc->aac_io_lock); 3233169689Skan } 3234169689Skan 3235169689Skan break; 3236169689Skan 3237169689Skan default: 3238169689Skan break; 3239169689Skan } 3240169689Skan 3241169689Skan default: 3242169689Skan break; 3243169689Skan } 3244169689Skan 3245169689Skan /* Copy the AIF data to the AIF queue for ioctl retrieval */ 3246169689Skan mtx_lock(&sc->aac_aifq_lock); 3247169689Skan current = sc->aifq_idx; 3248169689Skan next = (current + 1) % AAC_AIFQ_LENGTH; 3249169689Skan if (next == 0) 3250169689Skan sc->aifq_filled = 1; 3251169689Skan bcopy(fib, &sc->aac_aifq[current], sizeof(struct aac_fib)); 3252169689Skan /* modify AIF contexts */ 3253169689Skan if (sc->aifq_filled) { 3254169689Skan for (ctx = sc->fibctx; ctx; ctx = ctx->next) { 3255169689Skan if (next == ctx->ctx_idx) 3256169689Skan ctx->ctx_wrap = 1; 3257169689Skan else if (current == ctx->ctx_idx && ctx->ctx_wrap) 3258169689Skan ctx->ctx_idx = next; 3259169689Skan } 3260169689Skan } 3261169689Skan sc->aifq_idx = next; 3262169689Skan /* On the off chance that someone is sleeping for an aif... */ 3263169689Skan if (sc->aac_state & AAC_STATE_AIF_SLEEPER) 3264169689Skan wakeup(sc->aac_aifq); 3265169689Skan /* Wakeup any poll()ers */ 3266169689Skan selwakeuppri(&sc->rcv_select, PRIBIO); 3267169689Skan mtx_unlock(&sc->aac_aifq_lock); 3268169689Skan 3269169689Skan return; 3270169689Skan} 3271169689Skan 3272169689Skan/* 3273169689Skan * Return the Revision of the driver to userspace and check to see if the 3274169689Skan * userspace app is possibly compatible. This is extremely bogus since 3275169689Skan * our driver doesn't follow Adaptec's versioning system. Cheat by just 3276169689Skan * returning what the card reported. 3277169689Skan */ 3278169689Skanstatic int 3279169689Skanaac_rev_check(struct aac_softc *sc, caddr_t udata) 3280169689Skan{ 3281169689Skan struct aac_rev_check rev_check; 3282169689Skan struct aac_rev_check_resp rev_check_resp; 3283169689Skan int error = 0; 3284169689Skan 3285169689Skan debug_called(2); 3286169689Skan 3287169689Skan /* 3288169689Skan * Copyin the revision struct from userspace 3289169689Skan */ 3290169689Skan if ((error = copyin(udata, (caddr_t)&rev_check, 3291169689Skan sizeof(struct aac_rev_check))) != 0) { 3292169689Skan return error; 3293169689Skan } 3294169689Skan 3295169689Skan debug(2, "Userland revision= %d\n", 3296169689Skan rev_check.callingRevision.buildNumber); 3297169689Skan 3298169689Skan /* 3299169689Skan * Doctor up the response struct. 3300169689Skan */ 3301169689Skan rev_check_resp.possiblyCompatible = 1; 3302169689Skan rev_check_resp.adapterSWRevision.external.ul = 3303169689Skan sc->aac_revision.external.ul; 3304169689Skan rev_check_resp.adapterSWRevision.buildNumber = 3305169689Skan sc->aac_revision.buildNumber; 3306169689Skan 3307169689Skan return(copyout((caddr_t)&rev_check_resp, udata, 3308169689Skan sizeof(struct aac_rev_check_resp))); 3309169689Skan} 3310169689Skan 3311169689Skan/* 3312169689Skan * Pass the fib context to the caller 3313169689Skan */ 3314169689Skanstatic int 3315169689Skanaac_open_aif(struct aac_softc *sc, caddr_t arg) 3316169689Skan{ 3317169689Skan struct aac_fib_context *fibctx, *ctx; 3318169689Skan int error = 0; 3319169689Skan 3320169689Skan debug_called(2); 3321169689Skan 3322169689Skan fibctx = malloc(sizeof(struct aac_fib_context), M_AACBUF, M_NOWAIT|M_ZERO); 3323169689Skan if (fibctx == NULL) 3324169689Skan return (ENOMEM); 3325169689Skan 3326169689Skan mtx_lock(&sc->aac_aifq_lock); 3327169689Skan /* all elements are already 0, add to queue */ 3328169689Skan if (sc->fibctx == NULL) 3329169689Skan sc->fibctx = fibctx; 3330169689Skan else { 3331169689Skan for (ctx = sc->fibctx; ctx->next; ctx = ctx->next) 3332169689Skan ; 3333169689Skan ctx->next = fibctx; 3334169689Skan fibctx->prev = ctx; 3335169689Skan } 3336169689Skan 3337169689Skan /* evaluate unique value */ 3338169689Skan fibctx->unique = (*(u_int32_t *)&fibctx & 0xffffffff); 3339169689Skan ctx = sc->fibctx; 3340169689Skan while (ctx != fibctx) { 3341169689Skan if (ctx->unique == fibctx->unique) { 3342169689Skan fibctx->unique++; 3343169689Skan ctx = sc->fibctx; 3344169689Skan } else { 3345169689Skan ctx = ctx->next; 3346169689Skan } 3347169689Skan } 3348169689Skan mtx_unlock(&sc->aac_aifq_lock); 3349169689Skan 3350169689Skan error = copyout(&fibctx->unique, (void *)arg, sizeof(u_int32_t)); 3351169689Skan if (error) 3352169689Skan aac_close_aif(sc, (caddr_t)ctx); 3353169689Skan return error; 3354169689Skan} 3355169689Skan 3356169689Skan/* 3357169689Skan * Close the caller's fib context 3358169689Skan */ 3359169689Skanstatic int 3360169689Skanaac_close_aif(struct aac_softc *sc, caddr_t arg) 3361169689Skan{ 3362169689Skan struct aac_fib_context *ctx; 3363169689Skan 3364169689Skan debug_called(2); 3365169689Skan 3366169689Skan mtx_lock(&sc->aac_aifq_lock); 3367169689Skan for (ctx = sc->fibctx; ctx; ctx = ctx->next) { 3368169689Skan if (ctx->unique == *(uint32_t *)&arg) { 3369169689Skan if (ctx == sc->fibctx) 3370169689Skan sc->fibctx = NULL; 3371169689Skan else { 3372169689Skan ctx->prev->next = ctx->next; 3373169689Skan if (ctx->next) 3374169689Skan ctx->next->prev = ctx->prev; 3375169689Skan } 3376169689Skan break; 3377169689Skan } 3378169689Skan } 3379169689Skan mtx_unlock(&sc->aac_aifq_lock); 3380169689Skan if (ctx) 3381169689Skan free(ctx, M_AACBUF); 3382169689Skan 3383169689Skan return 0; 3384169689Skan} 3385169689Skan 3386169689Skan/* 3387169689Skan * Pass the caller the next AIF in their queue 3388169689Skan */ 3389169689Skanstatic int 3390169689Skanaac_getnext_aif(struct aac_softc *sc, caddr_t arg) 3391169689Skan{ 3392169689Skan struct get_adapter_fib_ioctl agf; 3393169689Skan struct aac_fib_context *ctx; 3394169689Skan int error; 3395169689Skan 3396169689Skan debug_called(2); 3397169689Skan 3398169689Skan if ((error = copyin(arg, &agf, sizeof(agf))) == 0) { 3399169689Skan for (ctx = sc->fibctx; ctx; ctx = ctx->next) { 3400169689Skan if (agf.AdapterFibContext == ctx->unique) 3401169689Skan break; 3402169689Skan } 3403169689Skan if (!ctx) 3404169689Skan return (EFAULT); 3405169689Skan 3406169689Skan error = aac_return_aif(sc, ctx, agf.AifFib); 3407169689Skan if (error == EAGAIN && agf.Wait) { 3408169689Skan debug(2, "aac_getnext_aif(): waiting for AIF"); 3409169689Skan sc->aac_state |= AAC_STATE_AIF_SLEEPER; 3410169689Skan while (error == EAGAIN) { 3411169689Skan error = tsleep(sc->aac_aifq, PRIBIO | 3412169689Skan PCATCH, "aacaif", 0); 3413169689Skan if (error == 0) 3414169689Skan error = aac_return_aif(sc, ctx, agf.AifFib); 3415169689Skan } 3416169689Skan sc->aac_state &= ~AAC_STATE_AIF_SLEEPER; 3417169689Skan } 3418169689Skan } 3419169689Skan return(error); 3420169689Skan} 3421169689Skan 3422169689Skan/* 3423169689Skan * Hand the next AIF off the top of the queue out to userspace. 3424169689Skan */ 3425169689Skanstatic int 3426169689Skanaac_return_aif(struct aac_softc *sc, struct aac_fib_context *ctx, caddr_t uptr) 3427169689Skan{ 3428169689Skan int current, error; 3429169689Skan 3430169689Skan debug_called(2); 3431169689Skan 3432169689Skan mtx_lock(&sc->aac_aifq_lock); 3433169689Skan current = ctx->ctx_idx; 3434169689Skan if (current == sc->aifq_idx && !ctx->ctx_wrap) { 3435169689Skan /* empty */ 3436169689Skan mtx_unlock(&sc->aac_aifq_lock); 3437169689Skan return (EAGAIN); 3438169689Skan } 3439169689Skan error = 3440169689Skan copyout(&sc->aac_aifq[current], (void *)uptr, sizeof(struct aac_fib)); 3441169689Skan if (error) 3442169689Skan device_printf(sc->aac_dev, 3443169689Skan "aac_return_aif: copyout returned %d\n", error); 3444169689Skan else { 3445169689Skan ctx->ctx_wrap = 0; 3446169689Skan ctx->ctx_idx = (current + 1) % AAC_AIFQ_LENGTH; 3447169689Skan } 3448169689Skan mtx_unlock(&sc->aac_aifq_lock); 3449169689Skan return(error); 3450169689Skan} 3451169689Skan 3452169689Skanstatic int 3453169689Skanaac_get_pci_info(struct aac_softc *sc, caddr_t uptr) 3454169689Skan{ 3455169689Skan struct aac_pci_info { 3456169689Skan u_int32_t bus; 3457169689Skan u_int32_t slot; 3458169689Skan } pciinf; 3459169689Skan int error; 3460169689Skan 3461169689Skan debug_called(2); 3462169689Skan 3463169689Skan pciinf.bus = pci_get_bus(sc->aac_dev); 3464169689Skan pciinf.slot = pci_get_slot(sc->aac_dev); 3465169689Skan 3466169689Skan error = copyout((caddr_t)&pciinf, uptr, 3467169689Skan sizeof(struct aac_pci_info)); 3468169689Skan 3469169689Skan return (error); 3470169689Skan} 3471169689Skan 3472169689Skan/* 3473169689Skan * Give the userland some information about the container. The AAC arch 3474169689Skan * expects the driver to be a SCSI passthrough type driver, so it expects 3475169689Skan * the containers to have b:t:l numbers. Fake it. 3476169689Skan */ 3477169689Skanstatic int 3478169689Skanaac_query_disk(struct aac_softc *sc, caddr_t uptr) 3479169689Skan{ 3480169689Skan struct aac_query_disk query_disk; 3481169689Skan struct aac_container *co; 3482169689Skan struct aac_disk *disk; 3483169689Skan int error, id; 3484169689Skan 3485169689Skan debug_called(2); 3486169689Skan 3487169689Skan disk = NULL; 3488169689Skan 3489169689Skan error = copyin(uptr, (caddr_t)&query_disk, 3490169689Skan sizeof(struct aac_query_disk)); 3491169689Skan if (error) 3492169689Skan return (error); 3493169689Skan 3494169689Skan id = query_disk.ContainerNumber; 3495169689Skan if (id == -1) 3496169689Skan return (EINVAL); 3497169689Skan 3498169689Skan mtx_lock(&sc->aac_container_lock); 3499169689Skan TAILQ_FOREACH(co, &sc->aac_container_tqh, co_link) { 3500169689Skan if (co->co_mntobj.ObjectId == id) 3501169689Skan break; 3502169689Skan } 3503169689Skan 3504169689Skan if (co == NULL) { 3505169689Skan query_disk.Valid = 0; 3506169689Skan query_disk.Locked = 0; 3507169689Skan query_disk.Deleted = 1; /* XXX is this right? */ 3508169689Skan } else { 3509169689Skan disk = device_get_softc(co->co_disk); 3510169689Skan query_disk.Valid = 1; 3511169689Skan query_disk.Locked = 3512169689Skan (disk->ad_flags & AAC_DISK_OPEN) ? 1 : 0; 3513169689Skan query_disk.Deleted = 0; 3514169689Skan query_disk.Bus = device_get_unit(sc->aac_dev); 3515169689Skan query_disk.Target = disk->unit; 3516169689Skan query_disk.Lun = 0; 3517169689Skan query_disk.UnMapped = 0; 3518169689Skan sprintf(&query_disk.diskDeviceName[0], "%s%d", 3519169689Skan disk->ad_disk->d_name, disk->ad_disk->d_unit); 3520169689Skan } 3521169689Skan mtx_unlock(&sc->aac_container_lock); 3522169689Skan 3523169689Skan error = copyout((caddr_t)&query_disk, uptr, 3524169689Skan sizeof(struct aac_query_disk)); 3525169689Skan 3526169689Skan return (error); 3527169689Skan} 3528169689Skan 3529169689Skanstatic void 3530169689Skanaac_get_bus_info(struct aac_softc *sc) 3531169689Skan{ 3532169689Skan struct aac_fib *fib; 3533169689Skan struct aac_ctcfg *c_cmd; 3534169689Skan struct aac_ctcfg_resp *c_resp; 3535169689Skan struct aac_vmioctl *vmi; 3536169689Skan struct aac_vmi_businf_resp *vmi_resp; 3537169689Skan struct aac_getbusinf businfo; 3538169689Skan struct aac_sim *caminf; 3539169689Skan device_t child; 3540169689Skan int i, found, error; 3541169689Skan 3542169689Skan mtx_lock(&sc->aac_io_lock); 3543169689Skan aac_alloc_sync_fib(sc, &fib); 3544169689Skan c_cmd = (struct aac_ctcfg *)&fib->data[0]; 3545169689Skan bzero(c_cmd, sizeof(struct aac_ctcfg)); 3546169689Skan 3547169689Skan c_cmd->Command = VM_ContainerConfig; 3548169689Skan c_cmd->cmd = CT_GET_SCSI_METHOD; 3549169689Skan c_cmd->param = 0; 3550169689Skan 3551169689Skan error = aac_sync_fib(sc, ContainerCommand, 0, fib, 3552169689Skan sizeof(struct aac_ctcfg)); 3553169689Skan if (error) { 3554169689Skan device_printf(sc->aac_dev, "Error %d sending " 3555169689Skan "VM_ContainerConfig command\n", error); 3556169689Skan aac_release_sync_fib(sc); 3557169689Skan mtx_unlock(&sc->aac_io_lock); 3558169689Skan return; 3559169689Skan } 3560169689Skan 3561169689Skan c_resp = (struct aac_ctcfg_resp *)&fib->data[0]; 3562169689Skan if (c_resp->Status != ST_OK) { 3563169689Skan device_printf(sc->aac_dev, "VM_ContainerConfig returned 0x%x\n", 3564169689Skan c_resp->Status); 3565169689Skan aac_release_sync_fib(sc); 3566169689Skan mtx_unlock(&sc->aac_io_lock); 3567169689Skan return; 3568169689Skan } 3569169689Skan 3570169689Skan sc->scsi_method_id = c_resp->param; 3571169689Skan 3572169689Skan vmi = (struct aac_vmioctl *)&fib->data[0]; 3573169689Skan bzero(vmi, sizeof(struct aac_vmioctl)); 3574169689Skan 3575169689Skan vmi->Command = VM_Ioctl; 3576169689Skan vmi->ObjType = FT_DRIVE; 3577169689Skan vmi->MethId = sc->scsi_method_id; 3578169689Skan vmi->ObjId = 0; 3579169689Skan vmi->IoctlCmd = GetBusInfo; 3580169689Skan 3581169689Skan error = aac_sync_fib(sc, ContainerCommand, 0, fib, 3582169689Skan sizeof(struct aac_vmioctl)); 3583169689Skan if (error) { 3584169689Skan device_printf(sc->aac_dev, "Error %d sending VMIoctl command\n", 3585169689Skan error); 3586169689Skan aac_release_sync_fib(sc); 3587169689Skan mtx_unlock(&sc->aac_io_lock); 3588169689Skan return; 3589169689Skan } 3590169689Skan 3591169689Skan vmi_resp = (struct aac_vmi_businf_resp *)&fib->data[0]; 3592169689Skan if (vmi_resp->Status != ST_OK) { 3593169689Skan device_printf(sc->aac_dev, "VM_Ioctl returned %d\n", 3594169689Skan vmi_resp->Status); 3595169689Skan aac_release_sync_fib(sc); 3596169689Skan mtx_unlock(&sc->aac_io_lock); 3597169689Skan return; 3598169689Skan } 3599169689Skan 3600169689Skan bcopy(&vmi_resp->BusInf, &businfo, sizeof(struct aac_getbusinf)); 3601169689Skan aac_release_sync_fib(sc); 3602169689Skan mtx_unlock(&sc->aac_io_lock); 3603169689Skan 3604169689Skan found = 0; 3605169689Skan for (i = 0; i < businfo.BusCount; i++) { 3606169689Skan if (businfo.BusValid[i] != AAC_BUS_VALID) 3607169689Skan continue; 3608169689Skan 3609169689Skan caminf = (struct aac_sim *)malloc( sizeof(struct aac_sim), 3610169689Skan M_AACBUF, M_NOWAIT | M_ZERO); 3611169689Skan if (caminf == NULL) { 3612169689Skan device_printf(sc->aac_dev, 3613169689Skan "No memory to add passthrough bus %d\n", i); 3614169689Skan break; 3615169689Skan }; 3616169689Skan 3617169689Skan child = device_add_child(sc->aac_dev, "aacp", -1); 3618169689Skan if (child == NULL) { 3619169689Skan device_printf(sc->aac_dev, 3620169689Skan "device_add_child failed for passthrough bus %d\n", 3621169689Skan i); 3622169689Skan free(caminf, M_AACBUF); 3623169689Skan break; 3624169689Skan } 3625169689Skan 3626169689Skan caminf->TargetsPerBus = businfo.TargetsPerBus; 3627169689Skan caminf->BusNumber = i; 3628169689Skan caminf->InitiatorBusId = businfo.InitiatorBusId[i]; 3629169689Skan caminf->aac_sc = sc; 3630169689Skan caminf->sim_dev = child; 3631169689Skan 3632169689Skan device_set_ivars(child, caminf); 3633169689Skan device_set_desc(child, "SCSI Passthrough Bus"); 3634169689Skan TAILQ_INSERT_TAIL(&sc->aac_sim_tqh, caminf, sim_link); 3635169689Skan 3636169689Skan found = 1; 3637169689Skan } 3638169689Skan 3639169689Skan if (found) 3640169689Skan bus_generic_attach(sc->aac_dev); 3641169689Skan 3642169689Skan return; 3643169689Skan} 3644169689Skan