linux/drivers/scsi/aacraid/rx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *      Adaptec AAC series RAID controller driver
   4 *      (c) Copyright 2001 Red Hat Inc.
   5 *
   6 * based on the old aacraid driver that is..
   7 * Adaptec aacraid device driver for Linux.
   8 *
   9 * Copyright (c) 2000-2010 Adaptec, Inc.
  10 *               2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
  11 *               2016-2017 Microsemi Corp. (aacraid@microsemi.com)
  12 *
  13 * Module Name:
  14 *  rx.c
  15 *
  16 * Abstract: Hardware miniport for Drawbridge specific hardware functions.
  17 */
  18
  19#include <linux/kernel.h>
  20#include <linux/init.h>
  21#include <linux/types.h>
  22#include <linux/pci.h>
  23#include <linux/spinlock.h>
  24#include <linux/blkdev.h>
  25#include <linux/delay.h>
  26#include <linux/completion.h>
  27#include <linux/time.h>
  28#include <linux/interrupt.h>
  29
  30#include <scsi/scsi_host.h>
  31
  32#include "aacraid.h"
  33
  34static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id)
  35{
  36        struct aac_dev *dev = dev_id;
  37        unsigned long bellbits;
  38        u8 intstat = rx_readb(dev, MUnit.OISR);
  39
  40        /*
  41         *      Read mask and invert because drawbridge is reversed.
  42         *      This allows us to only service interrupts that have
  43         *      been enabled.
  44         *      Check to see if this is our interrupt.  If it isn't just return
  45         */
  46        if (likely(intstat & ~(dev->OIMR))) {
  47                bellbits = rx_readl(dev, OutboundDoorbellReg);
  48                if (unlikely(bellbits & DoorBellPrintfReady)) {
  49                        aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5]));
  50                        rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
  51                        rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
  52                }
  53                else if (unlikely(bellbits & DoorBellAdapterNormCmdReady)) {
  54                        rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
  55                        aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
  56                }
  57                else if (likely(bellbits & DoorBellAdapterNormRespReady)) {
  58                        rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
  59                        aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
  60                }
  61                else if (unlikely(bellbits & DoorBellAdapterNormCmdNotFull)) {
  62                        rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
  63                }
  64                else if (unlikely(bellbits & DoorBellAdapterNormRespNotFull)) {
  65                        rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
  66                        rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
  67                }
  68                return IRQ_HANDLED;
  69        }
  70        return IRQ_NONE;
  71}
  72
  73static irqreturn_t aac_rx_intr_message(int irq, void *dev_id)
  74{
  75        int isAif, isFastResponse, isSpecial;
  76        struct aac_dev *dev = dev_id;
  77        u32 Index = rx_readl(dev, MUnit.OutboundQueue);
  78        if (unlikely(Index == 0xFFFFFFFFL))
  79                Index = rx_readl(dev, MUnit.OutboundQueue);
  80        if (likely(Index != 0xFFFFFFFFL)) {
  81                do {
  82                        isAif = isFastResponse = isSpecial = 0;
  83                        if (Index & 0x00000002L) {
  84                                isAif = 1;
  85                                if (Index == 0xFFFFFFFEL)
  86                                        isSpecial = 1;
  87                                Index &= ~0x00000002L;
  88                        } else {
  89                                if (Index & 0x00000001L)
  90                                        isFastResponse = 1;
  91                                Index >>= 2;
  92                        }
  93                        if (!isSpecial) {
  94                                if (unlikely(aac_intr_normal(dev,
  95                                                Index, isAif,
  96                                                isFastResponse, NULL))) {
  97                                        rx_writel(dev,
  98                                                MUnit.OutboundQueue,
  99                                                Index);
 100                                        rx_writel(dev,
 101                                                MUnit.ODR,
 102                                                DoorBellAdapterNormRespReady);
 103                                }
 104                        }
 105                        Index = rx_readl(dev, MUnit.OutboundQueue);
 106                } while (Index != 0xFFFFFFFFL);
 107                return IRQ_HANDLED;
 108        }
 109        return IRQ_NONE;
 110}
 111
 112/**
 113 *      aac_rx_disable_interrupt        -       Disable interrupts
 114 *      @dev: Adapter
 115 */
 116
 117static void aac_rx_disable_interrupt(struct aac_dev *dev)
 118{
 119        rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
 120}
 121
 122/**
 123 *      aac_rx_enable_interrupt_producer        -       Enable interrupts
 124 *      @dev: Adapter
 125 */
 126
 127static void aac_rx_enable_interrupt_producer(struct aac_dev *dev)
 128{
 129        rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
 130}
 131
 132/**
 133 *      aac_rx_enable_interrupt_message -       Enable interrupts
 134 *      @dev: Adapter
 135 */
 136
 137static void aac_rx_enable_interrupt_message(struct aac_dev *dev)
 138{
 139        rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
 140}
 141
 142/**
 143 *      rx_sync_cmd     -       send a command and wait
 144 *      @dev: Adapter
 145 *      @command: Command to execute
 146 *      @p1: first parameter
 147 *      @p2: second parameter
 148 *      @p3: third parameter
 149 *      @p4: forth parameter
 150 *      @p5: fifth parameter
 151 *      @p6: sixth parameter
 152 *      @status: adapter status
 153 *      @r1: first return value
 154 *      @r2: second return value
 155 *      @r3: third return value
 156 *      @r4: forth return value
 157 *
 158 *      This routine will send a synchronous command to the adapter and wait 
 159 *      for its completion.
 160 */
 161
 162static int rx_sync_cmd(struct aac_dev *dev, u32 command,
 163        u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
 164        u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4)
 165{
 166        unsigned long start;
 167        int ok;
 168        /*
 169         *      Write the command into Mailbox 0
 170         */
 171        writel(command, &dev->IndexRegs->Mailbox[0]);
 172        /*
 173         *      Write the parameters into Mailboxes 1 - 6
 174         */
 175        writel(p1, &dev->IndexRegs->Mailbox[1]);
 176        writel(p2, &dev->IndexRegs->Mailbox[2]);
 177        writel(p3, &dev->IndexRegs->Mailbox[3]);
 178        writel(p4, &dev->IndexRegs->Mailbox[4]);
 179        /*
 180         *      Clear the synch command doorbell to start on a clean slate.
 181         */
 182        rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
 183        /*
 184         *      Disable doorbell interrupts
 185         */
 186        rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
 187        /*
 188         *      Force the completion of the mask register write before issuing
 189         *      the interrupt.
 190         */
 191        rx_readb (dev, MUnit.OIMR);
 192        /*
 193         *      Signal that there is a new synch command
 194         */
 195        rx_writel(dev, InboundDoorbellReg, INBOUNDDOORBELL_0);
 196
 197        ok = 0;
 198        start = jiffies;
 199
 200        /*
 201         *      Wait up to 30 seconds
 202         */
 203        while (time_before(jiffies, start+30*HZ)) 
 204        {
 205                udelay(5);      /* Delay 5 microseconds to let Mon960 get info. */
 206                /*
 207                 *      Mon960 will set doorbell0 bit when it has completed the command.
 208                 */
 209                if (rx_readl(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) {
 210                        /*
 211                         *      Clear the doorbell.
 212                         */
 213                        rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
 214                        ok = 1;
 215                        break;
 216                }
 217                /*
 218                 *      Yield the processor in case we are slow 
 219                 */
 220                msleep(1);
 221        }
 222        if (unlikely(ok != 1)) {
 223                /*
 224                 *      Restore interrupt mask even though we timed out
 225                 */
 226                aac_adapter_enable_int(dev);
 227                return -ETIMEDOUT;
 228        }
 229        /*
 230         *      Pull the synch status from Mailbox 0.
 231         */
 232        if (status)
 233                *status = readl(&dev->IndexRegs->Mailbox[0]);
 234        if (r1)
 235                *r1 = readl(&dev->IndexRegs->Mailbox[1]);
 236        if (r2)
 237                *r2 = readl(&dev->IndexRegs->Mailbox[2]);
 238        if (r3)
 239                *r3 = readl(&dev->IndexRegs->Mailbox[3]);
 240        if (r4)
 241                *r4 = readl(&dev->IndexRegs->Mailbox[4]);
 242        /*
 243         *      Clear the synch command doorbell.
 244         */
 245        rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
 246        /*
 247         *      Restore interrupt mask
 248         */
 249        aac_adapter_enable_int(dev);
 250        return 0;
 251
 252}
 253
 254/**
 255 *      aac_rx_interrupt_adapter        -       interrupt adapter
 256 *      @dev: Adapter
 257 *
 258 *      Send an interrupt to the i960 and breakpoint it.
 259 */
 260
 261static void aac_rx_interrupt_adapter(struct aac_dev *dev)
 262{
 263        rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
 264}
 265
 266/**
 267 *      aac_rx_notify_adapter           -       send an event to the adapter
 268 *      @dev: Adapter
 269 *      @event: Event to send
 270 *
 271 *      Notify the i960 that something it probably cares about has
 272 *      happened.
 273 */
 274
 275static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
 276{
 277        switch (event) {
 278
 279        case AdapNormCmdQue:
 280                rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_1);
 281                break;
 282        case HostNormRespNotFull:
 283                rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_4);
 284                break;
 285        case AdapNormRespQue:
 286                rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_2);
 287                break;
 288        case HostNormCmdNotFull:
 289                rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
 290                break;
 291        case HostShutdown:
 292                break;
 293        case FastIo:
 294                rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
 295                break;
 296        case AdapPrintfDone:
 297                rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_5);
 298                break;
 299        default:
 300                BUG();
 301                break;
 302        }
 303}
 304
 305/**
 306 *      aac_rx_start_adapter            -       activate adapter
 307 *      @dev:   Adapter
 308 *
 309 *      Start up processing on an i960 based AAC adapter
 310 */
 311
 312static void aac_rx_start_adapter(struct aac_dev *dev)
 313{
 314        union aac_init *init;
 315
 316        init = dev->init;
 317        init->r7.host_elapsed_seconds = cpu_to_le32(ktime_get_real_seconds());
 318        // We can only use a 32 bit address here
 319        rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
 320          0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
 321}
 322
 323/**
 324 *      aac_rx_check_health
 325 *      @dev: device to check if healthy
 326 *
 327 *      Will attempt to determine if the specified adapter is alive and
 328 *      capable of handling requests, returning 0 if alive.
 329 */
 330static int aac_rx_check_health(struct aac_dev *dev)
 331{
 332        u32 status = rx_readl(dev, MUnit.OMRx[0]);
 333
 334        /*
 335         *      Check to see if the board failed any self tests.
 336         */
 337        if (unlikely(status & SELF_TEST_FAILED))
 338                return -1;
 339        /*
 340         *      Check to see if the board panic'd.
 341         */
 342        if (unlikely(status & KERNEL_PANIC)) {
 343                char * buffer;
 344                struct POSTSTATUS {
 345                        __le32 Post_Command;
 346                        __le32 Post_Address;
 347                } * post;
 348                dma_addr_t paddr, baddr;
 349                int ret;
 350
 351                if (likely((status & 0xFF000000L) == 0xBC000000L))
 352                        return (status >> 16) & 0xFF;
 353                buffer = dma_alloc_coherent(&dev->pdev->dev, 512, &baddr,
 354                                            GFP_KERNEL);
 355                ret = -2;
 356                if (unlikely(buffer == NULL))
 357                        return ret;
 358                post = dma_alloc_coherent(&dev->pdev->dev,
 359                                          sizeof(struct POSTSTATUS), &paddr,
 360                                          GFP_KERNEL);
 361                if (unlikely(post == NULL)) {
 362                        dma_free_coherent(&dev->pdev->dev, 512, buffer, baddr);
 363                        return ret;
 364                }
 365                memset(buffer, 0, 512);
 366                post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
 367                post->Post_Address = cpu_to_le32(baddr);
 368                rx_writel(dev, MUnit.IMRx[0], paddr);
 369                rx_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, 0, 0, 0, 0, 0,
 370                  NULL, NULL, NULL, NULL, NULL);
 371                dma_free_coherent(&dev->pdev->dev, sizeof(struct POSTSTATUS),
 372                                  post, paddr);
 373                if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) {
 374                        ret = (hex_to_bin(buffer[2]) << 4) +
 375                                hex_to_bin(buffer[3]);
 376                }
 377                dma_free_coherent(&dev->pdev->dev, 512, buffer, baddr);
 378                return ret;
 379        }
 380        /*
 381         *      Wait for the adapter to be up and running.
 382         */
 383        if (unlikely(!(status & KERNEL_UP_AND_RUNNING)))
 384                return -3;
 385        /*
 386         *      Everything is OK
 387         */
 388        return 0;
 389}
 390
 391/**
 392 *      aac_rx_deliver_producer
 393 *      @fib: fib to issue
 394 *
 395 *      Will send a fib, returning 0 if successful.
 396 */
 397int aac_rx_deliver_producer(struct fib * fib)
 398{
 399        struct aac_dev *dev = fib->dev;
 400        struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
 401        u32 Index;
 402        unsigned long nointr = 0;
 403
 404        aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr);
 405
 406        atomic_inc(&q->numpending);
 407        *(q->headers.producer) = cpu_to_le32(Index + 1);
 408        if (!(nointr & aac_config.irq_mod))
 409                aac_adapter_notify(dev, AdapNormCmdQueue);
 410
 411        return 0;
 412}
 413
 414/**
 415 *      aac_rx_deliver_message
 416 *      @fib: fib to issue
 417 *
 418 *      Will send a fib, returning 0 if successful.
 419 */
 420static int aac_rx_deliver_message(struct fib * fib)
 421{
 422        struct aac_dev *dev = fib->dev;
 423        struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
 424        u32 Index;
 425        u64 addr;
 426        volatile void __iomem *device;
 427
 428        unsigned long count = 10000000L; /* 50 seconds */
 429        atomic_inc(&q->numpending);
 430        for(;;) {
 431                Index = rx_readl(dev, MUnit.InboundQueue);
 432                if (unlikely(Index == 0xFFFFFFFFL))
 433                        Index = rx_readl(dev, MUnit.InboundQueue);
 434                if (likely(Index != 0xFFFFFFFFL))
 435                        break;
 436                if (--count == 0) {
 437                        atomic_dec(&q->numpending);
 438                        return -ETIMEDOUT;
 439                }
 440                udelay(5);
 441        }
 442        device = dev->base + Index;
 443        addr = fib->hw_fib_pa;
 444        writel((u32)(addr & 0xffffffff), device);
 445        device += sizeof(u32);
 446        writel((u32)(addr >> 32), device);
 447        device += sizeof(u32);
 448        writel(le16_to_cpu(fib->hw_fib_va->header.Size), device);
 449        rx_writel(dev, MUnit.InboundQueue, Index);
 450        return 0;
 451}
 452
 453/**
 454 *      aac_rx_ioremap
 455 *      @dev: adapter
 456 *      @size: mapping resize request
 457 *
 458 */
 459static int aac_rx_ioremap(struct aac_dev * dev, u32 size)
 460{
 461        if (!size) {
 462                iounmap(dev->regs.rx);
 463                return 0;
 464        }
 465        dev->base = dev->regs.rx = ioremap(dev->base_start, size);
 466        if (dev->base == NULL)
 467                return -1;
 468        dev->IndexRegs = &dev->regs.rx->IndexRegs;
 469        return 0;
 470}
 471
 472static int aac_rx_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type)
 473{
 474        u32 var = 0;
 475
 476        if (!(dev->supplement_adapter_info.supported_options2 &
 477          AAC_OPTION_MU_RESET) || (bled >= 0) || (bled == -2)) {
 478                if (bled)
 479                        printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
 480                                dev->name, dev->id, bled);
 481                else {
 482                        bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
 483                          0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
 484                        if (!bled && (var != 0x00000001) && (var != 0x3803000F))
 485                                bled = -EINVAL;
 486                }
 487                if (bled && (bled != -ETIMEDOUT))
 488                        bled = aac_adapter_sync_cmd(dev, IOP_RESET,
 489                          0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL);
 490
 491                if (bled && (bled != -ETIMEDOUT))
 492                        return -EINVAL;
 493        }
 494        if (bled && (var == 0x3803000F)) { /* USE_OTHER_METHOD */
 495                rx_writel(dev, MUnit.reserved2, 3);
 496                msleep(5000); /* Delay 5 seconds */
 497                var = 0x00000001;
 498        }
 499        if (bled && (var != 0x00000001))
 500                return -EINVAL;
 501        ssleep(5);
 502        if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC)
 503                return -ENODEV;
 504        if (startup_timeout < 300)
 505                startup_timeout = 300;
 506        return 0;
 507}
 508
 509/**
 510 *      aac_rx_select_comm      -       Select communications method
 511 *      @dev: Adapter
 512 *      @comm: communications method
 513 */
 514
 515int aac_rx_select_comm(struct aac_dev *dev, int comm)
 516{
 517        switch (comm) {
 518        case AAC_COMM_PRODUCER:
 519                dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_producer;
 520                dev->a_ops.adapter_intr = aac_rx_intr_producer;
 521                dev->a_ops.adapter_deliver = aac_rx_deliver_producer;
 522                break;
 523        case AAC_COMM_MESSAGE:
 524                dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_message;
 525                dev->a_ops.adapter_intr = aac_rx_intr_message;
 526                dev->a_ops.adapter_deliver = aac_rx_deliver_message;
 527                break;
 528        default:
 529                return 1;
 530        }
 531        return 0;
 532}
 533
 534/**
 535 *      _aac_rx_init    -       initialize an i960 based AAC card
 536 *      @dev: device to configure
 537 *
 538 *      Allocate and set up resources for the i960 based AAC variants. The 
 539 *      device_interface in the commregion will be allocated and linked 
 540 *      to the comm region.
 541 */
 542
 543int _aac_rx_init(struct aac_dev *dev)
 544{
 545        unsigned long start;
 546        unsigned long status;
 547        int restart = 0;
 548        int instance = dev->id;
 549        const char * name = dev->name;
 550
 551        if (aac_adapter_ioremap(dev, dev->base_size)) {
 552                printk(KERN_WARNING "%s: unable to map adapter.\n", name);
 553                goto error_iounmap;
 554        }
 555
 556        /* Failure to reset here is an option ... */
 557        dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
 558        dev->a_ops.adapter_enable_int = aac_rx_disable_interrupt;
 559        dev->OIMR = status = rx_readb (dev, MUnit.OIMR);
 560
 561        if (((status & 0x0c) != 0x0c) || dev->init_reset) {
 562                dev->init_reset = false;
 563                if (!aac_rx_restart_adapter(dev, 0, IOP_HWSOFT_RESET)) {
 564                        /* Make sure the Hardware FIFO is empty */
 565                        while ((++restart < 512) &&
 566                               (rx_readl(dev, MUnit.OutboundQueue) != 0xFFFFFFFFL));
 567                }
 568        }
 569
 570        /*
 571         *      Check to see if the board panic'd while booting.
 572         */
 573        status = rx_readl(dev, MUnit.OMRx[0]);
 574        if (status & KERNEL_PANIC) {
 575                if (aac_rx_restart_adapter(dev,
 576                        aac_rx_check_health(dev), IOP_HWSOFT_RESET))
 577                        goto error_iounmap;
 578                ++restart;
 579        }
 580        /*
 581         *      Check to see if the board failed any self tests.
 582         */
 583        status = rx_readl(dev, MUnit.OMRx[0]);
 584        if (status & SELF_TEST_FAILED) {
 585                printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance);
 586                goto error_iounmap;
 587        }
 588        /*
 589         *      Check to see if the monitor panic'd while booting.
 590         */
 591        if (status & MONITOR_PANIC) {
 592                printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance);
 593                goto error_iounmap;
 594        }
 595        start = jiffies;
 596        /*
 597         *      Wait for the adapter to be up and running. Wait up to 3 minutes
 598         */
 599        while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING))
 600        {
 601                if ((restart &&
 602                  (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
 603                  time_after(jiffies, start+HZ*startup_timeout)) {
 604                        printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", 
 605                                        dev->name, instance, status);
 606                        goto error_iounmap;
 607                }
 608                if (!restart &&
 609                  ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
 610                  time_after(jiffies, start + HZ *
 611                  ((startup_timeout > 60)
 612                    ? (startup_timeout - 60)
 613                    : (startup_timeout / 2))))) {
 614                        if (likely(!aac_rx_restart_adapter(dev,
 615                                aac_rx_check_health(dev), IOP_HWSOFT_RESET)))
 616                                start = jiffies;
 617                        ++restart;
 618                }
 619                msleep(1);
 620        }
 621        if (restart && aac_commit)
 622                aac_commit = 1;
 623        /*
 624         *      Fill in the common function dispatch table.
 625         */
 626        dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter;
 627        dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt;
 628        dev->a_ops.adapter_notify = aac_rx_notify_adapter;
 629        dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
 630        dev->a_ops.adapter_check_health = aac_rx_check_health;
 631        dev->a_ops.adapter_restart = aac_rx_restart_adapter;
 632        dev->a_ops.adapter_start = aac_rx_start_adapter;
 633
 634        /*
 635         *      First clear out all interrupts.  Then enable the one's that we
 636         *      can handle.
 637         */
 638        aac_adapter_comm(dev, AAC_COMM_PRODUCER);
 639        aac_adapter_disable_int(dev);
 640        rx_writel(dev, MUnit.ODR, 0xffffffff);
 641        aac_adapter_enable_int(dev);
 642
 643        if (aac_init_adapter(dev) == NULL)
 644                goto error_iounmap;
 645        aac_adapter_comm(dev, dev->comm_interface);
 646        dev->sync_mode = 0;     /* sync. mode not supported */
 647        dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
 648        if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
 649                        IRQF_SHARED, "aacraid", dev) < 0) {
 650                if (dev->msi)
 651                        pci_disable_msi(dev->pdev);
 652                printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
 653                        name, instance);
 654                goto error_iounmap;
 655        }
 656        dev->dbg_base = dev->base_start;
 657        dev->dbg_base_mapped = dev->base;
 658        dev->dbg_size = dev->base_size;
 659
 660        aac_adapter_enable_int(dev);
 661        /*
 662         *      Tell the adapter that all is configured, and it can
 663         * start accepting requests
 664         */
 665        aac_rx_start_adapter(dev);
 666
 667        return 0;
 668
 669error_iounmap:
 670
 671        return -1;
 672}
 673
 674int aac_rx_init(struct aac_dev *dev)
 675{
 676        /*
 677         *      Fill in the function dispatch table.
 678         */
 679        dev->a_ops.adapter_ioremap = aac_rx_ioremap;
 680        dev->a_ops.adapter_comm = aac_rx_select_comm;
 681
 682        return _aac_rx_init(dev);
 683}
 684