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


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * Linux User BDE User Library
      8  */
      9 #include <sched.h>
     10 #include <stdio.h>
     11 #include <stdlib.h>
     12 #include <string.h>
     13 #include <assert.h>
     14 #include <sched.h>
     15 
     16 #include <fcntl.h>
     17 #include <unistd.h>
     18 #include <sys/mman.h>
     19 #include <sys/ioctl.h>
     20 #include <endian.h>
     21 
     22 #include <sal/core/sync.h>
     23 #include <sal/core/spl.h>
     24 #include <sal/core/thread.h>
     25 #include <sal/core/time.h>
     26 #include <sal/core/alloc.h>
     27 #include <soc/cmic.h>
     28 #include <soc/devids.h>
     29 #include <soc/drv.h>
     30 #ifdef INCLUDE_CPU_I2C
     31 #include <soc/i2c.h>
     32 #endif
     33 
     34 #ifdef LINUX_PLI_COMBO_BDE
     35 /* Avoid name clash when using two BDEs */
     36 #define intr_int_context linux_intr_int_context
     37 
     38 /* Must match name change in src/sal/core/unix/alloc.c */
     39 extern void * sal_sim_dma_alloc(size_t sz, char *s);
     40 extern void sal_sim_dma_free(void *addr);
     41 /* Get sim_path defined in systems/linux/user/common/socdiag.c */
     42 extern int bcm_sim_path_get(void);
     43 #endif
     44 
     45 #if defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT)
     46 
     47 #ifdef __DUNE_LINUX_BCM_CPU_PCIE__
     48 #include <soc/dpp/SAND/Utils/sand_framework.h>
     49 #else /* !__DUNE_LINUX_BCM_CPU_PCIE__ */
     50 #include <soc/i2c.h>
     51 #if defined(BCM_DFE_SUPPORT)
     52 #include <appl/diag/dfe/utils_fe1600_card.h>
     53 #endif
     54 #if (defined(__DUNE_GTO_BCM_CPU__) || defined(__DUNE_WRX_BCM_CPU__)) && defined(INCLUDE_I2C)
     55 #define DUNE_GTO_I2C
     56 #define GFA_BI_I2C_PCP_DEVICE_ADDR 0x40
     57 #endif
     58 #endif /* __DUNE_LINUX_BCM_CPU_PCIE__ */
     59 
     60 #endif /* defined(BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) */
     61 
     62 #include <mpool.h>
     63 #include <linux-bde.h>
     64 
     65 #include "kernel/linux-user-bde.h"
     66 
     67 #include <linux/version.h>
     68 
     69 #ifdef KEYSTONE
     70 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
     71 #include <linux/types.h>
     72 #include <linux/spi/spidev.h>
     73 
     74 #include <sal/core/libc.h>
     75 #include <sal/appl/config.h>
     76 
     77 #define LINUX_SPIDEV_SUPPORT 1
     78 #else
     79 #define LINUX_SPIDEV_SUPPORT 0
     80 #endif
     81 #else /* !KEYSTONE */
     82 
     83 #define LINUX_SPIDEV_SUPPORT 0
     84 
     85 #endif /* KEYSTONE */
     86 
     87 #if defined(BCM_ESW_SUPPORT) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
     88 #define CMIC_SPI_SUPPORT 1
     89 #endif
     90 #ifndef CMIC_SPI_SUPPORT
     91 #define CMIC_SPI_SUPPORT 0
     92 #endif
     93 
     94 #if CMIC_SPI_SUPPORT 
     95 #include <linux/spi/spidev.h>
     96 
     97 /* 
     98  * The path to the spidev driver device file 
     99  */
    100 #define LINUX_USER_CMIC_SPIDEV_NAME "/dev/spidev0.0"
    101 
    102 /* Data array to record Read/Wirte device through the Linux mdio device driver or not */
    103 static int cmic_spidev_linux[LINUX_BDE_MAX_SWITCH_DEVICES];
    104 
    105 /*
    106  * Actual spi devices in our system
    107  */
    108 static struct {
    109     int unit;
    110     int spidev_fd; /* CPU MDIO device descriptor */
    111 } _sys_cmic_spidevs[LINUX_BDE_MAX_SWITCH_DEVICES];
    112 
    113 static int cmic_spidev_log_on = 0;
    114 
    115 #define CMIC_SPI_NORMAL 0
    116 #define CMIC_SPI_FAST 1
    117 #define CMIC_SPI_READ 0
    118 #define CMIC_SPI_WRITE 1
    119 #define CMIC_SPI_NORMAL_BITS_7_5 0x3
    120 
    121 static unsigned int 
    122 _cmic_spidev_read(int dev, uint32 addr)
    123 {    
    124     int i;
    125     int ret;    
    126     int fd = _sys_cmic_spidevs[dev].spidev_fd;
    127     unsigned int value;
    128     uint8 tx[5];
    129     uint8 rx[4];
    130     struct spi_ioc_transfer tr[2];
    131 
    132     memset(&rx, 0, sizeof(rx));
    133 
    134     tx[0] = (CMIC_SPI_NORMAL_BITS_7_5 << 5) | (CMIC_SPI_NORMAL << 4) | \
    135             ((dev & 0x7) << 1) | CMIC_SPI_READ;
    136     tx[1] = addr & 0x000000ff;
    137     tx[2] = (addr & 0x0000ff00) >> 8;
    138     tx[3] = (addr & 0x00ff0000) >> 16;
    139     tx[4] = (addr & 0xff000000) >> 24;
    140 
    141     memset(tr, 0, sizeof(tr));
    142     tr[0].tx_buf = (unsigned long)tx;
    143     tr[0].len = sizeof(tx);
    144 
    145     tr[1].rx_buf = (unsigned long)rx;
    146     tr[1].len = sizeof(rx);
    147 
    148     ret = ioctl(fd, SPI_IOC_MESSAGE(2), &tr);
    149     if (ret < 1) {
    150         printf("Can't send spi message: read(ret=%d)\n", ret);
    151     }
    152 
    153     value = 0;
    154     for (i = 0; i < sizeof(rx); i++) {
    155         value |= (rx[i] << i*8);
    156     }
    157 
    158     return value;
    159 }
    160 
    161 static int
    162 _cmic_spidev_write(int dev, uint32 addr, uint32 data)
    163 {    
    164     int ret;    
    165     int fd = _sys_cmic_spidevs[dev].spidev_fd;
    166     uint8 tx1[9];
    167     struct spi_ioc_transfer tr[1];
    168 
    169     memset(tx1, 0, sizeof(tx1));
    170 
    171     tx1[0] = (CMIC_SPI_NORMAL_BITS_7_5 << 5) | (CMIC_SPI_NORMAL << 4) | \
    172             ((dev & 0x7) << 1) | CMIC_SPI_WRITE;
    173     tx1[1] = addr & 0x000000ff;
    174     tx1[2] = (addr & 0x0000ff00) >> 8;
    175     tx1[3] = (addr & 0x00ff0000) >> 16;
    176     tx1[4] = (addr & 0xff000000) >> 24;
    177 
    178     tx1[5] = data & 0x000000ff;
    179     tx1[6] = (data & 0x0000ff00) >> 8;
    180     tx1[7] = (data & 0x00ff0000) >> 16;
    181     tx1[8] = (data & 0xff000000) >> 24;
    182     
    183     memset(&tr, 0, sizeof(tr));
    184     tr[0].tx_buf = (unsigned long)tx1;
    185     tr[0].len = sizeof(tx1);
    186 
    187     ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    188     if (ret < 1) {
    189         printf("Can't send spi message: write(ret=%d)\n", ret);
    190     }
    191 
    192     return ret;
    193 }
    194 
    195 /* 
    196  * Function:
    197  *    _sys_cmic_spidev_deinit
    198  * Purpose:
    199  *    close linux spi dev driver device file
    200  * Parameters:
    201  *    dev - device number
    202  * Returns:
    203  *    void
    204  */
    205 static void
    206 linux_cmic_spidev_close(int dev)
    207 {
    208     int fd;
    209 
    210     fd = _sys_cmic_spidevs[dev].spidev_fd;
    211     close(fd);
    212 }
    213 
    214 static int
    215 linux_cmic_spidev_open(int dev)
    216 {
    217     char *spidev_name = LINUX_USER_CMIC_SPIDEV_NAME;
    218     int fd = 0;
    219 
    220 
    221     /* Initialization */
    222     memset(cmic_spidev_linux, 0, sizeof(cmic_spidev_linux));
    223 
    224     fd = open(spidev_name, O_RDWR);
    225     if (fd >= 0) {
    226         _sys_cmic_spidevs[dev].unit = dev;
    227         _sys_cmic_spidevs[dev].spidev_fd = fd;
    228         cmic_spidev_linux[dev] = 1;
    229     }
    230 
    231     cmic_spidev_log_on = 1;
    232 
    233     return 0;
    234 
    235 }
    236 #endif 
    237 
    238 #ifdef IPROC_CMICD
    239 #include <soc/cmic.h>
    240 #define LINUX_MDIODEV_SUPPORT 1
    241 
    242 /* IOCTL commands */
    243 #define MDIO_IOC_MAGIC       'm'
    244 struct mdio_ioc_transfer {
    245     uint8   pa; /* phy address */
    246     uint8   ra; /* register address */
    247     uint16  tx_buf; /* buffer for write */
    248     uint16  rx_buf; /* buffer for read */
    249 };
    250 
    251 #define MDIO_MSGSIZE(N) \
    252     ((((N)*(sizeof (struct mdio_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \
    253         ? ((N)*(sizeof (struct mdio_ioc_transfer))) : 0)
    254 
    255 #define MDIO_IOC_MESSAGE(N) _IOW(MDIO_IOC_MAGIC, 0, char[MDIO_MSGSIZE(N)])
    256 
    257 #define MDIO_IOC_EXTERNAL_R_REG _IOWR(MDIO_IOC_MAGIC, 0, char[MDIO_MSGSIZE(1)])
    258 #define MDIO_IOC_EXTERNAL_W_REG _IOW(MDIO_IOC_MAGIC, 1, char[MDIO_MSGSIZE(1)])
    259 #define MDIO_IOC_LOCAL_R_REG _IOWR(MDIO_IOC_MAGIC, 2, char[MDIO_MSGSIZE(1)])
    260 #define MDIO_IOC_LOCAL_W_REG _IOW(MDIO_IOC_MAGIC, 3, char[MDIO_MSGSIZE(1)])
    261 
    262 #else
    263 #define LINUX_MDIODEV_SUPPORT 0
    264 #endif /* IPROC_CMICD */
    265 
    266 #ifdef SAL_BDE_32BIT_USER_64BIT_KERNEL
    267 
    268 typedef struct sal_kernel64_ptr_s {
    269     uint64    ptr64;
    270 } *sal_kernel64_ptr_t;
    271 
    272 #define SAL_SEM_REDIRECT
    273 
    274 #ifndef PHYS_ADDRS_ARE_64BITS
    275 #define PHYS_ADDRS_ARE_64BITS
    276 #endif
    277 #include <sys/mman.h>
    278 #define MMAP    mmap
    279 typedef uint64 phys_addr_t;
    280 
    281 #else /* SAL_BDE_32BIT_USER_64BIT_KERNEL */
    282 
    283 #ifdef PHYS_ADDRS_ARE_64BITS
    284 #include <sys/mman.h>
    285 #ifdef SAL_BDE_USE_MMAP64
    286 #define MMAP    mmap64
    287 #else
    288 #define MMAP    mmap
    289 #endif
    290 typedef uint64 phys_addr_t;
    291 #else 
    292 #define MMAP    mmap
    293 typedef uint32 phys_addr_t;
    294 #endif  /* PHYS_ADDRS_ARE_64BITS */
    295 
    296 #endif /* SAL_BDE_32BIT_USER_64BIT_KERNEL */
    297 
    298 #define _SWAP32(_x) \
    299     (((_x) << 24) | (((_x) & 0xff00) << 8) | \
    300      (((_x) & 0xff0000) >> 8) | ((_x) >> 24))
    301 
    302 /* 
    303  * The path to the driver device file 
    304  */
    305 #define LUBDE_DEVICE_NAME "/dev/" LINUX_USER_BDE_NAME
    306 
    307 /* 
    308  * The path to the mem device file 
    309  */
    310 #define MEM_DEVICE_NAME "/dev/mem"
    311 #define LKBDE_DEVICE_NAME "/dev/"LINUX_KERNEL_BDE_NAME
    312 
    313 /*
    314  * Device information structure 
    315  */
    316 typedef struct bde_dev_s {
    317     int                 dev_id;         /* HW (probed in kernel BDE) device id*/
    318     uint32              dev_type;       /* Type of underlaying device */
    319     ibde_dev_t          bde_dev;        /* BDE device description */
    320     phys_addr_t         pbase;          /* Physical base address of the device */
    321     uint32             *vbase;          /* Virtual base address of the device */
    322     uint32             *vbase1;         /* Secondary virtual base address #1 */
    323     uint32             *vbase2;         /* Secondary virtual base address #2 */
    324 #ifdef DUNE_GTO_I2C
    325     int                i2c_addr;       /* I2C base address */
    326     CPU_I2C_BUS_LEN    i2c_access_type;
    327 #endif /*DUNE_GTO_I2C*/
    328 #ifdef INCLUDE_CPU_I2C
    329     uint8 i2c_bus;        /* The number of the CPU I2C bus the device is connected to */
    330     uint8 i2c_dev;        /* the device slave address on the I2C bus */
    331     uint8 use_i2c_access; /* Use I2C access for the device instead of PCIe */
    332     uint32 i2c_base;      /* Base address for the device's internal address space */
    333 #endif
    334 } bde_dev_t;
    335 
    336 static bde_dev_t* _devices[LINUX_BDE_MAX_DEVICES];
    337 static int        _ndevices = 0;
    338 static int        _switch_ndevices = 0;
    339 static int        _ether_ndevices = 0;
    340 static int        _cpu_ndevices = 0;
    341 static int        _bde_version = -1;
    342 
    343 /*
    344  * instance information
    345  */
    346 static unsigned int     _inst_dev_mask = 0;
    347 static unsigned int     _inst_dma_size = 0;
    348 
    349 /*
    350  * Global DMA pool.
    351  *
    352  * One DMA memory pool is shared by all devices.
    353  */
    354 static void *_dma_vbase = NULL;
    355 /* cpu physical address for mmap */
    356 static phys_addr_t _cpu_pbase = 0;
    357 /*
    358  * DMA bus address, it is either identical to cpu physical address
    359  * or another address(IOVA) translated by IOMMU.
    360  */
    361 static phys_addr_t _dma_pbase = 0;
    362 static ssize_t _dma_size = 0;
    363 static mpool_handle_t _dma_pool;
    364 
    365 /* 
    366  * Device File Descriptors
    367  */
    368 static int _devfd = -1;
    369 static int _memfd = -1;
    370 static int _kdevfd = -1;
    371 static int _use_kernel_bde_mmap = 0;
    372 
    373 #ifndef BCM_PLX9656_LOCAL_BUS
    374 #ifdef SAL_BDE_CACHE_DMA_MEM
    375 /*
    376  * Optionally use cached memory for DMA to improve performance.
    377  * Should be enabled on cache-coherent platforms only to avoid
    378  * data corruption and other fatal errors.
    379  */
    380 static int _sync_flags = 0;
    381 #else
    382 static int _sync_flags = O_SYNC | O_DSYNC | O_RSYNC;
    383 #endif /* SAL_BDE_CACHE_DMA_MEM */
    384 #endif /* BCM_PLX9656_LOCAL_BUS */
    385 
    386 #if LINUX_SPIDEV_SUPPORT
    387 #endif /* LINUX_SPIDEV_SUPPORT */
    388 
    389 #if LINUX_MDIODEV_SUPPORT
    390 #endif /* LINUX_MDIODEV_SUPPORT */
    391 
    392 #define IPROC_SUBWIN_MAX        8
    393 #define IPROC_DEFAULT_SUBWIN    7
    394 #define IPROC_PAXB_PAGE         0x18012000
    395 #define IPROC_PAXB_IMAP0_ADDR   (IPROC_PAXB_PAGE + 0xc00)
    396 #define BAR0_PAXB_IMAP0_0       0x2c00
    397 
    398 
    399 typedef struct _iproc_subwin_s {
    400     uint32 addr_min;
    401     uint32 addr_max;
    402 } _iproc_subwin_t;
    403 
    404 typedef struct _iproc_map_s {
    405     _iproc_subwin_t subwin[IPROC_SUBWIN_MAX];
    406 } _iproc_map_t;
    407 
    408 static _iproc_map_t iproc_map_default = {
    409     {
    410         { 0x18000000, 0x18000fff }, /* CCA */
    411         { 0x18030000, 0x18030fff }, /* CCB */
    412         { 0x18012000, 0x18012fff }, /* PAXB */
    413         { 0, 0 }
    414     }
    415 };
    416 
    417 static _iproc_map_t iproc_map[LINUX_BDE_MAX_DEVICES];
    418 
    419 sal_mutex_t iproc_map_lock;
    420 
    421 static int
    422 _devio_remap(unsigned int command, lubde_ioctl_t *pdevio)
    423 {
    424     int idx = 0;
    425 
    426     if ((_inst_dev_mask == 0)||(_devices[0] == NULL)) {
    427         return 0;
    428     }
    429 
    430     switch(command) {
    431     case LUBDE_GET_DEVICE_STATE:
    432     case LUBDE_GET_NUM_DEVICES :
    433     case LUBDE_GET_DMA_INFO:
    434     case LUBDE_ATTACH_INSTANCE:
    435     case LUBDE_USLEEP:
    436     case LUBDE_UDELAY:
    437     case LUBDE_SEM_OP:
    438         /* 
    439          * We don't need to do the remap for those devio.dev
    440          * which is not used to identify the device id 
    441          */
    442         return 0;
    443     }
    444 
    445     idx = pdevio->dev;
    446     pdevio->dev = _devices[idx]->dev_id;
    447 
    448     return 0;
    449 }
    450 
    451 /*
    452  * Function: _ioctl
    453  *
    454  * Purpose:
    455  *    Helper function for performing device ioctls
    456  * Parameters:  
    457  *    command - ioctl command code
    458  * Returns:
    459  *    Asserts if ioctl() system call fails. 
    460  *    Returns devio.rc value. 
    461  * Notes:
    462  *    You must program the devio structure with your parameters
    463  *    before calling this function. 
    464  */
    465 static int
    466 _ioctl(unsigned int command, lubde_ioctl_t *pdevio)
    467 {
    468     pdevio->rc = -1;
    469     _devio_remap(command, pdevio);
    470     assert(ioctl(_devfd, command, pdevio) == 0);
    471     return pdevio->rc;
    472 }
    473 
    474 /*
    475  * Function: _mmap
    476  *
    477  * Purpose:
    478  *    Helper function for address mmapping. 
    479  * Parameters:
    480  *    p - physical address start
    481  *    size - size of region
    482  * Returns:
    483  *    Pointer to mapped region, or NULL on failure. 
    484  */
    485 static void *
    486 _mmap(phys_addr_t p, int size) 
    487 {  
    488     void *map;
    489     phys_addr_t page_size, page_mask;
    490     unsigned int offset;
    491     phys_addr_t  paddr;
    492     sal_vaddr_t  vmap;
    493     int dev_fd = (_use_kernel_bde_mmap && /* device to use for mmap */
    494       (p < _cpu_pbase + _dma_size) && (p >= _cpu_pbase)) ?
    495       _kdevfd : _memfd;
    496 
    497     page_size = getpagesize();
    498     page_mask = ~(page_size - 1);
    499 
    500     if (p & ~page_mask) {
    501         /*
    502         * If address (p) not aligned to page_size, we could not get the virtual 
    503         * address. So we make the paddr aligned with the page size.
    504         * Get the _map by using the aligned paddr.
    505         * Add the offset back to return the virtual mapped region of p.
    506         */
    507 
    508         paddr = p & page_mask;
    509         offset = p - paddr;
    510         size += offset;
    511 
    512         map = MMAP(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, dev_fd, paddr);
    513         if ((map == MAP_FAILED) && (dev_fd == _kdevfd)) {
    514             map = MMAP(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, _memfd, paddr);
    515         }
    516         if (map == MAP_FAILED) {
    517             perror("aligned mmap failed: ");
    518             map = NULL;
    519         }
    520         vmap = PTR_TO_UINTPTR(map) + offset;
    521         return (void *)(vmap);
    522     }
    523 #ifdef SAL_BDE_USE_MMAP2
    524     size += (p & ~page_mask);
    525     map = (void *)syscall(4210, 0, size, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, (off_t)((p & page_mask) >> 12));
    526     if ((map == MAP_FAILED) && (dev_fd == _kdevfd)) {
    527         map = (void *)syscall(4210, 0, size, PROT_READ | PROT_WRITE, MAP_SHARED, _memfd, (off_t)((p & page_mask) >> 12));
    528     }
    529     if (map == MAP_FAILED) {
    530         perror("mmap2 failed: ");
    531         map = NULL;
    532     } else {
    533         map = UINTPTR_TO_PTR(PTR_TO_UINTPTR(map) + PTR_TO_UINTPTR(p & ~page_mask));
    534     }
    535 #else
    536     map = MMAP(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, dev_fd, p);
    537     if ((map == MAP_FAILED) && (dev_fd == _kdevfd)) {
    538         map = MMAP(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, _memfd, p);
    539     }
    540     if (map == MAP_FAILED) {
    541         perror("mmap failed: ");
    542         map = NULL;
    543     }
    544 #endif
    545     return map;
    546 }
    547 
    548 /*
    549  * Function: _get_dma_info
    550  *
    551  * Purpose:
    552  *    Retrieve the size and base address of the DMA memory pool
    553  * Parameters:
    554  *    cpu_pbase - (out) cpu physical address of the memory pool for mmap
    555  *    dma_pbase - (out) bus address of the memory pool
    556  *    size  - (out) size of the memory pool
    557  * Returns:
    558  *    0
    559  */
    560 static int
    561 _get_dma_info(phys_addr_t* cpu_pbase, phys_addr_t* dma_pbase, ssize_t* size)
    562 {
    563     lubde_ioctl_t devio;
    564 
    565     /* Initialize the variable */
    566     memset(&devio, 0, sizeof(lubde_ioctl_t));
    567 
    568     devio.dev = _inst_dev_mask;
    569     devio.d2 = 0; /* if we work with older kernel modules, this will make us behave properly */
    570     _ioctl(LUBDE_GET_DMA_INFO, &devio);
    571     *dma_pbase = devio.d0;
    572     *size = devio.d1;
    573     _use_kernel_bde_mmap = devio.d2;
    574 #ifdef PHYS_ADDRS_ARE_64BITS
    575     *cpu_pbase = devio.dx.dw[1];
    576     *cpu_pbase <<= 32;
    577     *cpu_pbase |= devio.dx.dw[0];
    578 #else
    579     *cpu_pbase = devio.dx.dw[0];
    580 #endif
    581     return 0;
    582 }
    583 
    584 static int
    585 _bde_instance_attach(unsigned int dev_mask, unsigned int dma_size)
    586 {
    587     lubde_ioctl_t devio;
    588 
    589     /* Initialize the variable */
    590     memset(&devio, 0, sizeof(lubde_ioctl_t));
    591 
    592     devio.d0 = dev_mask;
    593     devio.d1 = dma_size;
    594 
    595     _ioctl(LUBDE_ATTACH_INSTANCE, &devio);
    596 
    597     return devio.rc;
    598 
    599 }
    600 
    601 /* 
    602  * Function:
    603  *     _get_dev_state
    604  * Purpose:
    605  *    BDE get_dev_state function. Returns device state.
    606  *     (BDE_DEV_STATE_REMOVED/CHANGED)
    607  * Parameters:
    608  *    d - device number
    609  * Returns:
    610  *    state of underlaying device.
    611  */
    612 static int
    613 _get_dev_state(int d)
    614 {
    615     lubde_ioctl_t _devio;
    616 
    617     /* Initialize the variable */
    618     memset(&_devio, 0, sizeof(lubde_ioctl_t));
    619 
    620     assert(d >= 0 || d < _ndevices);
    621 
    622     if (_bde_version > 0) {
    623         /* LUBDE_GET_DEVICE_STATE support after BDE Version 1 */
    624         _devio.dev = d;
    625         if (_ioctl(LUBDE_GET_DEVICE_STATE, &_devio) != 0) {
    626             return -1;
    627         }
    628         return _devio.d0;
    629     } 
    630 
    631     return -1;
    632 }
    633 
    634 /*
    635  * Function: _open
    636  *
    637  * Purpose:
    638  *    Open device driver
    639  *    Initialize device structures
    640  *    Initialize DMA memory
    641  * Parameters:
    642  *    None
    643  * Returns:
    644  *    0 on successfully initialization
    645  *    -1 on error. 
    646  */
    647 static int 
    648 _open(void)
    649 { 
    650     lubde_ioctl_t devio;
    651     phys_addr_t pbase;
    652     int i, j, dev_no;
    653     int linux24;
    654     int procfd;
    655     char procbuf[4];
    656     uint32 rval;
    657     int num_devices;
    658     int _dev_mask = 0;
    659 #ifdef BCM_JERICHO_SUPPORT
    660     int devknetfd = -1;
    661 #endif
    662 
    663 #ifndef NDEBUG    
    664     int _ioctl_LUBDE_GET_NUM_DEVICES;    
    665     int _ioctl_LUBDE_GET_DEVICE_TYPE;    
    666     int _ioctl_LUBDE_GET_DEVICE;
    667 #endif /* !NDEBUG */   
    668 
    669     if (_devfd >= 0) {
    670         /* Already open */
    671         return 0;
    672     }
    673 
    674     /* Check Linux kernel version */
    675     linux24 = 0;
    676     if ((procfd = open("/proc/sys/kernel/osrelease", O_RDONLY)) >= 0) {
    677         if ((read(procfd, procbuf, sizeof(procbuf))) == 4) {
    678             if (strncmp(procbuf, "2.4", 3) == 0) {
    679                 linux24 = 1;
    680             }
    681         }
    682         close(procfd);
    683     }
    684 
    685     /* Open the device driver */
    686     if ((_devfd = open(LUBDE_DEVICE_NAME,
    687                        O_RDWR | O_SYNC | O_DSYNC | O_RSYNC)) < 0) {
    688         /* Try inserting modules from the current directory */
    689         if (linux24) {
    690             system("/sbin/insmod linux-kernel-bde.o");
    691             system("/sbin/insmod linux-user-bde.o");
    692         } else {
    693             system("/sbin/insmod linux-kernel-bde.ko");
    694             system("/sbin/insmod linux-user-bde.ko");
    695         }
    696 
    697         if ((_devfd = open(LUBDE_DEVICE_NAME,
    698                            O_RDWR | O_SYNC | O_DSYNC | O_RSYNC)) < 0) {
    699             perror("open " LUBDE_DEVICE_NAME ": ");
    700             return -1;
    701         }
    702     }
    703 
    704 /*  knet is only supported on jericho and qmx of DUNE */
    705 #ifdef BCM_JERICHO_SUPPORT
    706 #ifdef INCLUDE_KNET
    707     /* check if knet module exists */
    708     if ((devknetfd = open("/dev/linux-bcm-knet", O_RDONLY | O_NONBLOCK  )) < 0) {
    709         /* Try inserting knet module when KNET feature is enabled */
    710         if (linux24) {
    711             /* no linux-bcm-knet.o */
    712         } else {
    713             system("/sbin/insmod linux-bcm-knet.ko");
    714         }
    715     }
    716 #else
    717     /* check if knet module exists */
    718     if ((devknetfd = open("/dev/linux-bcm-knet", O_RDONLY | O_NONBLOCK  )) >= 0) {
    719         close(devknetfd);
    720         /* Try removing knet module when KNET feature is not eanbled*/
    721         if (linux24) {
    722             /* no linux-bcm-knet.o */
    723         } else {
    724             system("/sbin/rmmod linux_bcm_knet");
    725         }   
    726     }
    727 #endif
    728 #endif
    729 
    730     if (_inst_dev_mask) {
    731         if (_bde_instance_attach(_inst_dev_mask, _inst_dma_size) < 0) {
    732             perror("fail to attach instance ");
    733             close(_devfd);
    734             return -1;
    735         }
    736     }
    737 
    738     /* get dma pool information and its handling mode */
    739     _get_dma_info(&_cpu_pbase, &_dma_pbase, &_dma_size);
    740     assert(_dma_size);
    741 
    742 #ifndef BCM_PLX9656_LOCAL_BUS
    743     if ((_memfd = open(MEM_DEVICE_NAME, O_RDWR | _sync_flags)) < 0) {
    744         perror("open " MEM_DEVICE_NAME ": ");
    745         close(_devfd);
    746         return -1;
    747     }
    748 #else /* BCM_PLX9656_LOCAL_BUS */
    749     /*
    750      * On 440GX board with 2.6 kernel, /dev/mem and mmap don't work well
    751      * together.  So we use /dev/linux-user-bde for mapping instead
    752      * (see systems/linux/kernel/modules/shared/gmodule.c) -- hqian 8/15/07
    753      */
    754     _memfd = _devfd;
    755 #endif
    756     if ( _use_kernel_bde_mmap &&
    757       (_kdevfd = open(LKBDE_DEVICE_NAME, O_RDWR | O_SYNC | O_DSYNC | O_RSYNC)) < 0) {
    758         perror("open " LKBDE_DEVICE_NAME ": ");
    759         close(_devfd);
    760 #ifndef BCM_PLX9656_LOCAL_BUS
    761         close(_memfd);
    762 #endif
    763         return -1;
    764     }
    765 
    766     /* Initialize the variable */
    767     memset(&devio, 0, sizeof(lubde_ioctl_t));
    768 
    769     /* Get BDE module version */
    770     if (_bde_version == -1) {
    771 #ifndef NDEBUG
    772         /* "assert" maps to NULL statement with NDEBUG */
    773         const int _ioctl_LUBDE_VERSION = 
    774 #endif /* !NDEBUG */
    775         _ioctl(LUBDE_VERSION, &devio);
    776         assert(_ioctl_LUBDE_VERSION == 0);
    777         _bde_version = devio.d0;
    778     }
    779 
    780     /* Get the availabled devices from the driver */
    781     memset(_devices, 0, sizeof(_devices));  
    782  
    783     /* first, get all available devices */
    784     devio.dev = BDE_ALL_DEVICES;
    785     #ifndef NDEBUG
    786         _ioctl_LUBDE_GET_NUM_DEVICES =
    787     #endif /* !NDEBUG */
    788         _ioctl(LUBDE_GET_NUM_DEVICES, &devio);
    789     assert(_ioctl_LUBDE_GET_NUM_DEVICES == 0);
    790 
    791     num_devices = devio.d0;
    792     if (num_devices == 0) {
    793         printf("linux-user-bde: no devices\n");
    794     }
    795     _dev_mask = _inst_dev_mask;
    796     if(_dev_mask == 0) {
    797         /* Include all devices for non-instance mode */
    798         _dev_mask = ~0;
    799     }
    800     /* Initialize device structures for each device */
    801     for (dev_no = 0; dev_no < num_devices; dev_no++) {
    802         uint32 dev_type;
    803         uint32 dev_state;
    804 
    805         dev_state = _get_dev_state(dev_no);
    806         if (dev_state == BDE_DEV_STATE_REMOVED) {
    807             printf("linux-user-bde: device was removed.\n");
    808             continue;
    809         } else if (dev_state == -1){
    810             printf("linux-user-bde: hot-plug device state not supported "
    811                    "by kernel module.\n");
    812         }
    813 
    814         if ((_dev_mask & (1 << dev_no)) == 0) {
    815             continue;
    816         }
    817         /* i tracks devices belonging to this instance */
    818         i = _ndevices++;
    819 
    820         _devices[i] = (bde_dev_t*)malloc(sizeof(bde_dev_t));
    821         memset(_devices[i], 0, sizeof(bde_dev_t));
    822         iproc_map[i] = iproc_map_default;
    823 
    824         _devices[i]->dev_id = dev_no;
    825         /* Get the type of device */
    826         devio.dev = i;
    827 #ifndef NDEBUG
    828     _ioctl_LUBDE_GET_DEVICE_TYPE=
    829 #endif /* !NDEBUG */
    830     _ioctl(LUBDE_GET_DEVICE_TYPE, &devio);
    831     assert(_ioctl_LUBDE_GET_DEVICE_TYPE == 0);
    832 
    833         dev_type = devio.d0;
    834 
    835         if (dev_type & BDE_SWITCH_DEV_TYPE) {
    836             _switch_ndevices++;
    837         } else if (dev_type & BDE_ETHER_DEV_TYPE){
    838             _ether_ndevices++;
    839         } else if (dev_type & BDE_CPU_DEV_TYPE){
    840             _cpu_ndevices++;
    841         }
    842 
    843         /* Get the detail info of the device */
    844         devio.dev = i;
    845 #ifndef NDEBUG
    846     _ioctl_LUBDE_GET_DEVICE =
    847 #endif /* !NDEBUG */
    848     _ioctl(LUBDE_GET_DEVICE, &devio);
    849     assert(_ioctl_LUBDE_GET_DEVICE == 0);
    850 
    851         _devices[i]->bde_dev.device = devio.d0;
    852         _devices[i]->bde_dev.rev = devio.d1;
    853 
    854         if (BDE_DEV_MEM_MAPPED(dev_type)) {
    855             int size;
    856 
    857             /* Default is 64K memory window */
    858             size = 64 * 1024;
    859             if (dev_type & BDE_128K_REG_SPACE) {
    860                 size = 128 * 1024;
    861 #if defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)
    862             } else if (dev_type & BDE_8MB_REG_SPACE) {
    863                 size = 8 * 1024 * 1024;
    864 #endif
    865             } else if (dev_type & BDE_256K_REG_SPACE) {
    866                 size = 256 * 1024;
    867             } else if (dev_type & BDE_320K_REG_SPACE) {
    868                 size = 320 * 1024;
    869             }
    870 
    871             /* Get physical devices address */
    872 #ifdef PHYS_ADDRS_ARE_64BITS
    873             pbase = devio.d3;
    874             pbase <<= 32;
    875             pbase |= devio.d2;
    876 #else
    877             pbase = devio.d2;
    878 #endif /* PHYS_ADDRS_ARE_64BITS */
    879             _devices[i]->pbase = pbase;
    880             
    881             switch (_devices[i]->bde_dev.device) {
    882             case GEDI_DEVICE_ID:
    883             case ACP_PCI_DEVICE_ID:
    884                 size = 0x10000000;
    885                 dev_type |= BDE_BYTE_SWAP;
    886                 break;
    887             default:
    888                 break;
    889             }
    890             {    
    891             _devices[i]->vbase = _mmap(pbase, size);
    892             _devices[i]->bde_dev.base_address = (sal_vaddr_t)_devices[i]->vbase;
    893             }
    894             /* Check for additional device resources */
    895             devio.dev = i;
    896             devio.d0 = 1; /* Resource number */
    897             if (_ioctl(LUBDE_DEV_RESOURCE, &devio) == 0) {
    898                 /* Get physical devices address */
    899 #ifdef PHYS_ADDRS_ARE_64BITS
    900                 pbase = devio.d3;
    901                 pbase <<= 32;
    902                 pbase |= devio.d2;
    903 #else
    904                 pbase = devio.d2;
    905 #endif /* PHYS_ADDRS_ARE_64BITS */
    906 #ifdef __DUNE_LINUX_BCM_CPU_PCIE__ 
    907             if (dev_type & BDE_256K_REG_SPACE) {
    908                 size = 0x8000;
    909             }
    910 #endif
    911             iproc_map_lock = sal_mutex_create("iproc_map_mutex");
    912             if (iproc_map_lock == NULL) {
    913                 return -1;
    914             }
    915 
    916                 if (pbase) {
    917                     _devices[i]->vbase1 = _mmap(pbase, size);  
    918                     if (!(dev_type & BDE_NO_IPROC)) {
    919                         /* Cache IMAP0 registers from the current PAXB */
    920                         for (j = 0; j < IPROC_SUBWIN_MAX; j++) {
    921                             rval = _devices[i]->vbase1[(BAR0_PAXB_IMAP0_0/sizeof(uint32))+j];
    922                             if (rval & 1) { /* Valid Bit */
    923                                 iproc_map[i].subwin[j].addr_min = rval & ~(0xfff);
    924                                 iproc_map[i].subwin[j].addr_max = rval | 0xfff;
    925                             } else {
    926                                 iproc_map[i].subwin[j].addr_min = 0;
    927                                 iproc_map[i].subwin[j].addr_max = 0;
    928                             }
    929                         }
    930                         if (iproc_map[i].subwin[2].addr_min  & 0x1000) {
    931                             /* PAXB_1 */
    932                             dev_type |= BDE_DEV_BUS_ALT;
    933                         }
    934                     }
    935                 }
    936             }
    937         }
    938         _devices[i]->dev_type = dev_type;
    939 
    940 #ifdef DUNE_GTO_I2C
    941         _devices[i]->dev_type |= BDE_I2C_DEV_TYPE;
    942         _devices[i]->dev_type &= ~BDE_PCI_DEV_TYPE;
    943         switch (_devices[i]->bde_dev.device) {
    944         case GEDI_DEVICE_ID:
    945             _devices[i]->i2c_addr = GFA_BI_I2C_PCP_DEVICE_ADDR;
    946             _devices[i]->i2c_access_type = CPU_I2C_ALEN_LONG_DLEN_LONG;
    947             break;
    948 
    949         case BCM88750_DEVICE_ID:
    950         case BCM88753_DEVICE_ID:
    951         case BCM88754_DEVICE_ID:
    952         case BCM88755_DEVICE_ID:
    953 #ifdef BCM_DFE_SUPPORT
    954         case BCM88752_DEVICE_ID:    
    955             _devices[i]->i2c_addr = FE1600_CARD_I2C_FE1600_DEVICE_ADDR;
    956             _devices[i]->i2c_access_type = CPU_I2C_ALEN_WORD_DLEN_LONG;
    957             break;
    958 #endif /* BCM_DFE_SUPPORT */
    959         case JERICHO_DEVICE_ID:
    960         case BCM88670_DEVICE_ID:
    961         case BCM88671_DEVICE_ID:
    962         case BCM88671M_DEVICE_ID:
    963         case BCM88672_DEVICE_ID:
    964         case BCM88673_DEVICE_ID:
    965         case BCM88674_DEVICE_ID:
    966         case BCM88675M_DEVICE_ID:
    967         case BCM88676_DEVICE_ID:
    968         case BCM88676M_DEVICE_ID:
    969         case BCM88677_DEVICE_ID:
    970         case BCM88678_DEVICE_ID:
    971         case BCM88679_DEVICE_ID:
    972         case QMX_DEVICE_ID:
    973         case BCM88370_DEVICE_ID:
    974         case BCM88371_DEVICE_ID:
    975         case BCM88371M_DEVICE_ID:
    976         case BCM88376_DEVICE_ID:
    977         case BCM88376M_DEVICE_ID:
    978         case BCM88377_DEVICE_ID:
    979         case BCM88378_DEVICE_ID:
    980         case BCM88379_DEVICE_ID:
    981         case BCM88680_DEVICE_ID:
    982         case BCM88681_DEVICE_ID:
    983         case BCM88682_DEVICE_ID:
    984         case BCM88683_DEVICE_ID:
    985         case BCM88684_DEVICE_ID:
    986         case BCM88685_DEVICE_ID:
    987         case BCM88380_DEVICE_ID:
    988         case BCM88381_DEVICE_ID:
    989         case BCM88800_DEVICE_ID:
    990         case BCM88770_DEVICE_ID:
    991         case BCM88773_DEVICE_ID:
    992         case BCM88774_DEVICE_ID:
    993         case BCM88775_DEVICE_ID:
    994         case BCM88776_DEVICE_ID:
    995         case BCM88777_DEVICE_ID:
    996         case QAX_DEVICE_ID:
    997         case BCM88470P_DEVICE_ID:
    998         case BCM88471_DEVICE_ID:
    999         case BCM88473_DEVICE_ID:
   1000         case BCM88474_DEVICE_ID:
   1001         case BCM88474H_DEVICE_ID:
   1002         case BCM88476_DEVICE_ID:
   1003         case BCM88477_DEVICE_ID:
   1004 
   1005         case QUX_DEVICE_ID:
   1006         case BCM88272_DEVICE_ID:
   1007         case BCM88273_DEVICE_ID:
   1008         case BCM88274_DEVICE_ID:
   1009         case BCM88278_DEVICE_ID:
   1010         case BCM88279_DEVICE_ID:
   1011         case FLAIR_DEVICE_ID:
   1012         case BCM88950_DEVICE_ID:
   1013         case BCM88953_DEVICE_ID:
   1014         case BCM88954_DEVICE_ID:
   1015         case BCM88955_DEVICE_ID:
   1016         case BCM88956_DEVICE_ID:
   1017         case BCM88772_DEVICE_ID:
   1018         case BCM88952_DEVICE_ID:
   1019             _devices[i]->i2c_addr = 0x44;
   1020             _devices[i]->i2c_access_type = CPU_I2C_ALEN_LONG_DLEN_LONG;
   1021             break;
   1022         default:
   1023             break;
   1024         }
   1025 
   1026         /*All Jericho 2 devices from 0x8690 to 0x869F*/
   1027         if (SOC_IS_JERICHO_2_TYPE(_devices[i]->bde_dev.device)) {
   1028             _devices[i]->i2c_addr = 0x44;
   1029             _devices[i]->i2c_access_type = CPU_I2C_ALEN_LONG_DLEN_LONG;
   1030         }
   1031 
   1032         /*All Ramon devices from 0x8790 to 0x879F*/
   1033         if ((_devices[i]->bde_dev.device & BCM_DNXF_DEVID_MASK) == BCM88790_DEVICE_ID) {
   1034             _devices[i]->i2c_addr = 0x44;
   1035             _devices[i]->i2c_access_type = CPU_I2C_ALEN_LONG_DLEN_LONG;
   1036         }
   1037 #endif
   1038 #ifdef INCLUDE_CPU_I2C
   1039         /* Configure the device's I2C access information */
   1040         switch (_devices[i]->bde_dev.device & BCM_DNXF_DEVID_MASK) {
   1041           case BCM88690_DEVICE_ID:
   1042           case BCM88790_DEVICE_ID:
   1043             _devices[i]->i2c_bus = cpu_i2c_bus_num_default; /* The number of the CPU I2C bus the device is connected to on Broadcom CPU cards */
   1044             _devices[i]->i2c_dev = 0x44;  /* the device slave address on most Broadcom demo boards */
   1045             _devices[i]->use_i2c_access = 0;
   1046             break;
   1047           default:
   1048             _devices[i]->i2c_bus = -1;
   1049             _devices[i]->i2c_dev = -1;
   1050             _devices[i]->use_i2c_access = 0;
   1051         }
   1052 #endif /* INCLUDE_CPU_I2C */
   1053     }
   1054     /* Initialize DMA memory pool */
   1055     mpool_init();
   1056     assert(_dma_vbase = _mmap(_cpu_pbase, _dma_size));
   1057     printf("DMA pool size: %d\n", (int)_dma_size);
   1058     assert(_dma_pool = mpool_create(_dma_vbase, _dma_size));
   1059 
   1060     /* calibrate */
   1061     sal_udelay(0);
   1062 
   1063     return 0;
   1064 }
   1065 
   1066 /* 
   1067  * Function: _close
   1068  *
   1069  * Purpose:
   1070  *    close the driver
   1071  * Parameters:
   1072  *    None
   1073  * Returns:
   1074  *    0
   1075  */
   1076 static int
   1077 _close(void)
   1078 {       
   1079     if (_memfd >= 0 && _memfd != _devfd) {
   1080         close(_memfd);
   1081     }
   1082     close(_devfd);
   1083     if (_kdevfd >=0) {
   1084         close(_kdevfd);
   1085     }
   1086     _kdevfd = _memfd = _devfd = -1;
   1087     return 0;
   1088 }
   1089 
   1090 /*
   1091  * Function: _enable_interrupts
   1092  *
   1093  * Purpose:
   1094  *    Enable interrupts on all devices in the driver
   1095  * Parameters:
   1096  *    d - 0      the switching devices
   1097  *        others the ether device id of _devices.
   1098  * Returns:
   1099  *    0
   1100  * Notes:
   1101  *    When a real device interrupt occurs, the driver masks all 
   1102  *    interrupts and wakes up the interrupt thread.
   1103  *    It is assumed that the interrupt handler will unmask 
   1104  *    interrupts upon exit.
   1105  */
   1106 static int
   1107 _enable_interrupts(int d)
   1108 {
   1109     lubde_ioctl_t devio;
   1110 #ifndef NDEBUG
   1111     /* "assert" maps to NULL statement with NDEBUG */
   1112     int _ioctl_irrupt_status;
   1113 #endif /* !NDEBUG */
   1114 
   1115     /* Initialize the variable */
   1116     memset(&devio, 0, sizeof(lubde_ioctl_t));
   1117 
   1118     if (_switch_ndevices > 0 || _devices[d]->dev_type & BDE_ETHER_DEV_TYPE) {
   1119         devio.dev = d;
   1120         #ifndef NDEBUG
   1121         _ioctl_irrupt_status =
   1122         #endif
   1123         _ioctl(LUBDE_ENABLE_INTERRUPTS, &devio);
   1124         assert(_ioctl_irrupt_status == 0);
   1125     }
   1126     return 0;
   1127 }
   1128 
   1129 /* 
   1130  * Function: _disable_interrupts
   1131  *
   1132  * Purpose:
   1133  *    Disable interrupts on all devices in the driver
   1134  * Parameters:
   1135  *    d - 0      the switching devices
   1136  *        others the ether device id of _devices.
   1137  * Returns:
   1138  *    0
   1139  */
   1140 static int
   1141 _disable_interrupts(int d)
   1142 {
   1143     lubde_ioctl_t devio;
   1144 #ifndef NDEBUG
   1145     /* "assert" maps to NULL statement with NDEBUG */
   1146     int _ioctl_irrupt_status;
   1147 #endif /* !NDEBUG */
   1148 
   1149     /* Initialize the variable */
   1150     memset(&devio, 0, sizeof(lubde_ioctl_t));
   1151 
   1152     if (_switch_ndevices > 0 || _devices[d]->dev_type & BDE_ETHER_DEV_TYPE) {
   1153         devio.dev = d;
   1154         #ifndef NDEBUG
   1155             _ioctl_irrupt_status =
   1156         #endif
   1157             _ioctl(LUBDE_DISABLE_INTERRUPTS, &devio);
   1158             assert(_ioctl_irrupt_status == 0);
   1159     }
   1160     return 0;
   1161 }
   1162 
   1163 /* 
   1164  * Function: _pci_config_put32
   1165  *
   1166  * Purpose:
   1167  *    Write a PCI configuration register on the device
   1168  * Parameters:
   1169  *    d - device number
   1170  *    offset - register offset
   1171  *    data - register data
   1172  * Returns:
   1173  *    0
   1174  */
   1175 int 
   1176 _pci_config_put32(int d, unsigned int offset, unsigned int data)
   1177 {
   1178     lubde_ioctl_t devio;
   1179 
   1180     /* Initialize the variable */
   1181     memset(&devio, 0, sizeof(lubde_ioctl_t));
   1182 
   1183     devio.dev = d;
   1184     devio.d0 = offset;
   1185     devio.d1 = data;
   1186     _ioctl(LUBDE_PCI_CONFIG_PUT32, &devio);
   1187     return 0;
   1188 }
   1189 
   1190 /* 
   1191  * Function: _pci_config_get32
   1192  *
   1193  * Purpose:
   1194  *    Read a PCI configuration register on the device
   1195  * Parameters:
   1196  *    d - device number
   1197  *    offset - register offset
   1198  * Returns:
   1199  *    register value
   1200  */
   1201 unsigned int 
   1202 _pci_config_get32(int d, unsigned int offset)
   1203 {
   1204     lubde_ioctl_t devio;
   1205 
   1206     /* Initialize the variable */
   1207     memset(&devio, 0, sizeof(lubde_ioctl_t));
   1208 
   1209     devio.dev = d;
   1210     devio.d0 = offset;
   1211     _ioctl(LUBDE_PCI_CONFIG_GET32, &devio);
   1212     return devio.d0;
   1213 }
   1214 
   1215 /*
   1216  * Function: _read
   1217  *
   1218  * Purpose:
   1219  *    Read a register
   1220  * Parameters:
   1221  *    d - device number
   1222  *    addr - register address
   1223  * Returns:
   1224  *    register value
   1225  */
   1226 static unsigned int 
   1227 _read(int d, unsigned int addr)
   1228 {
   1229     lubde_ioctl_t _devio;
   1230     unsigned int rv = 0;
   1231 
   1232     /* Initialize the variable */
   1233     memset(&_devio, 0, sizeof(lubde_ioctl_t));
   1234 
   1235 #if CMIC_SPI_SUPPORT
   1236     if (_devices[d]->dev_type & BDE_SPI_DEV_TYPE) {
   1237         return _cmic_spidev_read(d, addr);
   1238     }
   1239 #endif
   1240 
   1241     if (_devices[d]->dev_type & BDE_DEV_BUS_RD_16BIT) {
   1242         _devio.dev = d;
   1243         _devio.d0 = addr;
   1244         if (_ioctl(LUBDE_READ_REG_16BIT_BUS, &_devio) != 0) {
   1245             printf("linux-user-bde: warning: "
   1246                    "eb_read from kernel failed unit=%d addr=%x",
   1247                    d, addr);
   1248             return -1;
   1249         }
   1250         return _devio.d1;
   1251     }
   1252 
   1253     if (_devices[d]->dev_type & BDE_I2C_DEV_TYPE) {
   1254 #ifdef DUNE_GTO_I2C
   1255         int data = 0;
   1256         assert(_devices[d]->i2c_addr);
   1257         if (cpu_i2c_read(_devices[d]->i2c_addr, addr,
   1258                          _devices[d]->i2c_access_type, &data) != 0) {
   1259             printf("linux-user-bde: warning: "
   1260                    "cpu_i2c_read failed unit=%d addr=0x%x ,"
   1261                    "i2c_addr=0x%x , i2c_access_type=0x%x .\n",
   1262                    d, addr, _devices[d]->i2c_addr , _devices[d]->i2c_access_type);
   1263             return -1;
   1264         }
   1265         return data;
   1266 #endif
   1267     }
   1268 
   1269     assert(_devices[d]->vbase);
   1270     rv = _devices[d]->vbase[addr/sizeof(uint32)];
   1271     if (_devices[d]->dev_type & BDE_BYTE_SWAP) {
   1272         rv = _SWAP32(rv);
   1273     }
   1274 
   1275     return rv;
   1276 }
   1277 
   1278 /*
   1279  * Function: _write
   1280  *
   1281  * Purpose:
   1282  *    Write a register
   1283  * Parameters:
   1284  *    d - device number
   1285  *    addr - register address
   1286  *    data - register data
   1287  * Returns:
   1288  *    0
   1289  */
   1290 static int
   1291 _write(int d, uint32 addr, uint32 data)
   1292 {
   1293     lubde_ioctl_t _devio;
   1294 
   1295     /* Initialize the variable */
   1296     memset(&_devio, 0, sizeof(lubde_ioctl_t));
   1297 
   1298 #if CMIC_SPI_SUPPORT
   1299     if (_devices[d]->dev_type & BDE_SPI_DEV_TYPE) {
   1300         return _cmic_spidev_write(d, addr, data);
   1301     }
   1302 #endif
   1303 
   1304     if (_devices[d]->dev_type & BDE_DEV_BUS_WR_16BIT) {
   1305         _devio.dev = d;
   1306         _devio.d0 = addr;
   1307         _devio.d1 = data;
   1308         if (_ioctl(LUBDE_WRITE_REG_16BIT_BUS, &_devio) != 0) {
   1309             printf("linux-user-bde: warnning: "
   1310                    "eb_write failed unit=%d addr=%x",
   1311                    d, addr);
   1312             return -1;
   1313         }
   1314         return 0;
   1315     }
   1316 
   1317     if (_devices[d]->dev_type & BDE_I2C_DEV_TYPE) {
   1318 #ifdef DUNE_GTO_I2C
   1319         assert(_devices[d]->i2c_addr);
   1320         if (cpu_i2c_write(_devices[d]->i2c_addr, addr,
   1321                          _devices[d]->i2c_access_type, data) != 0) {
   1322             printf("linux-user-bde: warning: "
   1323                    "cpu_i2c_write failed unit=%d addr=0x%x ,"
   1324                    "i2c_addr=0x%x , i2c_access_type=0x%x .\n",
   1325                    d, addr , _devices[d]->i2c_addr , _devices[d]->i2c_access_type);
   1326             return -1;
   1327         }
   1328         return 0;
   1329 #endif
   1330     }
   1331 
   1332     assert(_devices[d]->vbase);
   1333     if (_devices[d]->dev_type & BDE_BYTE_SWAP) {
   1334         data = _SWAP32(data);
   1335     }
   1336     _devices[d]->vbase[addr/sizeof(uint32)] = data;
   1337 
   1338     return 0;
   1339 }
   1340 
   1341 /*
   1342  * Function: _salloc
   1343  *
   1344  * Purpose:
   1345  *    Allocate DMA memory
   1346  * Parameters:
   1347  *    d - device number
   1348  *    size - size of block
   1349  *    name - name of block (debugging, unused)
   1350  * Returns:
   1351  *    0
   1352  */
   1353 static uint32*
   1354 _salloc(int d, int size, const char *name)
   1355 {
   1356     /* All devices use the same dma memory pool */
   1357     uint32 *tmp;
   1358     tmp =  mpool_alloc(_dma_pool, size);
   1359 #if AGGRESSIVE_ALLOC_DEBUG_TESTING
   1360     printf("DMA Alloc: %p. Descriptor: %s.\n", tmp, name);
   1361 #endif
   1362     return tmp;
   1363 }
   1364 
   1365 /* 
   1366  * Function: _sfree
   1367  *
   1368  * Purpose:
   1369  *    Free DMA memory
   1370  * Parameters:
   1371  *    d - device number
   1372  *    ptr - ptr to memory to free
   1373  * Returns:
   1374  *    0
   1375  */
   1376 static void
   1377 _sfree(int d, void *ptr)
   1378 {
   1379 #if AGGRESSIVE_ALLOC_DEBUG_TESTING
   1380      printf("DMA Free: %p.\n", ptr);
   1381 #endif
   1382     /* All devices use the same dma memory pool */
   1383     mpool_free(_dma_pool, ptr);
   1384 }       
   1385 
   1386 
   1387 /*
   1388  * Thread ID of the signal handler/interrupt thread
   1389  */
   1390 static volatile sal_thread_t _intr_thread = NULL;
   1391 
   1392 /*
   1393  * Thread ID of the signal handler/interrupt thread for ethernet devices
   1394  */
   1395 static volatile sal_thread_t _ether_intr_thread = NULL;
   1396 
   1397 /*
   1398  * Function: intr_int_context
   1399  *
   1400  * Purpose:
   1401  *    Used by the linux kernel SAL to implement sal_int_context(). 
   1402  * Parameters:
   1403  *    None
   1404  * Returns:
   1405  *    When the current thread is the interrupt thread. 
   1406  */
   1407 int intr_int_context(void) 
   1408 {
   1409     return ((_intr_thread == sal_thread_self()) ||
   1410             (_ether_intr_thread == sal_thread_self()));
   1411 }
   1412 
   1413 
   1414 /* 
   1415  * Client Interrrupt Management
   1416  */
   1417 
   1418 typedef struct intr_handler_s {
   1419     void *data;
   1420     void (*handler)(void*);
   1421 } intr_handler_t;
   1422 
   1423 /* For switching devices */
   1424 static intr_handler_t _handlers[LINUX_BDE_MAX_SWITCH_DEVICES];
   1425 static int _handler_max = -1;
   1426 static int _intr_thread_running = 0;
   1427 
   1428 /* for ethernet devices */ 
   1429 static intr_handler_t _ether_handler;
   1430 static int _ether_dev_handler = 0; /* device id for ethernet device */
   1431 
   1432 /*
   1433  * Function: _run_intr_handlers
   1434  *
   1435  * Purpose:
   1436  *    Run application level interrupt handlers.
   1437  * Parameters:
   1438  *    None
   1439  * Returns:
   1440  *    Nothing
   1441  */
   1442 static void
   1443 _run_intr_handlers(void)
   1444 {
   1445     int i;
   1446     int spl;
   1447 
   1448     /* 
   1449      * Protect applications threads from interrupt thread.
   1450      */
   1451     spl = sal_splhi();
   1452 
   1453     /*
   1454      * Run all of the client interrupt handlers
   1455      */
   1456     for (i = 0; i <= _handler_max; i++) {
   1457         if (_handlers[i].handler) {
   1458             _handlers[i].handler(_handlers[i].data);
   1459         }
   1460     }
   1461 
   1462     /* 
   1463      * Restore spl
   1464      */
   1465     sal_spl(spl);
   1466 }
   1467 static void
   1468 _run_ether_intr_handlers(void)
   1469 {
   1470     int spl;
   1471 
   1472     /* 
   1473      * Protect applications threads from interrupt thread.
   1474      */
   1475     spl = sal_splhi();
   1476 
   1477     /*
   1478      * Run all of the client interrupt handlers
   1479      */
   1480     
   1481     _ether_handler.handler(_ether_handler.data);
   1482     
   1483 
   1484     /* 
   1485      * Restore spl
   1486      */
   1487     sal_spl(spl);
   1488 }
   1489 
   1490 #ifdef SAL_BDE_THREAD_PRIO_DEFAULT
   1491 #else
   1492 /*
   1493  * Function: _set_thread_priority
   1494  *
   1495  * Purpose:
   1496  *    Raise the current thread's execution priority
   1497  *    from regular to realtime. 
   1498  * Parameters:
   1499  *    prio - The realtime scheduling priority (0 - 99)
   1500  * Returns:
   1501  *    Nothing
   1502  */
   1503 static void
   1504 _set_thread_priority(int prio)
   1505 {
   1506     struct sched_param param;
   1507     param.sched_priority = prio;
   1508     if (sched_setscheduler(0, SCHED_RR, &param)) {       
   1509         perror("\ninterrupt priority set: ");
   1510     }
   1511 }       
   1512 #endif /* SAL_BDE_THREAD_PRIO_DEFAULT */
   1513 
   1514 
   1515 /*
   1516  * Function: _interrupt_thread
   1517  *
   1518  * Purpose:
   1519  *    Provides a thread context for interrupt handling. 
   1520  * Parameters:
   1521  *    context - unused
   1522  * Returns:
   1523  *    Nothing
   1524  * Notes:
   1525  */
   1526 static void
   1527 _interrupt_thread(void *d)
   1528 {
   1529     lubde_ioctl_t devio;
   1530 
   1531     /* Initialize the variable */
   1532     memset(&devio, 0, sizeof(lubde_ioctl_t));
   1533 
   1534     devio.dev = PTR_TO_INT(d);
   1535 
   1536     /* We are the interrupt thread for intr_int_context() */
   1537     _intr_thread = sal_thread_self();
   1538 
   1539 #ifdef SAL_BDE_THREAD_PRIO_DEFAULT
   1540 #else
   1541     /* Increase our priority */
   1542     _set_thread_priority(90);
   1543 #endif /* SAL_BDE_THREAD_PRIO_DEFAULT */
   1544 
   1545     while (_intr_thread_running) {
   1546         devio.dev = PTR_TO_INT(d);
   1547         _ioctl(LUBDE_WAIT_FOR_INTERRUPT, &devio);
   1548         _run_intr_handlers();
   1549     }
   1550 }
   1551 
   1552 /*
   1553  * Function:
   1554  *    _ether_interrupt_thread
   1555  * Purpose:
   1556  *    Provides a thread context for ethernet interrupt handling. 
   1557  *     Interrupts are signaled, it provides the 
   1558  *    unique context needed by the signal handler. 
   1559  * Parameters:
   1560  *    d - the device id in _devices
   1561  * Returns:
   1562  *    Nothing
   1563  * Notes:
   1564  */
   1565 
   1566 static void
   1567 _ether_interrupt_thread(void* d)
   1568 {
   1569     lubde_ioctl_t devio;
   1570 
   1571     /* Initialize the variable */
   1572     memset(&devio, 0, sizeof(lubde_ioctl_t));
   1573 
   1574     devio.dev = PTR_TO_INT(d);
   1575 
   1576     /* We are the interrupt thread for intr_int_context() */
   1577     _ether_intr_thread = sal_thread_self();
   1578     
   1579 #ifdef SAL_BDE_THREAD_PRIO_DEFAULT
   1580 #else
   1581     /* Increase our priority */
   1582     _set_thread_priority(90);
   1583 #endif /* SAL_BDE_THREAD_PRIO_DEFAULT */
   1584 
   1585     for (;;) {
   1586         devio.dev = PTR_TO_INT(d);
   1587         _ioctl(LUBDE_WAIT_FOR_INTERRUPT, &devio);
   1588         _run_ether_intr_handlers();
   1589     }
   1590 }
   1591 
   1592 /*
   1593  * Function:
   1594  *    _interrupt_connect
   1595  * Purpose:
   1596  *    BDE vector for connecting client interrupts to the device. 
   1597  *    Initialized the SW interrupt controller and registers the handler. 
   1598  * Parameters:
   1599  *    d - device number
   1600  *    handler - client interrupt handler
   1601  *    data    - client interrupt handler data
   1602  * Returns:
   1603  *    0
   1604  */
   1605 static int 
   1606 _interrupt_connect(int d, 
   1607                    void (*handler)(void*),
   1608                    void *data)
   1609 {
   1610     if (d < 0 || d >= COUNTOF(_devices)) {
   1611         return -1;
   1612     }
   1613 
   1614     if (_devices[d]->dev_type & BDE_ETHER_DEV_TYPE) {
   1615         _ether_dev_handler = d;
   1616         _ether_handler.handler = handler;
   1617         _ether_handler.data = data;
   1618 
   1619         /* Create the ethernet interrupt thread */
   1620         sal_thread_create("bcmEthINTR",
   1621                           8096, 0,
   1622                           (void (*)(void*))_ether_interrupt_thread,
   1623                           INT_TO_PTR(d));
   1624         /* Enable interrupts on the device */
   1625         _enable_interrupts(d);
   1626 
   1627         return 0;
   1628     }
   1629 
   1630     if (d >= COUNTOF(_handlers)) {
   1631         return -1;
   1632     }
   1633 
   1634     /* Do not process more devices than necessary */
   1635     if (d > _handler_max) {
   1636         _handler_max = d;
   1637     }
   1638 
   1639     _handlers[d].handler = handler;
   1640     _handlers[d].data = data;
   1641     
   1642     /*
   1643      * Start up interrupt processing if this is the first connect
   1644      */
   1645     if (_intr_thread_running == 0) {
   1646         _intr_thread_running = 1;
   1647         sal_thread_create("bcmINTR",
   1648                           8096, 0,
   1649                           (void (*)(void*))_interrupt_thread,
   1650                           INT_TO_PTR(d)); 
   1651     }
   1652 
   1653     /* Enable interrupts on the device */
   1654     _enable_interrupts(d);
   1655 
   1656     return 0;
   1657 }
   1658 
   1659 /*
   1660  * Function: _interrupt_disconnect
   1661  *
   1662  * Purpose:
   1663  *    BDE interrupt disconnect function
   1664  * Parameters:
   1665  *    d - device number
   1666  * Returns:
   1667  *    0
   1668  */
   1669 static int 
   1670 _interrupt_disconnect(int d)
   1671 {
   1672     int spl;
   1673 
   1674     if (d < 0 || d >= COUNTOF(_devices)) {
   1675         return -1;
   1676     }
   1677 
   1678     /* Ethernet devices */
   1679     if (d >= _switch_ndevices && d < _ndevices) {
   1680         _disable_interrupts(d);
   1681         return 0;
   1682     }
   1683 
   1684     if (d >= COUNTOF(_handlers)) {
   1685         return -1;
   1686     }
   1687 
   1688     /* Switch devices */
   1689     if (d >= 0 && d < _switch_ndevices) {
   1690         _disable_interrupts(d);
   1691         spl = sal_splhi();
   1692         _handlers[d].handler = NULL;
   1693         _handlers[d].data = NULL;
   1694         sal_spl(spl);
   1695     }
   1696     return 0;
   1697 }
   1698 
   1699 /*
   1700  * Function: _l2p
   1701  *
   1702  * Purpose:
   1703  *    BDE l2p function. Converts CPU virtual DMA addresses
   1704  *    to Device Physical DMA addresses. 
   1705  * Parameters:
   1706  *    d - device number
   1707  *    laddr - logical address to convert
   1708  * Returns:
   1709  *    Physical address
   1710  */
   1711 static sal_paddr_t
   1712 _l2p(int d, void *laddr)
   1713 {
   1714     /* DMA memory is one contiguous block */
   1715     phys_addr_t pbase = _dma_pbase;
   1716 
   1717     if (!laddr) return 0;
   1718 
   1719     pbase = (phys_addr_t)(PTR_TO_UINTPTR(pbase) + (PTR_TO_UINTPTR(laddr) - PTR_TO_UINTPTR(_dma_vbase)));
   1720 
   1721     return ((sal_paddr_t)pbase);
   1722 }       
   1723 
   1724 /* 
   1725  * Function: _p2l
   1726  *
   1727  * Purpose:
   1728  *    BDE p2l function. Converts Device Physical DMA addresses
   1729  *    to CPU virtual DMA addresses. 
   1730  * Parameters:
   1731  *    d - device number
   1732  *    paddr - physical address to convert
   1733  * Returns:
   1734  *    Virtual address
   1735  */
   1736 static void *
   1737 _p2l(int d, sal_paddr_t paddr)
   1738 {
   1739     /* DMA memory is one contiguous block */
   1740     sal_vaddr_t vbase = PTR_TO_UINTPTR(_dma_vbase);
   1741 
   1742     if (!paddr) return 0;
   1743 
   1744     vbase = vbase + ((phys_addr_t)paddr  - _dma_pbase);
   1745 
   1746     return ((void *)vbase);
   1747 }
   1748 
   1749 static uint32
   1750 _iproc_offset(int d, uint32 addr)
   1751 {
   1752     _iproc_map_t *map;
   1753     _iproc_subwin_t *subwin;
   1754     volatile uint32 *bar0, *pv;
   1755     int idx;
   1756 
   1757     if (d >= LINUX_BDE_MAX_DEVICES) {
   1758         return 0;
   1759     }
   1760 
   1761     map = &iproc_map[d];
   1762     for (idx = 0; idx < IPROC_SUBWIN_MAX; idx++) {
   1763         subwin = &map->subwin[idx];
   1764         if (addr >= subwin->addr_min && addr <= subwin->addr_max) {
   1765             return subwin->addr_min - (idx * 0x1000);
   1766         }
   1767     }
   1768 
   1769     /* Not found. (Re)use the default Subwindow */
   1770     subwin = &map->subwin[IPROC_DEFAULT_SUBWIN];
   1771     if (addr < subwin->addr_min || addr > subwin->addr_max) {
   1772         subwin->addr_min = addr & ~(0xfff);
   1773         subwin->addr_max = addr | 0xfff;
   1774 
   1775         bar0 = (volatile uint32 *)_devices[d]->vbase1;
   1776         pv = &bar0[BAR0_PAXB_IMAP0_0 / sizeof(uint32)];
   1777         pv[IPROC_DEFAULT_SUBWIN] = (subwin->addr_min | 0x1);
   1778 
   1779         /* Read back IMAP register to ensure the write completes before proceeding */
   1780         if (pv[IPROC_DEFAULT_SUBWIN] != (subwin->addr_min | 0x1)) {
   1781             return 0;
   1782         }
   1783     }
   1784     return subwin->addr_min - (IPROC_DEFAULT_SUBWIN * 0x1000);
   1785 }
   1786 
   1787 
   1788 static uint32
   1789 _iproc_ihost_read(int d, uint32 addr)
   1790 {
   1791     lubde_ioctl_t _devio;
   1792 
   1793     /* Initialize the variable */
   1794     memset(&_devio, 0, sizeof(lubde_ioctl_t));
   1795 
   1796     _devio.dev = d;
   1797     _devio.d0 = addr;
   1798     if (_ioctl(LUBDE_IPROC_READ_REG, &_devio) != 0) {
   1799         printf("BDE iproc_read failed at 0x%08x\n", addr);
   1800         return -1;
   1801     }
   1802 
   1803     return _devio.d1;
   1804 }
   1805 
   1806 static int
   1807 _iproc_ihost_write(int d, uint32 addr, uint32 data)
   1808 {
   1809     lubde_ioctl_t _devio;
   1810 
   1811     /* Initialize the variable */
   1812     memset(&_devio, 0, sizeof(lubde_ioctl_t));
   1813 
   1814     _devio.dev = d;
   1815     _devio.d0 = addr;
   1816     _devio.d1 = data;
   1817 
   1818     if (_ioctl(LUBDE_IPROC_WRITE_REG, &_devio) != 0) {
   1819         printf("BDE iproc_write failed at 0x%08x\n", addr);
   1820         return -1;
   1821     }
   1822 
   1823     return 0;
   1824 }
   1825 
   1826 /*
   1827  * Function: _iproc_read
   1828  *
   1829  * Purpose:
   1830  *    Read an iProc register
   1831  * Parameters:
   1832  *    d - device number
   1833  *    addr - register address
   1834  * Returns:
   1835  *    register value
   1836  */
   1837 static unsigned int 
   1838 _iproc_read(int d, unsigned int addr)
   1839 {
   1840     uint32 offset;
   1841     uint32 rval;
   1842 
   1843     if (_devices[d]->dev_type & BDE_AXI_DEV_TYPE) {
   1844         return _iproc_ihost_read(d, addr);
   1845     }
   1846     sal_mutex_take(iproc_map_lock, sal_mutex_FOREVER);
   1847 
   1848     if (!(_devices[d]->dev_type & BDE_NO_IPROC)) {
   1849         if ((offset = _iproc_offset(d, addr)) == 0) {
   1850             sal_mutex_give(iproc_map_lock);
   1851             return -1;
   1852         }
   1853         addr -= offset;
   1854     }
   1855 
   1856     assert(_devices[d]->vbase1);
   1857     rval = _devices[d]->vbase1[addr/sizeof(uint32)];
   1858     sal_mutex_give(iproc_map_lock);
   1859     return rval;
   1860 }
   1861 
   1862 /*
   1863  * Function: _iproc_write
   1864  *
   1865  * Purpose:
   1866  *    Write an iProc register
   1867  * Parameters:
   1868  *    d - device number
   1869  *    addr - register address
   1870  *    data - register data
   1871  * Returns:
   1872  *    0
   1873  */
   1874 static int
   1875 _iproc_write(int d, uint32 addr, uint32 data)
   1876 {
   1877     uint32 offset;
   1878 
   1879     if (_devices[d]->dev_type & BDE_AXI_DEV_TYPE) {
   1880         return _iproc_ihost_write(d, addr, data);
   1881     }
   1882     sal_mutex_take(iproc_map_lock, sal_mutex_FOREVER);
   1883 
   1884     if (!(_devices[d]->dev_type & BDE_NO_IPROC)) {
   1885         if ((offset = _iproc_offset(d, addr)) == 0) {
   1886             sal_mutex_give(iproc_map_lock);
   1887             return -1;
   1888         }
   1889         addr -= offset;
   1890     }
   1891 
   1892     assert(_devices[d]->vbase1);
   1893     _devices[d]->vbase1[addr/sizeof(uint32)] = data;
   1894 
   1895     sal_mutex_give(iproc_map_lock);
   1896 
   1897     return 0;
   1898 }
   1899 
   1900 #ifdef INCLUDE_CPU_I2C
   1901     /*
   1902      * I2C operations on the Device, assuming it is connected by I2C to the CPU.
   1903      */
   1904 
   1905 /* Write to the internal device Address space using I2C */
   1906 static int
   1907 _i2c_device_read(
   1908     int dev,       /* The device ID to access */
   1909     uint32 addr,   /* The address to access in the internal device address space */
   1910     uint32 *value) /* the value to be read. */
   1911 {
   1912     return cpu_i2c_device_read(_devices[dev]->i2c_bus, _devices[dev]->i2c_dev, addr, value);
   1913 }
   1914 
   1915 /* Write to the internal device Address space using I2C */
   1916 static int
   1917 _i2c_device_write(
   1918     int dev,       /* The device ID to access */
   1919     uint32 addr,   /* The address to access in the internal device address space */
   1920     uint32 value)  /* the value to be written. */
   1921 {
   1922     return cpu_i2c_device_write(_devices[dev]->i2c_bus, _devices[dev]->i2c_dev, addr, value);
   1923 }
   1924 #endif /* INCLUDE_CPU_I2C */
   1925 
   1926 #if LINUX_SPIDEV_SUPPORT /* Linux spidev driver for switch register access */
   1927 
   1928 
   1929 #endif /* LINUX_SPIDEV_SUPPORT */
   1930 
   1931 
   1932 #if LINUX_MDIODEV_SUPPORT 
   1933 /* Linux mdio device driver for external PHY access */
   1934 
   1935 #endif /* LINUX_MDIODEV_SUPPORT */
   1936 
   1937 /* 
   1938  * Function:
   1939  *    _spi_read
   1940  * Purpose:
   1941  *    BDE spi_read function. Issue spi read via SMP
   1942  * Parameters:
   1943  *    d - device number
   1944  *    addr - register addr to read
   1945  *    buf - buffer addr to store the reading result
   1946  *    int - number bytes to read
   1947  * Returns:
   1948  *    0 - Success
   1949  *     -1 - Failed
   1950  */
   1951 
   1952 static int
   1953 _spi_read(int d, uint32 addr, uint8 *buf, int len)
   1954 {
   1955     lubde_ioctl_t _devio;
   1956 
   1957     /* Initialize the variable */
   1958     memset(&_devio, 0, sizeof(lubde_ioctl_t));
   1959 
   1960 #if LINUX_SPIDEV_SUPPORT
   1961 #endif /* LINUX_SPIDEV_SUPPORT */
   1962 
   1963 #if LINUX_MDIODEV_SUPPORT
   1964 #endif /* LINUX_MDIODEV_SUPPORT */
   1965 
   1966     _devio.dev = d;
   1967     _devio.d0 = addr;
   1968     _devio.d1 = len;
   1969     memset(_devio.dx.buf, 0, sizeof(_devio.dx.buf));
   1970 
   1971     if (_ioctl(LUBDE_SPI_READ_REG, &_devio) != 0) {
   1972     printf("linux-user-bde: warnning: spi_read failed \
   1973         unit=%d addr=%x, len=%d", d, addr, len);
   1974         return -1;
   1975     }
   1976 
   1977     memcpy(buf, _devio.dx.buf, len);
   1978 
   1979     return 0;
   1980 }
   1981 
   1982 /* 
   1983  * Function:
   1984  *    _spi_write
   1985  * Purpose:
   1986  *    BDE spi_write function. Issue spi read via SMP
   1987  * Parameters:
   1988  *    d - device number
   1989  *    addr - register addr to write
   1990  *    buf - buffer to write to spi
   1991  *    int - number bytes for write
   1992  * Returns:
   1993  *    0 - Success
   1994  *     -1 - Failed
   1995  */
   1996 
   1997 static int
   1998 _spi_write(int d, uint32 addr, uint8 *buf, int len)
   1999 {
   2000     lubde_ioctl_t _devio;
   2001 
   2002     /* Initialize the variable */
   2003     memset(&_devio, 0, sizeof(lubde_ioctl_t));
   2004 
   2005 #if LINUX_SPIDEV_SUPPORT
   2006 #endif /* LINUX_SPIDEV_SUPPORT */
   2007 
   2008 #if LINUX_MDIODEV_SUPPORT
   2009 #endif /* LINUX_MDIODEV_SUPPORT */
   2010 
   2011     _devio.dev = d;
   2012     _devio.d0 = addr;
   2013     _devio.d1 = len;
   2014     memcpy(_devio.dx.buf, buf, len);
   2015 
   2016     if (_ioctl(LUBDE_SPI_WRITE_REG, &_devio) != 0) {
   2017     printf("linux-user-bde: warnning: spi_write failed \
   2018         unit=%d addr=%x, len=%d", d, addr, len);
   2019         return -1;
   2020     }
   2021 
   2022     return 0;
   2023 }
   2024 
   2025 STATIC int
   2026 _xdigit2i(int digit)
   2027 {
   2028     if (digit >= '0' && digit <= '9') return (digit - '0'     );
   2029     if (digit >= 'a' && digit <= 'f') return (digit - 'a' + 10);
   2030     if (digit >= 'A' && digit <= 'F') return (digit - 'A' + 10);
   2031     return 0;
   2032 }
   2033 
   2034 /*
   2035  * Function:
   2036  *    bde_icid_get
   2037  * Purpose:
   2038  *    Read ICID.
   2039  * Parameters:
   2040  *    d - device number
   2041  *    data - buffer to store the reading result
   2042  *    size - buffer size
   2043  * Returns:
   2044  *    0 - Success
   2045  *    -1 - Failed
   2046  */
   2047 int
   2048 bde_icid_get(int d, uint8 *data, int len)
   2049 {
   2050     int fd;
   2051     int i;
   2052     char *fname;
   2053     int rv = 0;
   2054     int length = 0;
   2055     uint8 *buf;
   2056 
   2057     fname = "/proc/device-tree/aliases/icid";
   2058     fd = open(fname, O_RDONLY);
   2059     if (fd >= 0) {
   2060         buf = malloc(len * 2);
   2061         length = len * 2; /* actual read length */
   2062         if (length == read(fd, buf, length)) {
   2063             for (i = 0; i < len; i++) {
   2064                 *(data + i) = (_xdigit2i(*(buf + (2 * i))) << 4) | \
   2065                                _xdigit2i(*(buf + (2 * i + 1)));
   2066             }
   2067         } else {
   2068             /* data count in the file is not correct */
   2069             rv = -1;
   2070         }
   2071         free(buf);
   2072         close(fd);
   2073     } else {
   2074         rv = -1;
   2075     }
   2076     return rv;
   2077 }
   2078 
   2079 #ifdef BCM_SAND_SUPPORT
   2080 int
   2081 _cpu_write(int d, uint32 addr, uint32 *buf)
   2082 {
   2083     lubde_ioctl_t _devio;
   2084 
   2085     /* Initialize the variable */
   2086     memset(&_devio, 0, sizeof(lubde_ioctl_t));
   2087 
   2088     _devio.dev = d;
   2089     _devio.d0 = addr;
   2090     _devio.d1 = sizeof(uint32);
   2091     memcpy(_devio.dx.buf, buf, sizeof(uint32));
   2092 
   2093     if (_ioctl(LUBDE_CPU_WRITE_REG, &_devio) != 0) {
   2094         printf("linux-user-bde: warnning: _cpu_write failed unit=%d addr=0x%x, buf=%p, *buf=0x%x", d, addr, (void*)buf, *buf);
   2095         return -1;
   2096     }
   2097 
   2098     return 0;
   2099 }
   2100 
   2101 int
   2102 _cpu_read(int d, uint32 addr, uint32 *buf)
   2103 {
   2104     lubde_ioctl_t _devio;
   2105 
   2106     /* Initialize the variable */
   2107     memset(&_devio, 0, sizeof(lubde_ioctl_t));
   2108 
   2109     _devio.dev = d;
   2110     _devio.d0 = addr;
   2111     _devio.d1 = sizeof(uint32);
   2112     memset(_devio.dx.buf, 0, sizeof(_devio.dx.buf));
   2113 
   2114     if (_ioctl(LUBDE_CPU_READ_REG, &_devio) != 0) {
   2115         printf("linux-user-bde: warnning: _cpu_read failed unit=%d addr=%x", d, addr);
   2116         return -1;
   2117     }
   2118 
   2119     memcpy(buf, _devio.dx.buf, sizeof(uint32));
   2120 
   2121     return 0;
   2122 }
   2123 
   2124 int
   2125 _cpu_pci_register(int d)
   2126 {
   2127     lubde_ioctl_t _devio;
   2128 
   2129     /* Initialize the variable */
   2130     memset(&_devio, 0, sizeof(lubde_ioctl_t));
   2131 
   2132     _devio.dev = d;
   2133 
   2134     if (_ioctl(LUBDE_CPU_PCI_REGISTER, &_devio) != 0) {
   2135         printf("linux-user-bde: warnning: _cpu_pci_register failed unit=%d\n", d);
   2136         return -1;
   2137     }
   2138 
   2139     return 0;
   2140 }
   2141 
   2142 #endif
   2143 
   2144 /* 
   2145  * Function:
   2146  *    _num_devices
   2147  * Purpose:
   2148  *    BDE num_devices function. Returns the number of devices. 
   2149  * Parameters:
   2150  *    None
   2151  * Returns:
   2152  *    number of devices in this bde
   2153  */
   2154 static int
   2155 _num_devices(int type)
   2156 {
   2157     switch (type) {
   2158     case BDE_ALL_DEVICES:
   2159         return _ndevices;
   2160     case BDE_SWITCH_DEVICES:
   2161         return _switch_ndevices;
   2162     case BDE_ETHER_DEVICES:
   2163         return _ether_ndevices;
   2164     case BDE_CPU_DEVICES:
   2165         return _cpu_ndevices;
   2166     }
   2167     return 0;
   2168 }
   2169 
   2170 /* 
   2171  * Function: _get_dev
   2172  *
   2173  * Purpose:
   2174  *    BDE get_dev function. Returns device information structure. 
   2175  * Parameters:
   2176  *    d - device number
   2177  * Returns:
   2178  *    const pointer to BDE device information structure.
   2179  */
   2180 static const ibde_dev_t*
   2181 _get_dev(int d)
   2182 {
   2183     assert(d >= 0 || d < _ndevices);
   2184     return &_devices[d]->bde_dev;
   2185 }
   2186 
   2187 /* 
   2188  * Function:
   2189  *     _get_dev_type
   2190  * Purpose:
   2191  *    BDE get_dev_type function. Returns device type of BUS(PCI,SPI)/
   2192  *    FUNCTIONALITY(SWITCH/ETHERNET). 
   2193  * Parameters:
   2194  *    d - device number
   2195  * Returns:
   2196  *    unsigned dword ORed with capablities of underlaying device.
   2197  */
   2198 static uint32
   2199 _get_dev_type(int d)
   2200 {
   2201     assert(d >= 0 || d < _ndevices);
   2202     return _devices[d]->dev_type;
   2203 }
   2204 
   2205 /* 
   2206  * Function:
   2207  *    _name
   2208  * Purpose:
   2209  *    BDE name function. Returns the name of the BDE. 
   2210  * Parameters:
   2211  *    None
   2212  * Returns:
   2213  *    Name of this BDE
   2214  */
   2215 static const char*
   2216 _name(void)
   2217 {
   2218     return LINUX_USER_BDE_NAME;
   2219 }
   2220 
   2221 
   2222 /* 
   2223  * Function: _bus_features
   2224  *
   2225  * Purpose:
   2226  *    BDE bus features function. Returns the endian features of the system bus. 
   2227  * Parameters:
   2228  *    be_pio - (out) returns the big endian pio bit. 
   2229  *    be_packet - (out) returns the big endian packet bit. 
   2230  *    be_other - (out) returns the big endian other bit. 
   2231  * Returns:
   2232  *    nothing
   2233  * Notes:
   2234  *    This just uses the values passed in by the BDE creator. 
   2235  *    See linux_bde_create(). 
   2236  */ 
   2237 static linux_bde_bus_t _bus;
   2238 
   2239 static void
   2240 _bus_features(int unit, int *be_pio, int *be_packet, int *be_other)
   2241 {
   2242     /*
   2243      * XGS BCM 56xxx/53xxx devices get the endianness from compile flags
   2244      * whereas SBX devices (BCM88020 and QE-2000) get it by querying
   2245      * the kernel BDE (ioctl)
   2246      */
   2247     if ((_devices[unit]->bde_dev.device & 0xFF00) != 0x5600 &&
   2248         (_devices[unit]->bde_dev.device & 0xF000) != 0xc000 &&
   2249         (_devices[unit]->bde_dev.device & 0xF000) != 0xb000 &&
   2250         (_devices[unit]->bde_dev.device & 0xF000) != 0x8000 &&
   2251         (_devices[unit]->bde_dev.device & 0xFFFF) != 0x0732 &&
   2252         (_devices[unit]->bde_dev.device & 0xFFF0) != 0x0230 &&
   2253         (_devices[unit]->bde_dev.device & 0xFFF0) != 0x0030 &&
   2254         (_devices[unit]->bde_dev.device & 0xFFF0) != 0xa440) {
   2255         lubde_ioctl_t devio;
   2256 
   2257         /* Initialize the variable */
   2258         memset(&devio, 0, sizeof(lubde_ioctl_t));
   2259 
   2260         devio.dev = unit;
   2261         _ioctl(LUBDE_GET_BUS_FEATURES, &devio);
   2262         *be_pio = devio.d0;
   2263     *be_packet = devio.d1;
   2264     *be_other = devio.d2;
   2265     } else {
   2266         *be_pio = _bus.be_pio;
   2267         *be_packet = _bus.be_packet;
   2268         *be_other = _bus.be_other;
   2269     }
   2270 }
   2271 
   2272 /* 
   2273 * Our BDE interface structure
   2274 */
   2275 static ibde_t _ibde = {
   2276     _name, 
   2277     _num_devices, 
   2278     _get_dev, 
   2279     _get_dev_type, 
   2280     _pci_config_get32, 
   2281     _pci_config_put32,
   2282     _bus_features,
   2283     _read, 
   2284     _write, 
   2285     _salloc, 
   2286     _sfree, 
   2287     NULL, 
   2288     NULL, 
   2289     _interrupt_connect, 
   2290     _interrupt_disconnect, 
   2291     _l2p, 
   2292     _p2l, 
   2293     _spi_read,
   2294     _spi_write,
   2295     _iproc_read,
   2296     _iproc_write,
   2297     NULL,
   2298     NULL,
   2299     NULL,
   2300     NULL,
   2301 #ifdef INCLUDE_CPU_I2C
   2302     _i2c_device_read,
   2303     _i2c_device_write,
   2304 #else
   2305     NULL,
   2306     NULL,
   2307 #endif /* INCLUDE_CPU_I2C */
   2308 };
   2309 
   2310 #ifdef BCM_INSTANCE_SUPPORT
   2311 int
   2312 linux_bde_instance_attach(unsigned int dev_mask,unsigned int dma_size)
   2313 {
   2314     _inst_dev_mask = dev_mask;
   2315     _inst_dma_size = dma_size;
   2316     return 0;
   2317 }
   2318 #endif
   2319 
   2320 /* 
   2321  * Function: linux_bde_create
   2322  *
   2323  * Purpose:
   2324  *    Creator function for this BDE interface. 
   2325  * Parameters:
   2326  *    bus - pointer to the bus features structure you want this 
   2327  *          bde to export. Depends on the system. 
   2328  *    ibde - pointer to a location to recieve the bde interface pointer. 
   2329  * Returns:
   2330  *    0 on success
   2331  *    -1 on failure. 
   2332  * Notes:
   2333  *    This is the main BDE create function for this interface. 
   2334  *    Used by the external system initialization code.
   2335  */
   2336 int 
   2337 linux_bde_create(linux_bde_bus_t* bus, ibde_t** ibde)
   2338 {
   2339     static int _init = 0;
   2340     
   2341     if (!_init) {
   2342         if (_open() == -1) {       
   2343             *ibde = NULL;
   2344             return -1;
   2345         }       
   2346         _init = 1;
   2347     }
   2348     memset(&_bus, 0, sizeof(_bus));
   2349     if (bus) {
   2350         _bus = *bus;
   2351     }
   2352     *ibde = &_ibde;
   2353 
   2354 #if LINUX_SPIDEV_SUPPORT
   2355 #endif /* LINUX_SPIDEV_SUPPORT */
   2356 
   2357 #if LINUX_MDIODEV_SUPPORT
   2358 #endif /* LINUX_MDIODEV_SUPPORT */
   2359 
   2360 #if CMIC_SPI_SUPPORT 
   2361     linux_cmic_spidev_open(0);
   2362 #endif	
   2363     return 0;
   2364 }
   2365     
   2366 /*
   2367  * Function: linux_bde_destroy
   2368  *
   2369  * Purpose:
   2370  *    destroy this bde
   2371  * Parameters:
   2372  *    BDE interface pointer
   2373  * Returns:
   2374  *    0 on success, < 0 on error. 
   2375  */
   2376 int
   2377 linux_bde_destroy(ibde_t* ibde)
   2378 {
   2379 #if LINUX_SPIDEV_SUPPORT
   2380 #endif /* LINUX_SPIDEV_SUPPORT */
   2381 
   2382 #if LINUX_MDIODEV_SUPPORT
   2383 #endif /* LINUX_MDIODEV_SUPPORT */
   2384 
   2385 #if CMIC_SPI_SUPPORT 
   2386     linux_cmic_spidev_close(0);
   2387 #endif
   2388     return _close();
   2389 }
   2390 
   2391 /*
   2392  * Function: bde_irq_mask_set
   2393  *
   2394  * Purpose:
   2395  *    Set interrupt mask from user space interrupt handler
   2396  * Parameters:
   2397  *    unit - unit number
   2398  *    addr - PCI address of interrupt mask register
   2399  *    mask - interrupt mask
   2400  * Returns:
   2401  *    0 on success, < 0 on error. 
   2402  */
   2403 int
   2404 bde_irq_mask_set(int unit, uint32 addr, uint32 mask)
   2405 {
   2406     lubde_ioctl_t devio;
   2407 
   2408     /* Initialize the variable */
   2409     memset(&devio, 0, sizeof(lubde_ioctl_t));
   2410 
   2411     devio.dev = unit;
   2412     devio.d0 = addr;
   2413     devio.d1 = mask;
   2414     _ioctl(LUBDE_WRITE_IRQ_MASK, &devio);
   2415     return devio.rc;
   2416 }
   2417 /*
   2418  * Function: bde_hw_unit_get
   2419  *
   2420  * Purpose:
   2421  *  Get the hw or user unit map
   2422  * Parameter:
   2423  *  unit (IN)   : inverse == 0, unit = user unit
   2424  *                inverse != 0, unit = hw unit
   2425  *  inverse (IN): specify to get hw or user unip map
   2426  * Returns:
   2427  *  hw unit (probed in kernel BDE) : when inverse == 0
   2428  *  user unit : when invers != 0
   2429  */
   2430 int
   2431 bde_hw_unit_get(int unit, int inverse)
   2432 {
   2433     int u = 0;
   2434     if (inverse) {
   2435         for (u = 0; u < _ndevices; u ++) {
   2436             if (_devices[u]->dev_id == unit) {
   2437                 return u;
   2438             }
   2439         }
   2440     } else {
   2441         if ((unit >= 0) && (unit < _ndevices)) {
   2442             u = _devices[unit]->dev_id;
   2443         } else {
   2444             u = _devices[0]->dev_id;
   2445         }
   2446     }
   2447     return u;
   2448 }
   2449 
   2450 #ifdef LINUX_SAL_DMA_ALLOC_OVERRIDE
   2451 
   2452 /*
   2453  * Function: sal_dma_alloc
   2454  *
   2455  * Notes:
   2456  *    See src/sal/core/unix/alloc.c for details.
   2457  */
   2458 void *
   2459 sal_dma_alloc(unsigned int sz, char *name)
   2460 {
   2461 #ifdef LINUX_PLI_COMBO_BDE
   2462     if (bcm_sim_path_get()) {
   2463         return sal_sim_dma_alloc(sz, name);
   2464     }
   2465 #endif
   2466     return _ibde.salloc(0, sz, name);
   2467 }
   2468 
   2469 /*
   2470  * Function: sal_dma_free
   2471  *
   2472  * Notes:
   2473  *    See src/sal/core/unix/alloc.c for details.
   2474  */
   2475 void
   2476 sal_dma_free(void *ptr)
   2477 {
   2478 #ifdef LINUX_PLI_COMBO_BDE
   2479     if (bcm_sim_path_get()) {
   2480         sal_sim_dma_free(ptr);
   2481         return;
   2482     }
   2483 #endif
   2484     _ibde.sfree(0, ptr);
   2485 }
   2486 
   2487 #endif /* LINUX_SAL_DMA_ALLOC_OVERRIDE */
   2488 
   2489 int
   2490 _dma_get_usage(void)
   2491 {
   2492     return mpool_usage(_dma_pool);
   2493 }
   2494