openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

linux-user-bde.c (55620B)


      1 /*
      2  * Copyright 2017 Broadcom
      3  *
      4  * This program is free software; you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License, version 2, as
      6  * published by the Free Software Foundation (the "GPL").
      7  *
      8  * This program is distributed in the hope that it will be useful, but
      9  * WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     11  * General Public License version 2 (GPLv2) for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * version 2 (GPLv2) along with this source code.
     15  */
     16 
     17 /*
     18  * Linux User BDE Helper Module
     19  */
     20 #include <gmodule.h>
     21 #include <mpool.h>
     22 #include <linux-bde.h>
     23 
     24 #include <sal/core/thread.h>
     25 #include <sal/core/sync.h>
     26 #include <soc/devids.h>
     27 #include <linux/jiffies.h>
     28 #include "linux-user-bde.h"
     29 
     30 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0)
     31 #include <linux/uaccess.h>
     32 #endif
     33 
     34 
     35 MODULE_AUTHOR("Broadcom Corporation");
     36 MODULE_DESCRIPTION("User BDE Helper Module");
     37 MODULE_LICENSE("GPL");
     38 
     39 /* CMIC/CMICe defines */
     40 #define CMIC_IRQ_STAT                   0x00000144
     41 #define CMIC_IRQ_MASK                   0x00000148
     42 #define CMIC_IRQ_MASK_1                 0x0000006C
     43 #define CMIC_IRQ_MASK_2                 0x00000070
     44 
     45 /* CMICm defines */
     46 #define CMIC_CMCx_IRQ_STAT0_OFFSET(x)                    (0x31400 + (0x1000 * x))
     47 #define CMIC_CMCx_IRQ_STAT1_OFFSET(x)                    (0x31404 + (0x1000 * x))
     48 #define CMIC_CMCx_IRQ_STAT2_OFFSET(x)                    (0x31408 + (0x1000 * x))
     49 #define CMIC_CMCx_IRQ_STAT3_OFFSET(x)                    (0x3140c + (0x1000 * x))
     50 #define CMIC_CMCx_IRQ_STAT4_OFFSET(x)                    (0x31410 + (0x1000 * x))
     51 
     52 #define CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(x)               (0x31414 + (0x1000 * x))
     53 #define CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(x)               (0x31418 + (0x1000 * x))
     54 #define CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(x)               (0x3141c + (0x1000 * x))
     55 #define CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(x)               (0x31420 + (0x1000 * x))
     56 #define CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(x)               (0x31424 + (0x1000 * x))
     57 
     58 /* CMICd defines */
     59 #define CMIC_CMCx_IRQ_STAT5_OFFSET(x)                    (0x314b0 + (0x1000 * x))
     60 #define CMIC_CMCx_IRQ_STAT6_OFFSET(x)                    (0x314b4 + (0x1000 * x))
     61 #define CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(x)               (0x314b8 + (0x1000 * x))
     62 #define CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(x)               (0x314bc + (0x1000 * x))
     63 #define CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(x)                (0x314c0 + (0x1000 * x))
     64 #define CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(x)                (0x314c4 + (0x1000 * x))
     65 
     66 #define CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(x)                (0x31428 + (0x1000 * x))
     67 #define CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(x)                (0x3142c + (0x1000 * x))
     68 #define CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(x)                (0x31430 + (0x1000 * x))
     69 #define CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(x)                (0x31434 + (0x1000 * x))
     70 #define CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(x)                (0x31438 + (0x1000 * x))
     71 
     72 /* CMICX defines */
     73 #define INTC_INTR_REG_NUM               (8)
     74 #define PAXB_INTRCLR_DELAY_REG_NUM      (16)
     75 /*
     76 TODO:HX5
     77 The INTR base address values are changed for HX5,
     78 hence making new #defines so runtime decisions can
     79 be made.
     80 */
     81 #define PAXB_0_PAXB_IC_INTRCLR_0       (0x180123a0)
     82 #define PAXB_0_PAXB_IC_INTRCLR_1       (0x180123a4)
     83 #define PAXB_0_PAXB_IC_INTRCLR_MODE_0  (0x180123a8)
     84 #define PAXB_0_PAXB_IC_INTRCLR_MODE_1  (0x180123ac)
     85 #define PAXB_0_PAXB_INTR_STATUS             (0x18012f38)
     86 #define PAXB_0_PAXB_IC_INTR_PACING_CTRL     (0x18012398)
     87 #define PAXB_0_PAXB_INTRCLR_DELAY_UNIT      (0x1801239c)
     88 #define PAXB_0_PAXB_IC_INTRCLR_DELAY_REG0   (0x180123b0)
     89 #define PAXB_0_PCIE_ERROR_STATUS            (0x18012024)
     90 
     91 #define HX5_PAXB_0_PAXB_IC_INTRCLR_0   (0x102303a0)
     92 #define HX5_PAXB_0_PAXB_IC_INTRCLR_1   (0x102303a4)
     93 
     94 #define HX5_PAXB_0_PAXB_IC_INTRCLR_MODE_0   (0x102303a8)
     95 #define HX5_PAXB_0_PAXB_IC_INTRCLR_MODE_1   (0x102303ac)
     96 #define HX5_PAXB_0_PAXB_INTR_STATUS         (0x10230f38)
     97 #define HX5_PAXB_0_PAXB_IC_INTR_PACING_CTRL (0x10230398)
     98 #define HX5_PAXB_0_PAXB_INTRCLR_DELAY_UNIT  (0x1023039c)
     99 #define HX5_PAXB_0_PAXB_IC_INTRCLR_DELAY_REG0 (0x102303b0)
    100 #define HX5_PAXB_0_PCIE_ERROR_STATUS          (0x10230024)
    101 
    102 #define PAXB_0_PAXB_IC_INTRCLR_DELAY_BASE     (PAXB_0_PAXB_IC_INTRCLR_DELAY_REG0)
    103 #define HX5_PAXB_0_PAXB_IC_INTRCLR_DELAY_BASE (HX5_PAXB_0_PAXB_IC_INTRCLR_DELAY_REG0)
    104 
    105 #define INTC_INTR_ENABLE_REG0          (0x180130f0)
    106 #define INTC_INTR_STATUS_REG0          (0x18013190)
    107 #define INTC_INTR_RAW_STATUS_REG0      (0x18013140)
    108 
    109 #define INTC_INTR_ENABLE_BASE           (INTC_INTR_ENABLE_REG0)
    110 #define INTC_INTR_STATUS_BASE           (INTC_INTR_STATUS_REG0)
    111 #define INTC_INTR_RAW_STATUS_BASE       (INTC_INTR_RAW_STATUS_REG0)
    112 
    113 #define HX5_INTC_INTR_ENABLE_REG0          (0x102310f0)
    114 #define HX5_INTC_INTR_STATUS_REG0          (0x10231190)
    115 #define HX5_INTC_INTR_RAW_STATUS_REG0      (0x10231140)
    116 
    117 #define HX5_INTC_INTR_ENABLE_BASE          (HX5_INTC_INTR_ENABLE_REG0)
    118 #define HX5_INTC_INTR_STATUS_BASE          (HX5_INTC_INTR_STATUS_REG0)
    119 #define HX5_INTC_INTR_RAW_STATUS_BASE      (HX5_INTC_INTR_RAW_STATUS_REG0)
    120 
    121 #define IOREMAP(addr, size)                ioremap_nocache(addr, size)
    122 
    123 #define HX5_IHOST_GICD_ISENABLERN_0        (0x10781100)
    124 #define HX5_IHOST_GICD_ISENABLERN_1        (0x10781104)
    125 #define HX5_IHOST_GICD_ICENABLERN_1        (0x10781184)
    126 #define HX5_IHOST_GICD_ICENABLERN_8        (0x107811a0)
    127 #define HX5_IHOST_GICD_ISPENDRN_8          (0x10781220)
    128 /* Offset between ISENABLERN_1 and ICENABLERN_1 in 4-bytes */
    129 #define HX5_IHOST_IRQ_MASK_OFFSET          0x20
    130 /* Offset between ISENABLERN_1 and ISPENDRN_1 in 4-bytes */
    131 #define HX5_IHOST_IRQ_PEND_OFFSET          0x40
    132 #define HX5_IHOST_INTR_MAP_NUM             (HX5_IHOST_GICD_ISPENDRN_8 - HX5_IHOST_GICD_ISENABLERN_0)
    133 #define HX5_IHOST_INTR_STATUS_MAP_NUM      (INTC_INTR_REG_NUM * (sizeof(uint32)))
    134 #define IRQ_BIT(intr)                      (intr % (sizeof(uint32)*8))
    135 #define IRQ_MASK_INDEX(intr)               (intr / (sizeof(uint32)*8))
    136 #define HX5_SW_PROG_INTR_PRIORITY          73
    137 #define INTR_SW_PROG_INTR_BITPOS           (1 << IRQ_BIT(HX5_SW_PROG_INTR_PRIORITY))
    138 #define INTC_SW_PROG_INTR_REG_IND          IRQ_MASK_INDEX(HX5_SW_PROG_INTR_PRIORITY)
    139 #define HX5_CHIP_INTR_LOW_PRIORITY         119
    140 #define INTR_LOW_PRIORITY_BITPOS           (1 << IRQ_BIT(HX5_CHIP_INTR_LOW_PRIORITY))
    141 #define INTC_LOW_PRIORITY_INTR_REG_IND     IRQ_MASK_INDEX(HX5_CHIP_INTR_LOW_PRIORITY)
    142 #define INTC_PDMA_INTR_REG_IND             4
    143 
    144 #define READ_INTC_INTR(d, reg, v) \
    145         (v = user_bde->iproc_read(d, reg))
    146 #define WRITE_INTC_INTR(d, reg, v) \
    147         (user_bde->iproc_write(d, reg, v))
    148 
    149 #define IHOST_READ_INTR(d, reg, v) \
    150         (v = readl((reg)))
    151 #define IHOST_WRITE_INTR(d, reg, v) \
    152         (writel((v), (reg)))
    153 
    154 /* Allow override of default CMICm CMC */
    155 #ifndef BDE_CMICM_PCIE_CMC
    156 #define BDE_CMICM_PCIE_CMC              0
    157 #endif
    158 
    159 /* Allow override of default CMICm CMC */
    160 #ifndef BDE_CMICD_PCIE_CMC
    161 #define BDE_CMICD_PCIE_CMC              0
    162 #endif
    163 
    164 /* Defines used to distinguish CMICe from CMICm */
    165 #define CMICE_DEV_REV_ID                (0x178 / sizeof(uint32))
    166 
    167 static uint32 *ihost_intr_status_base = NULL;
    168 static uint32 *ihost_intr_enable_base = NULL;
    169 
    170 /* Module parameter for Interruptible timeout */
    171 static int intr_timeout = 0;
    172 LKM_MOD_PARAM(intr_timeout, "i", int, (S_IRUGO | S_IWUSR));
    173 MODULE_PARM_DESC(intr_timeout,
    174 "Interruptible wait timeout in milliseconds for Interrupt to be triggered.");
    175 
    176 static ulong intr_count = 0;
    177 LKM_MOD_PARAM(intr_count, "intr_count", ulong, (S_IRUGO | S_IWUSR));
    178 MODULE_PARM_DESC(intr_count,
    179 "Interrupt count provides information about the number of times the ISR is called.");
    180 
    181 /* Debug output */
    182 static int debug;
    183 LKM_MOD_PARAM(debug, "i", int, (S_IRUGO | S_IWUSR));
    184 MODULE_PARM_DESC(debug,
    185 "Set debug level (default 0).");
    186 
    187 static ibde_t *user_bde = NULL;
    188 
    189 typedef void (*isr_f)(void *);
    190 
    191 typedef struct _intr_regs_s {
    192     uint32 intc_intr_status_base;
    193     uint32 intc_intr_enable_base;
    194     uint32 intc_intr_raw_status_base;
    195     uint32 intc_intr_clear_0;
    196     uint32 intc_intr_clear_1;
    197     uint32 intc_intr_clear_mode_0;
    198     uint32 intc_intr_clear_mode_1;
    199     uint32 intc_intr_status;
    200     uint32 intc_intr_pacing_ctrl;
    201     uint32 intc_intr_clear_delay_unit;
    202     uint32 intc_intr_clear_delay_base;
    203     uint32 intc_intr_pcie_err_status;
    204 } _intr_regs_t;
    205 
    206 typedef struct bde_ctrl_s {
    207     uint32 dev_type;
    208     int irq;
    209     int enabled;
    210     int devid;
    211     isr_f isr;
    212     uint32 *ba;
    213     int inst;   /* associate to _bde_inst_resource[] */
    214     int timeout_count;
    215     _intr_regs_t intr_regs;
    216 } bde_ctrl_t;
    217 
    218 #define VALID_DEVICE(_n) (_n < LINUX_BDE_MAX_DEVICES)
    219 
    220 static bde_ctrl_t _devices[LINUX_BDE_MAX_DEVICES];
    221 
    222 static wait_queue_head_t _ether_interrupt_wq;
    223 static atomic_t _ether_interrupt_has_taken_place = ATOMIC_INIT(0);
    224 
    225 /*
    226  * Multiple instance resource data structure.
    227  * To keep the DMA resource per instance.
    228  * And track the DMA pool usage.
    229  */
    230 static int _bde_multi_inst = 0;
    231 
    232 typedef struct {
    233     unsigned int    inst_id;
    234     unsigned int    dma_offset;
    235     unsigned int    dma_size;
    236     wait_queue_head_t intr_wq;
    237     atomic_t intr;
    238 } bde_inst_resource_t;
    239 
    240 static bde_inst_resource_t _bde_inst_resource[LINUX_BDE_MAX_DEVICES];
    241 
    242 typedef struct {
    243     phys_addr_t  cpu_pbase; /* CPU physical base address of the DMA pool */
    244     phys_addr_t  dma_pbase; /* Bus base address of the DMA pool */
    245     uint32  total_size; /* Total size of the pool in MB */
    246     uint32  offset; /* Current offset of the pool in MB */
    247 }_dma_pool_t;
    248 
    249 static _dma_pool_t _dma_pool;
    250 
    251 #define ONE_MB      (1024 * 1024)
    252 
    253 #ifdef KEYSTONE
    254 /*
    255  * Enforce PCIE transaction ordering. Commit the write transaction.
    256  */
    257 
    258 #define SSOC_WRITEL(val, addr)                  \
    259             do {                                \
    260                 writel((val), (addr));          \
    261                 __asm__ __volatile__("sync");   \
    262             } while(0)
    263 
    264 #else
    265 
    266 #define SSOC_WRITEL(val, addr) \
    267             writel((val), (addr))
    268 
    269 #endif
    270 /*
    271  * Function: _interrupt
    272  *
    273  * Purpose:
    274  *    Interrupt Handler.
    275  *    Mask all interrupts on device and wake up interrupt
    276  *    thread. It is assumed that the interrupt thread unmasks
    277  *    interrupts again when interrupt handling is complete.
    278  * Parameters:
    279  *    ctrl - BDE control structure for this device.
    280  * Returns:
    281  *    Nothing
    282  */
    283 static void 
    284 _cmic_interrupt(bde_ctrl_t *ctrl)
    285 {
    286     int d;
    287     uint32_t mask = 0, stat, imask = 0, fmask = 0;
    288     bde_inst_resource_t *res;
    289 
    290     d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t));
    291     res = &_bde_inst_resource[ctrl->inst];
    292 
    293     /* Check for secondary interrupt handler */
    294     if (lkbde_irq_mask_get(d, &mask, &fmask) < 0) {
    295         fmask = 0;
    296     }
    297 
    298     if (fmask != 0) {
    299         imask = mask & ~fmask;
    300         /* Check for pending user mode interrupts */
    301         stat = user_bde->read(d, CMIC_IRQ_STAT);
    302         if ((stat & imask) == 0) {
    303             /* All handled in kernel mode */
    304             lkbde_irq_mask_set(d, CMIC_IRQ_MASK, imask, 0);
    305             return;
    306         }
    307     }
    308 
    309     lkbde_irq_mask_set(d, CMIC_IRQ_MASK, 0, 0);
    310 
    311     atomic_set(&res->intr, 1);
    312 
    313 #ifdef BDE_LINUX_NON_INTERRUPTIBLE
    314     wake_up(&res->intr_wq);
    315 #else
    316     wake_up_interruptible(&res->intr_wq);
    317 #endif
    318 }
    319 
    320 void
    321 dump_interrupt_regs(bde_ctrl_t *ctrl , int dev)
    322 {
    323     int ind;
    324     uint32_t val;
    325 
    326     if (debug >= 2) {
    327         gprintk("Interrupt timeout count = %d\n", ctrl->timeout_count);
    328         gprintk("Interrupt count = %lu\n", intr_count);
    329         for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) {
    330             READ_INTC_INTR(dev, ctrl->intr_regs.intc_intr_status_base + 4 * ind, val);
    331             gprintk("INTC_INTR_STATUS_REG_%d = 0x%x\n", ind, val);
    332             READ_INTC_INTR(dev, ctrl->intr_regs.intc_intr_raw_status_base + 4 * ind, val);
    333             gprintk("INTC_INTR_RAW_STATUS_REG_%d = 0x%x\n", ind, val);
    334             READ_INTC_INTR(dev, ctrl->intr_regs.intc_intr_enable_base + 4 * ind, val);
    335             gprintk("INTC_INTR_ENABLE_REG_%d = 0x%x\n", ind, val);
    336         }
    337         /* Dump PAXB Register */
    338         READ_INTC_INTR(dev, ctrl->intr_regs.intc_intr_status, val);
    339         gprintk("PAXB_0_PAXB_INTR_STATUS = 0x%x\n", val);
    340         READ_INTC_INTR(dev, ctrl->intr_regs.intc_intr_pacing_ctrl, val);
    341         gprintk("PAXB_0_PAXB_IC_INTR_PACING_CTRL = 0x%x\n", val);
    342         READ_INTC_INTR(dev, ctrl->intr_regs.intc_intr_clear_delay_unit, val);
    343         gprintk("PAXB_0_PAXB_INTRCLR_DELAY_UNIT = 0x%x\n", val);
    344         READ_INTC_INTR(dev, ctrl->intr_regs.intc_intr_pcie_err_status, val);
    345         gprintk("PAXB_0_PCIE_ERROR_STATUS = 0x%x\n", val);
    346 
    347         for (ind = 0; ind < PAXB_INTRCLR_DELAY_REG_NUM; ind++) {
    348             READ_INTC_INTR(dev, ctrl->intr_regs.intc_intr_clear_delay_base + 4 * ind, val);
    349             gprintk("PAXB_0_PAXB_IC_INTRCLR_DELAY_REG_%d = 0x%x\n", ind, val);
    350         }
    351     }
    352     /* Clear interrupt enable registers */
    353     for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) {
    354         WRITE_INTC_INTR(dev, ctrl->intr_regs.intc_intr_enable_base + 4 * ind, 0);
    355     }
    356 }
    357 
    358 static int
    359 _cmicx_interrupt_prepare(bde_ctrl_t *ctrl)
    360 {
    361     int d, ind;
    362     uint32 stat, iena, mask, fmask;
    363 
    364     d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t));
    365 
    366     if (ctrl->dev_type & BDE_PCI_DEV_TYPE) {
    367         READ_INTC_INTR(d, ctrl->intr_regs.intc_intr_clear_mode_0, stat);
    368         /* Clear MSI interrupts immediately to prevent spurious interrupts */
    369         if (stat == 0) {
    370             WRITE_INTC_INTR(d, ctrl->intr_regs.intc_intr_clear_0, 0xFFFFFFFF);
    371             WRITE_INTC_INTR(d, ctrl->intr_regs.intc_intr_clear_1, 0xFFFFFFFF);
    372         }
    373     }
    374 
    375     lkbde_irq_mask_get(d, &mask, &fmask);
    376 
    377     if (fmask) {
    378         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    379             IHOST_READ_INTR(d, ihost_intr_status_base + INTC_PDMA_INTR_REG_IND, stat);
    380             IHOST_READ_INTR(d, ihost_intr_enable_base + INTC_PDMA_INTR_REG_IND, iena);
    381         } else {
    382             READ_INTC_INTR(d, ctrl->intr_regs.intc_intr_status_base + 4 * INTC_PDMA_INTR_REG_IND, stat);
    383             READ_INTC_INTR(d, ctrl->intr_regs.intc_intr_enable_base + 4 * INTC_PDMA_INTR_REG_IND, iena);
    384         }
    385         if (stat & iena) {
    386             if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    387                 IHOST_WRITE_INTR(d, ihost_intr_enable_base + INTC_PDMA_INTR_REG_IND +
    388                     HX5_IHOST_IRQ_MASK_OFFSET, ~0);
    389             } else {
    390                 WRITE_INTC_INTR(d, ctrl->intr_regs.intc_intr_enable_base + 4 * INTC_PDMA_INTR_REG_IND, 0);
    391             }
    392 
    393             for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) {
    394                 if (ind == INTC_PDMA_INTR_REG_IND) {
    395                     continue;
    396                 }
    397                 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    398                     if (ind < INTC_SW_PROG_INTR_REG_IND) {
    399                         continue;
    400                     }
    401                     if (ind == INTC_SW_PROG_INTR_REG_IND) {
    402                         IHOST_READ_INTR(d, ihost_intr_enable_base + ind + HX5_IHOST_IRQ_PEND_OFFSET, stat);
    403                         stat &= INTR_SW_PROG_INTR_BITPOS;
    404                     } else {
    405                         IHOST_READ_INTR(d, ihost_intr_status_base + ind, stat);
    406                         if (ind == INTC_LOW_PRIORITY_INTR_REG_IND) {
    407                             stat &= INTR_LOW_PRIORITY_BITPOS;
    408                         }
    409                     }
    410                 } else {
    411                     READ_INTC_INTR(d, ctrl->intr_regs.intc_intr_status_base + 4 * ind, stat);
    412                     READ_INTC_INTR(d, ctrl->intr_regs.intc_intr_enable_base + 4 * ind, iena);
    413                 }
    414                 if (stat & iena) {
    415                     break;
    416                 }
    417             }
    418             /* No pending interrupts */
    419             if (ind >= INTC_INTR_REG_NUM) {
    420                 return -1;
    421             }
    422         }
    423     }
    424 
    425     /* Disable all interrupts.. Re-enable unserviced interrupts later
    426      * So as to avoid getting new interrupts until the user level driver
    427      * enumerates the interrupts to be serviced
    428      */
    429     for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) {
    430         if (fmask && ind == INTC_PDMA_INTR_REG_IND) {
    431             continue;
    432         }
    433         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    434             if (ind < INTC_SW_PROG_INTR_REG_IND) {
    435                 continue;
    436             }
    437             if (ind == INTC_SW_PROG_INTR_REG_IND) {
    438                 IHOST_WRITE_INTR(d, ihost_intr_enable_base + INTC_SW_PROG_INTR_REG_IND +
    439                     HX5_IHOST_IRQ_MASK_OFFSET, INTR_SW_PROG_INTR_BITPOS);
    440             } else if (ind == INTC_LOW_PRIORITY_INTR_REG_IND) {
    441                 IHOST_WRITE_INTR(d, ihost_intr_enable_base + INTC_LOW_PRIORITY_INTR_REG_IND +
    442                     HX5_IHOST_IRQ_MASK_OFFSET, INTR_LOW_PRIORITY_BITPOS);
    443             } else {
    444                 IHOST_WRITE_INTR(d, ihost_intr_enable_base + ind +
    445                     HX5_IHOST_IRQ_MASK_OFFSET, ~0);
    446             }
    447         } else {
    448             WRITE_INTC_INTR(d, ctrl->intr_regs.intc_intr_enable_base + 4*ind, 0);
    449         }
    450     }
    451     return 0;
    452 }
    453 
    454 static void
    455 _cmicx_interrupt(bde_ctrl_t *ctrl)
    456 {
    457     bde_inst_resource_t *res;
    458 
    459     intr_count++;
    460 
    461     res = &_bde_inst_resource[ctrl->inst];
    462     if (_cmicx_interrupt_prepare(ctrl) < 0) {
    463         return;
    464     }
    465 
    466     /* Notify */
    467     atomic_set(&res->intr, 1);
    468 #ifdef BDE_LINUX_NON_INTERRUPTIBLE
    469     wake_up(&res->intr_wq);
    470 #else
    471     wake_up_interruptible(&res->intr_wq);
    472 #endif
    473 }
    474 
    475 static void
    476 _cmicm_interrupt(bde_ctrl_t *ctrl)
    477 {
    478     int d;
    479     int cmc = BDE_CMICM_PCIE_CMC;
    480     uint32 stat, mask = 0, fmask = 0, imask = 0;
    481     bde_inst_resource_t *res;
    482 
    483     d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t));
    484     res = &_bde_inst_resource[ctrl->inst];
    485 
    486     lkbde_irq_mask_get(d, &mask, &fmask);
    487 
    488     while (fmask) {
    489         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc));
    490         imask = mask & ~fmask;
    491         if (stat & imask) {
    492             break;
    493         }
    494         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc));
    495         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    496             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc));
    497         } else {
    498             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc));
    499         }
    500         if (stat & mask) {
    501             break;
    502         }
    503         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc));
    504         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    505             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc));
    506         } else {
    507             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc));
    508         }
    509         if (stat & mask) {
    510             break;
    511         }
    512         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc));
    513         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    514             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc));
    515         } else {
    516             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc));
    517         }
    518         if (stat & mask) {
    519             break;
    520         }
    521         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT4_OFFSET(cmc));
    522         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    523             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc));
    524         } else {
    525             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc));
    526         }
    527         if (stat & mask) {
    528             break;
    529         }
    530         return;
    531     }
    532 
    533     if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    534         lkbde_irq_mask_set(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(cmc), 0, 0);
    535         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc), 0);
    536         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc), 0);
    537         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc), 0);
    538         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc), 0);
    539         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(1), 0);
    540         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(2), 0);
    541     }
    542     else {
    543         lkbde_irq_mask_set(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), 0, 0);
    544         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), 0);
    545         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), 0);
    546         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), 0);
    547         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), 0);
    548         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(1), 0);
    549         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(2), 0);
    550     }
    551     atomic_set(&res->intr, 1);
    552 #ifdef BDE_LINUX_NON_INTERRUPTIBLE
    553     wake_up(&res->intr_wq);
    554 #else
    555     wake_up_interruptible(&res->intr_wq);
    556 #endif
    557 }
    558 
    559 /* some device has cmc0 only */
    560 static void
    561 _cmicd_cmc0_interrupt(bde_ctrl_t *ctrl)
    562 {
    563     int d;
    564     int cmc = 0;
    565     uint32 stat, mask = 0, fmask = 0, imask = 0;
    566     bde_inst_resource_t *res;
    567 
    568     d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t));
    569     res = &_bde_inst_resource[ctrl->inst];
    570     lkbde_irq_mask_get(d, &mask, &fmask);
    571 
    572     while (fmask) {
    573         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc));
    574         imask = mask & ~fmask;
    575         if (stat & imask) {
    576             break;
    577         }
    578         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc));
    579         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    580             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc));
    581         } else {
    582             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc));
    583         }
    584         if (stat & mask) {
    585             break;
    586         }
    587         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc));
    588         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    589             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc));
    590         } else {
    591             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc));
    592         }
    593         if (stat & mask) {
    594             break;
    595         }
    596         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc));
    597         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    598             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc));
    599         } else {
    600             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc));
    601         }
    602         if (stat & mask) {
    603             break;
    604         }
    605         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT4_OFFSET(cmc));
    606         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    607             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc));
    608         } else {
    609             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc));
    610         }
    611         if (stat & mask) {
    612             break;
    613         }
    614         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT5_OFFSET(cmc));
    615         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    616             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc));
    617         } else {
    618             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc));
    619         }
    620         if (stat & mask) {
    621             break;
    622         }
    623         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT6_OFFSET(cmc));
    624         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    625             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc));
    626         } else {
    627             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc));
    628         }
    629         if (stat & mask) {
    630             break;
    631         }
    632         return;
    633     }
    634 
    635     if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    636         lkbde_irq_mask_set(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(cmc), 0, 0);
    637         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc), 0);
    638         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc), 0);
    639         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc), 0);
    640         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc), 0);
    641         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc), 0);
    642         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc), 0);
    643     } else {
    644         lkbde_irq_mask_set(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), 0, 0);
    645         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), 0);
    646         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), 0);
    647         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), 0);
    648         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), 0);
    649         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc), 0);
    650         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc), 0);
    651     }
    652     atomic_set(&res->intr, 1);
    653 #ifdef BDE_LINUX_NON_INTERRUPTIBLE
    654     wake_up(&res->intr_wq);
    655 #else
    656     wake_up_interruptible(&res->intr_wq);
    657 #endif
    658 }
    659 
    660 static void
    661 _cmicd_interrupt(bde_ctrl_t *ctrl)
    662 {
    663     int d;
    664     int cmc = BDE_CMICD_PCIE_CMC;
    665     uint32 stat, mask = 0, fmask = 0, imask = 0;
    666     bde_inst_resource_t *res;
    667 
    668     d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t));
    669     res = &_bde_inst_resource[ctrl->inst];
    670     lkbde_irq_mask_get(d, &mask, &fmask);
    671 
    672     while (fmask) {
    673         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc));
    674         imask = mask & ~fmask;
    675         if (stat & imask) {
    676             break;
    677         }
    678         /** Check if there are interrupts other than PacketIO interrupts on CMC1 */
    679         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(1));
    680         imask = mask & ~fmask;
    681         if (stat & imask) {
    682             break;
    683         }
    684         /** Check if there are interrupts other than PacketIO interrupts on CMC2 */
    685         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(2));
    686         imask = mask & ~fmask;
    687         if (stat & imask) {
    688             break;
    689         }
    690         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc));
    691         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    692             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc));
    693         } else {
    694             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc));
    695         }
    696         if (stat & mask) {
    697             break;
    698         }
    699         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc));
    700         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    701             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc));
    702         } else {
    703             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc));
    704         }
    705         if (stat & mask) {
    706             break;
    707         }
    708         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc));
    709         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    710             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc));
    711         } else {
    712             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc));
    713         }
    714         if (stat & mask) {
    715             break;
    716         }
    717         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT4_OFFSET(cmc));
    718         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    719             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc));
    720         } else {
    721             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc));
    722         }
    723         if (stat & mask) {
    724             break;
    725         }
    726         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT5_OFFSET(cmc));
    727         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    728             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc));
    729         } else {
    730             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc));
    731         }
    732         if (stat & mask) {
    733             break;
    734         }
    735         stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT6_OFFSET(cmc));
    736         if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    737             mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc));
    738         } else {
    739             mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc));
    740         }
    741         if (stat & mask) {
    742             break;
    743         }
    744         return;
    745     }
    746 
    747     if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    748         lkbde_irq_mask_set(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(cmc), 0, 0);
    749         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc), 0);
    750         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc), 0);
    751         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc), 0);
    752         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc), 0);
    753         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc), 0);
    754         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc), 0);
    755         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(1), 0);
    756         user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(2), 0);
    757     } else {
    758         lkbde_irq_mask_set(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), 0, 0);
    759         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), 0);
    760         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), 0);
    761         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), 0);
    762         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), 0);
    763         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc), 0);
    764         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc), 0);
    765         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(1), 0);
    766         user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(2), 0);
    767     }
    768     atomic_set(&res->intr, 1);
    769 #ifdef BDE_LINUX_NON_INTERRUPTIBLE
    770     wake_up(&res->intr_wq);
    771 #else
    772     wake_up_interruptible(&res->intr_wq);
    773 #endif
    774 }
    775 
    776 static void 
    777 _bcm88750_interrupt(bde_ctrl_t *ctrl)
    778 {
    779     int d;
    780     bde_inst_resource_t *res;
    781 
    782     d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t));
    783     res = &_bde_inst_resource[ctrl->inst];
    784     lkbde_irq_mask_set(d, CMIC_IRQ_MASK, 0, 0);
    785 
    786     lkbde_irq_mask_set(d, CMIC_IRQ_MASK_1, 0, 0); 
    787     lkbde_irq_mask_set(d, CMIC_IRQ_MASK_2, 0, 0);
    788     atomic_set(&res->intr, 1);
    789 #ifdef BDE_LINUX_NON_INTERRUPTIBLE
    790     wake_up(&res->intr_wq);
    791 #else
    792     wake_up_interruptible(&res->intr_wq);
    793 #endif
    794 }
    795 
    796 /* The actual interrupt handler of ethernet devices */
    797 static void 
    798 _ether_interrupt(bde_ctrl_t *ctrl)
    799 {
    800     SSOC_WRITEL(0, ctrl->ba + 0x024/4);
    801 
    802     atomic_set(&_ether_interrupt_has_taken_place, 1);
    803 #ifdef BDE_LINUX_NON_INTERRUPTIBLE
    804     wake_up(&_ether_interrupt_wq);
    805 #else
    806     wake_up_interruptible(&_ether_interrupt_wq);
    807 #endif
    808 }
    809 
    810 
    811 static struct _intr_mode_s {
    812     isr_f isr;
    813     const char *name;
    814 } _intr_mode[] = {
    815     { (isr_f)_cmic_interrupt,       "CMIC/CMICe" },
    816     { (isr_f)_cmicm_interrupt,      "CMICm" },
    817     { (isr_f)_cmicd_interrupt,      "CMICd" },
    818     { (isr_f)_cmicd_cmc0_interrupt, "CMICd CMC0" },
    819     { (isr_f)_bcm88750_interrupt,   "BCM88750" },
    820     { (isr_f)_cmicx_interrupt,      "CMICx" },
    821     { NULL, NULL }
    822 };
    823 
    824 static const char *
    825 _intr_mode_str(void *isr)
    826 {
    827     int imx;
    828 
    829     imx = 0;
    830     while (_intr_mode[imx].isr != NULL) {
    831         if (isr == _intr_mode[imx].isr) {
    832             return _intr_mode[imx].name;
    833         }
    834         imx++;
    835     }
    836     return NULL;
    837 }
    838 
    839 static void
    840 _intr_regs_init(bde_ctrl_t *ctrl, int hx5_intr)
    841 {
    842     if (hx5_intr) {
    843         ctrl->intr_regs.intc_intr_status_base = HX5_INTC_INTR_STATUS_BASE;
    844         ctrl->intr_regs.intc_intr_enable_base = HX5_INTC_INTR_ENABLE_BASE;
    845         ctrl->intr_regs.intc_intr_raw_status_base = HX5_INTC_INTR_RAW_STATUS_BASE;
    846         ctrl->intr_regs.intc_intr_clear_0 = HX5_PAXB_0_PAXB_IC_INTRCLR_0;
    847         ctrl->intr_regs.intc_intr_clear_1 = HX5_PAXB_0_PAXB_IC_INTRCLR_1;
    848         ctrl->intr_regs.intc_intr_clear_mode_0 = HX5_PAXB_0_PAXB_IC_INTRCLR_MODE_0;
    849         ctrl->intr_regs.intc_intr_clear_mode_1 = HX5_PAXB_0_PAXB_IC_INTRCLR_MODE_1;
    850         ctrl->intr_regs.intc_intr_status = HX5_PAXB_0_PAXB_INTR_STATUS;
    851         ctrl->intr_regs.intc_intr_pacing_ctrl = HX5_PAXB_0_PAXB_IC_INTR_PACING_CTRL;
    852         ctrl->intr_regs.intc_intr_clear_delay_unit = HX5_PAXB_0_PAXB_INTRCLR_DELAY_UNIT;
    853         ctrl->intr_regs.intc_intr_clear_delay_base = HX5_PAXB_0_PAXB_IC_INTRCLR_DELAY_BASE;
    854         ctrl->intr_regs.intc_intr_pcie_err_status = HX5_PAXB_0_PCIE_ERROR_STATUS;
    855 
    856     } else {
    857         ctrl->intr_regs.intc_intr_status_base = INTC_INTR_STATUS_BASE;
    858         ctrl->intr_regs.intc_intr_raw_status_base = INTC_INTR_RAW_STATUS_BASE;
    859         ctrl->intr_regs.intc_intr_enable_base = INTC_INTR_ENABLE_BASE;
    860         ctrl->intr_regs.intc_intr_clear_0 = PAXB_0_PAXB_IC_INTRCLR_0;
    861         ctrl->intr_regs.intc_intr_clear_1 = PAXB_0_PAXB_IC_INTRCLR_1;
    862         ctrl->intr_regs.intc_intr_clear_mode_0 = PAXB_0_PAXB_IC_INTRCLR_MODE_0;
    863         ctrl->intr_regs.intc_intr_clear_mode_1 = PAXB_0_PAXB_IC_INTRCLR_MODE_1;
    864         ctrl->intr_regs.intc_intr_status = PAXB_0_PAXB_INTR_STATUS;
    865         ctrl->intr_regs.intc_intr_pacing_ctrl = PAXB_0_PAXB_IC_INTR_PACING_CTRL;
    866         ctrl->intr_regs.intc_intr_clear_delay_unit = PAXB_0_PAXB_INTRCLR_DELAY_UNIT;
    867         ctrl->intr_regs.intc_intr_clear_delay_base = PAXB_0_PAXB_IC_INTRCLR_DELAY_BASE;
    868         ctrl->intr_regs.intc_intr_pcie_err_status = PAXB_0_PCIE_ERROR_STATUS;
    869 
    870     }
    871 }
    872 
    873 static void
    874 _devices_init(int d)
    875 {
    876     bde_ctrl_t *ctrl;
    877     uint32 ver;
    878     uint16 device_id_mask = 0xFFF0;
    879     uint16 device_id;
    880     uint32 state = 0;
    881 
    882     (void)lkbde_dev_state_get(d, &state);
    883     if (state == BDE_DEV_STATE_REMOVED) {
    884         return;
    885     }
    886 
    887     ctrl = &_devices[d];
    888     /* Initialize our control info */
    889     ctrl->dev_type = user_bde->get_dev_type(d);
    890     ctrl->devid = user_bde->get_dev(d)->device;
    891     ctrl->inst = 0;
    892 
    893     if (BDE_DEV_MEM_MAPPED(ctrl->dev_type)) {
    894         ctrl->enabled = 0;
    895         ctrl->ba = lkbde_get_dev_virt(d);
    896     }
    897     if (ctrl->dev_type & BDE_SWITCH_DEV_TYPE) {
    898         switch (user_bde->get_dev(d)->device) {
    899         case BCM88750_DEVICE_ID:
    900         case BCM88753_DEVICE_ID:
    901         case BCM88754_DEVICE_ID:
    902         case BCM88755_DEVICE_ID:
    903         case BCM88752_DEVICE_ID:
    904             ctrl->isr = (isr_f)_bcm88750_interrupt;
    905             break;
    906         case BCM53540_DEVICE_ID:
    907         case BCM53547_DEVICE_ID:
    908         case BCM53548_DEVICE_ID:
    909         case BCM53549_DEVICE_ID:
    910             ctrl->isr = (isr_f)_cmicd_cmc0_interrupt;
    911             break;
    912         case BCM88670_DEVICE_ID:
    913         case BCM88671_DEVICE_ID:
    914         case BCM88671M_DEVICE_ID:
    915         case BCM88672_DEVICE_ID:
    916         case BCM88673_DEVICE_ID:
    917         case BCM88674_DEVICE_ID:
    918         case BCM88675_DEVICE_ID:
    919         case BCM88675M_DEVICE_ID:
    920         case BCM88676_DEVICE_ID:
    921         case BCM88676M_DEVICE_ID:
    922         case BCM88677_DEVICE_ID:
    923         case BCM88678_DEVICE_ID:
    924         case BCM88679_DEVICE_ID:
    925         case BCM88370_DEVICE_ID:
    926         case BCM88371_DEVICE_ID:
    927         case BCM88371M_DEVICE_ID:
    928         case BCM88375_DEVICE_ID:
    929         case BCM88376_DEVICE_ID:
    930         case BCM88376M_DEVICE_ID:
    931         case BCM88377_DEVICE_ID:
    932         case BCM88378_DEVICE_ID:
    933         case BCM88379_DEVICE_ID:
    934         case BCM88681_DEVICE_ID:
    935         case BCM88682_DEVICE_ID:
    936         case BCM88683_DEVICE_ID:
    937         case BCM88684_DEVICE_ID:
    938         case BCM88685_DEVICE_ID:
    939         case BCM88687_DEVICE_ID:
    940         case BCM88380_DEVICE_ID:
    941         case BCM88381_DEVICE_ID:
    942         case BCM88680_DEVICE_ID:
    943         case BCM88770_DEVICE_ID:
    944         case BCM88773_DEVICE_ID:
    945         case BCM88774_DEVICE_ID:
    946         case BCM88775_DEVICE_ID:
    947         case BCM88776_DEVICE_ID:
    948         case BCM88777_DEVICE_ID:
    949         case BCM88470_DEVICE_ID:
    950         case BCM88470P_DEVICE_ID:
    951         case BCM88471_DEVICE_ID:
    952         case BCM88473_DEVICE_ID:
    953         case BCM88474_DEVICE_ID:
    954         case BCM88474H_DEVICE_ID:
    955         case BCM88476_DEVICE_ID:
    956         case BCM88477_DEVICE_ID:
    957         case BCM88270_DEVICE_ID:
    958         case BCM88272_DEVICE_ID:
    959         case BCM88273_DEVICE_ID:
    960         case BCM88274_DEVICE_ID:
    961         case BCM88278_DEVICE_ID:
    962         case BCM88279_DEVICE_ID:
    963         case BCM8206_DEVICE_ID:
    964         case BCM88950_DEVICE_ID:
    965         case BCM88953_DEVICE_ID:
    966         case BCM88954_DEVICE_ID:
    967         case BCM88955_DEVICE_ID:
    968         case BCM88956_DEVICE_ID:
    969         case BCM88772_DEVICE_ID:
    970         case BCM88952_DEVICE_ID:
    971             ctrl->isr = (isr_f)_cmicd_interrupt;
    972             break;
    973         case BCM56370_DEVICE_ID:
    974         case BCM56371_DEVICE_ID:
    975         case BCM56372_DEVICE_ID:
    976         case BCM56374_DEVICE_ID:
    977         case BCM56375_DEVICE_ID:
    978         case BCM56376_DEVICE_ID:
    979         case BCM56377_DEVICE_ID:
    980         case BCM56577_DEVICE_ID:
    981         case BCM56578_DEVICE_ID:
    982         case BCM56579_DEVICE_ID:
    983         case BCM56273_DEVICE_ID:
    984         case BCM56274_DEVICE_ID:
    985         case BCM56275_DEVICE_ID:
    986         case BCM56276_DEVICE_ID:
    987         case BCM56277_DEVICE_ID:
    988         case BCM56278_DEVICE_ID:
    989         case BCM56279_DEVICE_ID:
    990         case BCM56575_DEVICE_ID:
    991             ctrl->isr = (isr_f)_cmicx_interrupt;
    992             if (ctrl->dev_type & BDE_AXI_DEV_TYPE) {
    993                 if (!ihost_intr_enable_base) {
    994                     ihost_intr_enable_base = (uint32_t *)IOREMAP(HX5_IHOST_GICD_ISENABLERN_1,
    995                                                                  HX5_IHOST_INTR_MAP_NUM);
    996                 }
    997                 if (!ihost_intr_status_base) {
    998                     ihost_intr_status_base = (uint32_t *)IOREMAP(HX5_INTC_INTR_RAW_STATUS_REG0,
    999                                                                  HX5_IHOST_INTR_STATUS_MAP_NUM);
   1000                 }
   1001             }
   1002             _intr_regs_init(ctrl, 1);
   1003             break;
   1004         default:
   1005             /* Get CMIC version */
   1006             if (user_bde->get_cmic_ver(d, &ver) != 0) {
   1007                 ver = -1;
   1008             }
   1009             device_id = ctrl->devid & device_id_mask;
   1010             /* TH/TH+/TH2 should use cmicd interrupt handler */
   1011             if (BCM56960_DEVICE_ID == device_id ||
   1012                 BCM56930_DEVICE_ID == device_id ||
   1013                 BCM56970_DEVICE_ID == device_id) {
   1014                 ctrl->isr = (isr_f)_cmicd_interrupt;
   1015             }
   1016             /* check if version is CMICX */
   1017             else if (ver == 0x04) {
   1018                 ctrl->isr = (isr_f)_cmicx_interrupt;
   1019                 _intr_regs_init(ctrl, 0);
   1020             } else {
   1021                 ctrl->isr = (isr_f)_cmic_interrupt;
   1022                 if ((ctrl->dev_type & BDE_256K_REG_SPACE) &&
   1023 #ifdef BCM_PETRA_SUPPORT /* FIXME remove code when hardware design is fixed */
   1024                     ctrl->devid != 0x1234 &&
   1025 #endif
   1026                     readl(ctrl->ba + CMICE_DEV_REV_ID) == 0) {
   1027                     ctrl->isr = (isr_f)_cmicm_interrupt;
   1028                 }
   1029             }
   1030             break;
   1031         }
   1032 
   1033         /* configure interrupts for DNX devices using iproc >=14 */
   1034 #if defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT)
   1035         switch (user_bde->get_dev(d)->device & DNXC_DEVID_FAMILY_MASK) {
   1036 #ifdef BCM_DNX_SUPPORT
   1037           case JERICHO2_DEVICE_ID:
   1038           case J2C_DEVICE_ID:
   1039           case J2C_2ND_DEVICE_ID:
   1040           case Q2A_DEVICE_ID:
   1041           case Q2U_DEVICE_ID:
   1042           case J2P_DEVICE_ID:
   1043 #endif
   1044 #ifdef BCM_DNXF_SUPPORT
   1045           case  BCM88790_DEVICE_ID:
   1046 #endif
   1047             ctrl->isr = (isr_f)_cmicx_interrupt;
   1048             _intr_regs_init(ctrl, 0);
   1049             break;
   1050         }
   1051 #endif /* defined(BCM_DNXF_SUPPORT) || defined(BCM_DNX_SUPPORT) */
   1052 
   1053         if (_intr_mode_str(ctrl->isr) == NULL) {
   1054             gprintk("Warning: Unknown interrupt mode\n");
   1055         }
   1056     }
   1057 }
   1058 /*
   1059  * Function: _init
   1060  *
   1061  * Purpose:
   1062  *    Module initialization.
   1063  *    Attaches to kernel BDE.
   1064  * Parameters:
   1065  *    None
   1066  * Returns:
   1067  *    Always 0
   1068  */
   1069 static int
   1070 _init(void)
   1071 {
   1072     int i;
   1073     phys_addr_t cpu_pbase, dma_pbase;
   1074     ssize_t dmasize;
   1075     bde_inst_resource_t *res;
   1076 
   1077     /* Connect to the kernel bde */
   1078     if ((linux_bde_create(NULL, &user_bde) < 0) || user_bde == NULL) {
   1079         return -ENODEV;
   1080     }
   1081 
   1082     init_waitqueue_head(&_ether_interrupt_wq);
   1083 
   1084     lkbde_get_dma_info(&cpu_pbase, &dma_pbase, &dmasize);
   1085 
   1086     memset(&_dma_pool, 0, sizeof(_dma_pool));
   1087     _dma_pool.cpu_pbase = cpu_pbase;
   1088     _dma_pool.dma_pbase = dma_pbase;
   1089     _dma_pool.total_size = dmasize / ONE_MB;
   1090 
   1091     memset(_devices, 0, sizeof(_devices));
   1092 
   1093     /* Use _bde_inst_resource[0] as the default resource */
   1094     memset(_bde_inst_resource, 0, sizeof(_bde_inst_resource));
   1095     res = &_bde_inst_resource[0];
   1096     res->dma_offset = 0;
   1097     res->dma_size = _dma_pool.total_size;
   1098     init_waitqueue_head(&res->intr_wq);
   1099     atomic_set(&res->intr, 0);
   1100 
   1101     ihost_intr_enable_base = NULL;
   1102     ihost_intr_status_base = NULL;
   1103 
   1104     for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) {
   1105         res->inst_id |= (1 << i);
   1106         _devices_init(i);
   1107     }
   1108 
   1109     if (intr_timeout > 0) {
   1110         gprintk("Interruptible wait timeout = %d msecs\n", intr_timeout);
   1111     }
   1112 
   1113     return 0;
   1114 }
   1115 
   1116 /*
   1117  * Function: _cleanup
   1118  *
   1119  * Purpose:
   1120  *    Module cleanup function.
   1121  * Parameters:
   1122  *    None
   1123  * Returns:
   1124  *    Always 0
   1125  */
   1126 static int
   1127 _cleanup(void)
   1128 {
   1129     int i;
   1130 
   1131     if (user_bde) {
   1132         for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) {
   1133             if (_devices[i].enabled &&
   1134                 BDE_DEV_MEM_MAPPED(_devices[i].dev_type)) {
   1135                 user_bde->interrupt_disconnect(i);
   1136             }
   1137             lkbde_dev_instid_set(i, 0);
   1138         }
   1139         linux_bde_destroy(user_bde);
   1140         user_bde = NULL;
   1141     }
   1142 
   1143     if (ihost_intr_enable_base) {
   1144         iounmap(ihost_intr_enable_base);
   1145         ihost_intr_enable_base = NULL;
   1146     }
   1147     if (ihost_intr_status_base) {
   1148         iounmap(ihost_intr_status_base);
   1149         ihost_intr_status_base = NULL;
   1150     }
   1151 
   1152     return 0;
   1153 }
   1154 
   1155 /*
   1156  * Function: _pprint
   1157  *
   1158  * Purpose:
   1159  *    Print proc filesystem information.
   1160  * Parameters:
   1161  *    None
   1162  * Returns:
   1163  *    Always 0
   1164  */
   1165 static int
   1166 _pprint(void)
   1167 {
   1168     int idx;
   1169     const char *name;
   1170     bde_inst_resource_t *res;
   1171     uint32 state, instid;
   1172 
   1173     pprintf("Broadcom Device Enumerator (%s)\n", LINUX_USER_BDE_NAME);
   1174     for (idx = 0; idx < user_bde->num_devices(BDE_ALL_DEVICES); idx++) {
   1175         name = _intr_mode_str(_devices[idx].isr);
   1176         if (name == NULL) {
   1177             name = "unknown";
   1178         }
   1179         pprintf("\t%d: Interrupt mode  %s ",idx, name);
   1180         (void)lkbde_dev_state_get(idx, &state);
   1181         if (state == BDE_DEV_STATE_REMOVED) {
   1182             pprintf(" Device REMOVED ! \n");
   1183         } else {
   1184             (void)lkbde_dev_instid_get(idx, &instid);
   1185             if (instid) {
   1186                 pprintf("Inst id 0x%x\n",instid);
   1187             } else {
   1188                 pprintf("\n");
   1189             }
   1190         }
   1191     }
   1192     pprintf("Instance resource \n");
   1193 
   1194     for (idx = 0; idx < user_bde->num_devices(BDE_ALL_DEVICES); idx++) {
   1195         res = &_bde_inst_resource[idx];
   1196         if (res->inst_id) {
   1197             pprintf("\tDev mask 0x%x : "
   1198                     "DMA offset %d size %d MB\n",
   1199                     res->inst_id,
   1200                     res->dma_offset,
   1201                     res->dma_size);
   1202         }
   1203     }
   1204 
   1205     return 0;
   1206 }
   1207 
   1208 /* 
   1209  * Allocate the DMA resource from DMA pool
   1210  * Parameter :
   1211  * dma_size (IN): allocate dma_size in MB
   1212  * dma_offset (OUT): dma offset in MB
   1213  */
   1214 static int
   1215 _dma_resource_alloc(unsigned int dma_size, unsigned int *dma_offset)
   1216 {
   1217     uint32 left;
   1218 
   1219     left = _dma_pool.total_size - _dma_pool.offset;
   1220     if (dma_size > left) {
   1221         gprintk("ERROR: Run out the dma resource!\n");
   1222         return -1;
   1223     }
   1224     *dma_offset = _dma_pool.offset;
   1225     _dma_pool.offset += dma_size;
   1226     return 0;
   1227 }
   1228 
   1229 static int
   1230 _dma_resource_get(int inst_id, phys_addr_t *cpu_pbase, phys_addr_t *dma_pbase, ssize_t* size)
   1231 {
   1232     int i;
   1233     unsigned int dma_size = 0, dma_offset = 0;
   1234     bde_inst_resource_t *res;
   1235 
   1236     for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) {
   1237         res = &_bde_inst_resource[i];
   1238         if (res->inst_id == inst_id) {
   1239             dma_size = res->dma_size;
   1240             dma_offset = res->dma_offset;
   1241             break;
   1242         }
   1243     }
   1244 
   1245     *cpu_pbase = _dma_pool.cpu_pbase + dma_offset * ONE_MB;
   1246     *dma_pbase = _dma_pool.dma_pbase + dma_offset * ONE_MB;
   1247     *size = dma_size * ONE_MB;
   1248 
   1249     return 0;
   1250 }
   1251 
   1252 static int
   1253 _instance_validate(unsigned int inst_id, unsigned int dmasize)
   1254 {
   1255     int i;
   1256     bde_inst_resource_t *res;
   1257 
   1258     for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) {
   1259         res = &_bde_inst_resource[i];
   1260         if (res->inst_id == inst_id) {
   1261             if (res->dma_size != dmasize) {
   1262                 if(_devices[i].inst == 0){
   1263                     /* Skip _instance_validate (not init yet) */
   1264                     return LUBDE_SUCCESS;
   1265                 }
   1266                 gprintk("ERROR: dma_size mismatch\n");
   1267                 return LUBDE_FAIL;
   1268             }
   1269             return (1);
   1270         }
   1271     }
   1272     return LUBDE_SUCCESS;
   1273 }
   1274 
   1275 static int
   1276 _device_reprobe(void)
   1277 {
   1278     int i;
   1279 
   1280     for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) {
   1281         if (_devices[i].devid == 0) {
   1282             _devices_init(i);
   1283         }
   1284     }
   1285     return 0;
   1286 }
   1287 
   1288 static int
   1289 _instance_attach(unsigned int inst_id, unsigned int dma_size)
   1290 {
   1291     unsigned int dma_offset;
   1292     int i, exist;
   1293     bde_inst_resource_t *res;
   1294     int inst_idx = -1;
   1295     uint32 instid;
   1296 
   1297     /* Reprobe the system for hot-plugged device */
   1298     _device_reprobe();
   1299 
   1300     /* Validate the resource with inst_id */
   1301     exist = _instance_validate(inst_id, dma_size);
   1302     if (exist < 0) {
   1303         return LUBDE_FAIL;
   1304     }
   1305     if (exist > 0) {
   1306         return LUBDE_SUCCESS;
   1307     }
   1308     if (_dma_resource_alloc(dma_size, &dma_offset) < 0) {
   1309         return LUBDE_FAIL;
   1310     }
   1311     for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) {
   1312         res = &_bde_inst_resource[i];
   1313         if ((_bde_multi_inst == 0) || (res->inst_id == 0)) {
   1314             res->inst_id = inst_id;
   1315             res->dma_offset = dma_offset;
   1316             res->dma_size = dma_size;
   1317             _bde_multi_inst++;
   1318             inst_idx = i;
   1319             init_waitqueue_head(&res->intr_wq);
   1320             atomic_set(&res->intr, 0);
   1321             break;
   1322         }
   1323     }
   1324 
   1325     for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) {
   1326         if (inst_id & (1 << i)) {
   1327             _devices[i].inst = inst_idx;
   1328             /* Pass the instid to the kernel BDE */
   1329             if (lkbde_dev_instid_get(i, &instid) == 0) {
   1330                 if (!instid) {
   1331                     lkbde_dev_instid_set(i, inst_id);
   1332                 }
   1333             }
   1334         }
   1335     }
   1336 
   1337     return LUBDE_SUCCESS;
   1338 }
   1339 
   1340 /*
   1341  * Function: _ioctl
   1342  *
   1343  * Purpose:
   1344  *    Handle IOCTL commands from user mode.
   1345  * Parameters:
   1346  *    cmd - IOCTL cmd
   1347  *    arg - IOCTL parameters
   1348  * Returns:
   1349  *    0 on success, <0 on error
   1350  */
   1351 static int 
   1352 _ioctl(unsigned int cmd, unsigned long arg)
   1353 {
   1354     lubde_ioctl_t io;
   1355     phys_addr_t cpu_pbase, dma_pbase;
   1356     ssize_t size;
   1357     const ibde_dev_t *bde_dev;
   1358     int inst_id;
   1359     bde_inst_resource_t *res;
   1360     uint32_t *mapaddr;
   1361 
   1362     if (copy_from_user(&io, (void *)arg, sizeof(io))) {
   1363         return -EFAULT;
   1364     }
   1365   
   1366     io.rc = LUBDE_SUCCESS;
   1367   
   1368     switch(cmd) {
   1369     case LUBDE_VERSION:
   1370         io.d0 = KBDE_VERSION;
   1371         break;
   1372     case LUBDE_GET_NUM_DEVICES:
   1373         io.d0 = user_bde->num_devices(io.dev);
   1374         break;
   1375     case LUBDE_GET_DEVICE:
   1376         if (!VALID_DEVICE(io.dev)) {
   1377             return -EINVAL;
   1378         }
   1379         bde_dev = user_bde->get_dev(io.dev);
   1380         if (bde_dev) {
   1381             io.d0 = bde_dev->device;
   1382             io.d1 = bde_dev->rev;
   1383             io.dx.dw[0] = bde_dev->dev_unique_id;
   1384             if (BDE_DEV_MEM_MAPPED(_devices[io.dev].dev_type)) {
   1385                 /* Get physical address to map */
   1386                 io.d2 = lkbde_get_dev_phys(io.dev);
   1387                 io.d3 = lkbde_get_dev_phys_hi(io.dev);
   1388             }
   1389         } else {
   1390             io.rc = LUBDE_FAIL;
   1391         }
   1392         break;
   1393     case LUBDE_GET_DEVICE_TYPE:
   1394         if (!VALID_DEVICE(io.dev)) {
   1395             return -EINVAL;
   1396         }
   1397         io.d0 = _devices[io.dev].dev_type;
   1398         break;
   1399     case LUBDE_GET_BUS_FEATURES:
   1400         user_bde->pci_bus_features(io.dev, (int *) &io.d0, (int *) &io.d1,
   1401                                    (int *) &io.d2);
   1402         break;
   1403     case LUBDE_PCI_CONFIG_PUT32:
   1404         if (!VALID_DEVICE(io.dev)) {
   1405             return -EINVAL;
   1406         }
   1407         if (_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) {
   1408             user_bde->pci_conf_write(io.dev, io.d0, io.d1);
   1409         } else {
   1410             io.rc = LUBDE_FAIL;
   1411         }
   1412         break;
   1413     case LUBDE_PCI_CONFIG_GET32:
   1414         if (!VALID_DEVICE(io.dev)) {
   1415             return -EINVAL;
   1416         }
   1417         if (_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) {
   1418             io.d0 = user_bde->pci_conf_read(io.dev, io.d0);
   1419         } else {
   1420             io.rc = LUBDE_FAIL;
   1421         }
   1422         break;
   1423     case LUBDE_GET_DMA_INFO:
   1424         inst_id = io.dev;
   1425         if (_bde_multi_inst){
   1426             _dma_resource_get(inst_id, &cpu_pbase, &dma_pbase, &size);
   1427         } else {
   1428             lkbde_get_dma_info(&cpu_pbase, &dma_pbase, &size);
   1429         }
   1430         io.d0 = dma_pbase;
   1431         io.d1 = size;
   1432         /* Optionally enable DMA mmap via /dev/linux-kernel-bde */
   1433         io.d2 = USE_LINUX_BDE_MMAP;
   1434         /* Get physical address for mmap */
   1435         io.dx.dw[0] = cpu_pbase;
   1436 #ifdef PHYS_ADDRS_ARE_64BITS
   1437         io.dx.dw[1] = cpu_pbase >> 32;
   1438         io.d3 = dma_pbase >> 32;
   1439 #else
   1440         io.dx.dw[1] = 0;
   1441         io.d3 = 0;
   1442 #endif
   1443         break;
   1444     case LUBDE_ENABLE_INTERRUPTS:
   1445         if (!VALID_DEVICE(io.dev)) {
   1446             return -EINVAL;
   1447         }
   1448         if (_devices[io.dev].dev_type & BDE_SWITCH_DEV_TYPE) {
   1449             if (_devices[io.dev].isr && !_devices[io.dev].enabled) {
   1450                 user_bde->interrupt_connect(io.dev,
   1451                                             _devices[io.dev].isr,
   1452                                             _devices+io.dev);
   1453                 _devices[io.dev].enabled = 1;
   1454             }
   1455         } else {
   1456             /* Process ethernet device interrupt */
   1457             /* FIXME: for multiple chips */
   1458             if (!_devices[io.dev].enabled) {
   1459                 user_bde->interrupt_connect(io.dev,
   1460                                             (void(*)(void *))_ether_interrupt, 
   1461                                             _devices+io.dev);
   1462                 _devices[io.dev].enabled = 1;
   1463             }
   1464         }
   1465         break;
   1466     case LUBDE_DISABLE_INTERRUPTS:
   1467         if (!VALID_DEVICE(io.dev)) {
   1468             return -EINVAL;
   1469         }
   1470         if (_devices[io.dev].enabled) {
   1471             user_bde->interrupt_disconnect(io.dev);
   1472             _devices[io.dev].enabled = 0;
   1473         }
   1474         break;
   1475     case LUBDE_WAIT_FOR_INTERRUPT:
   1476         if (!VALID_DEVICE(io.dev)) {
   1477             return -EINVAL;
   1478         }
   1479         if (_devices[io.dev].dev_type & BDE_SWITCH_DEV_TYPE) {
   1480             res = &_bde_inst_resource[_devices[io.dev].inst];
   1481 #ifdef BDE_LINUX_NON_INTERRUPTIBLE
   1482             wait_event_timeout(res->intr_wq, 
   1483                                atomic_read(&res->intr) != 0, 100);
   1484 
   1485 #else
   1486             /* CMICX Devices */
   1487             if ((_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) &&
   1488                 (_devices[io.dev].isr == (isr_f)_cmicx_interrupt)  &&
   1489                 (intr_timeout > 0)) {
   1490                 unsigned long t_jiffies;
   1491                 int err=0;
   1492                 t_jiffies =  msecs_to_jiffies(intr_timeout);
   1493                 err = wait_event_interruptible_timeout(res->intr_wq,
   1494                              atomic_read(&res->intr) != 0,
   1495                              t_jiffies);
   1496                 /* Timeout happend and condition not set */
   1497                 if (err == 0) {
   1498                     bde_ctrl_t *ctrl;
   1499                     ctrl = &_devices[io.dev];
   1500                     ctrl->timeout_count++;
   1501                     if (debug >= 1) {
   1502                         gprintk("Timeout happend and condition not set\n");
   1503                     }
   1504                     dump_interrupt_regs(ctrl, io.dev);
   1505                 } else if (err == -ERESTARTSYS) {
   1506                     if (debug >= 1) {
   1507                        gprintk("Interrupted by Signal\n");
   1508                     }
   1509                 }
   1510             } else {
   1511                 wait_event_interruptible(res->intr_wq,
   1512                                       atomic_read(&res->intr) != 0);
   1513             }
   1514 #endif
   1515             /* 
   1516              * Even if we get multiple interrupts, we 
   1517              * only run the interrupt handler once.
   1518              */
   1519             atomic_set(&res->intr, 0);
   1520         } else {
   1521 #ifdef BDE_LINUX_NON_INTERRUPTIBLE
   1522             wait_event_timeout(_ether_interrupt_wq,     
   1523                                atomic_read(&_ether_interrupt_has_taken_place) != 0, 100);
   1524 #else
   1525             wait_event_interruptible(_ether_interrupt_wq,     
   1526                                      atomic_read(&_ether_interrupt_has_taken_place) != 0);
   1527 
   1528 #endif
   1529             /* 
   1530              * Even if we get multiple interrupts, we 
   1531              * only run the interrupt handler once.
   1532              */
   1533             atomic_set(&_ether_interrupt_has_taken_place, 0);
   1534         }
   1535         break;
   1536     case LUBDE_USLEEP:
   1537     case LUBDE_UDELAY:
   1538     case LUBDE_SEM_OP:
   1539         return -EINVAL;
   1540     case LUBDE_WRITE_IRQ_MASK:
   1541         io.rc = lkbde_irq_mask_set(io.dev, io.d0, io.d1, 0);
   1542         break;
   1543     case LUBDE_SPI_READ_REG:
   1544         if (user_bde->spi_read(io.dev, io.d0, io.dx.buf, io.d1) == -1) {
   1545             io.rc = LUBDE_FAIL;
   1546         } 
   1547         break;
   1548     case LUBDE_SPI_WRITE_REG:
   1549         if (user_bde->spi_write(io.dev, io.d0, io.dx.buf, io.d1) == -1) {
   1550             io.rc = LUBDE_FAIL;
   1551         }
   1552         break;
   1553     case LUBDE_READ_REG_16BIT_BUS:
   1554         io.d1 = user_bde->read(io.dev, io.d0);
   1555         break;
   1556     case LUBDE_WRITE_REG_16BIT_BUS:
   1557         io.rc = user_bde->write(io.dev, io.d0, io.d1);
   1558         break;
   1559 #ifdef BCM_SAND_SUPPORT
   1560     case LUBDE_CPU_WRITE_REG:
   1561     {
   1562         if (lkbde_cpu_write(io.dev, io.d0, (uint32*)io.dx.buf) == -1) {
   1563             io.rc = LUBDE_FAIL;
   1564         }
   1565         break;
   1566     }
   1567     case LUBDE_CPU_READ_REG:
   1568     {
   1569         if (lkbde_cpu_read(io.dev, io.d0, (uint32*)io.dx.buf) == -1) {
   1570             io.rc = LUBDE_FAIL;
   1571         }
   1572         break;
   1573     }
   1574     case LUBDE_CPU_PCI_REGISTER:
   1575     {
   1576         if (lkbde_cpu_pci_register(io.dev) == -1) {
   1577             io.rc = LUBDE_FAIL;
   1578         }
   1579         break;
   1580     }
   1581 #endif
   1582     case LUBDE_DEV_RESOURCE:
   1583         if (!VALID_DEVICE(io.dev)) {
   1584             return -EINVAL;
   1585         }
   1586         bde_dev = user_bde->get_dev(io.dev);
   1587         if (bde_dev) {
   1588             if (BDE_DEV_MEM_MAPPED(_devices[io.dev].dev_type)) {
   1589                 /* Get physical address to map */
   1590                 io.rc = lkbde_get_dev_resource(io.dev, io.d0,
   1591                                                &io.d1, &io.d2, &io.d3);
   1592             }
   1593         } else {
   1594             io.rc = LUBDE_FAIL;
   1595         }
   1596         break;
   1597     case LUBDE_IPROC_READ_REG:
   1598         if (!VALID_DEVICE(io.dev)) {
   1599             return -EINVAL;
   1600         }
   1601         if (_devices[io.dev].dev_type & BDE_AXI_DEV_TYPE) {
   1602             mapaddr = IOREMAP(io.d0, sizeof(uint32_t));
   1603             if (mapaddr == NULL) {
   1604                 io.rc = LUBDE_FAIL;
   1605                 return -1;
   1606             }
   1607             io.d1 = readl(mapaddr);
   1608             iounmap(mapaddr);
   1609         } else {
   1610             io.d1 = user_bde->iproc_read(io.dev, io.d0);
   1611             if (io.d1 == -1) {
   1612                 io.rc = LUBDE_FAIL;
   1613             }
   1614         }
   1615         break;
   1616     case LUBDE_IPROC_WRITE_REG:
   1617         if (user_bde->iproc_write(io.dev, io.d0, io.d1) == -1) {
   1618             io.rc = LUBDE_FAIL;
   1619         }
   1620         break;
   1621     case LUBDE_ATTACH_INSTANCE:
   1622         io.rc = _instance_attach(io.d0, io.d1);
   1623         break;
   1624     case LUBDE_GET_DEVICE_STATE:
   1625         io.rc = lkbde_dev_state_get(io.dev, &io.d0);
   1626         break;
   1627     case LUBDE_REPROBE:
   1628         io.rc = _device_reprobe();
   1629         break;
   1630     default:
   1631         gprintk("Error: Invalid ioctl (%08x)\n", cmd);
   1632         io.rc = LUBDE_FAIL;
   1633         break;
   1634     }
   1635 
   1636     if (copy_to_user((void *)arg, &io, sizeof(io))) {
   1637         return -EFAULT;
   1638     }
   1639 
   1640     return 0;
   1641 }
   1642 
   1643 /* Workaround for broken Busybox/PPC insmod */
   1644 static char _modname[] = LINUX_USER_BDE_NAME;
   1645 
   1646 static gmodule_t _gmodule = 
   1647 {
   1648     name: LINUX_USER_BDE_NAME, 
   1649     major: LINUX_USER_BDE_MAJOR, 
   1650     init: _init, 
   1651     cleanup: _cleanup, 
   1652     pprint: _pprint, 
   1653     ioctl: _ioctl,
   1654 }; 
   1655 
   1656 gmodule_t*
   1657 gmodule_get(void)
   1658 {
   1659     _gmodule.name = _modname;
   1660     return &_gmodule;
   1661 }