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 (46765B)


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