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

sal.c (18452B)


      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  * File: 	sal.c
      8  * Purpose:	Defines sal routines for user-mode Unix targets.
      9  */
     10 
     11 #include <sys/types.h>
     12 #include <sys/time.h>
     13 #include <string.h>
     14 #include <stdlib.h>
     15 #include <errno.h>
     16 #include <unistd.h>
     17 #include <signal.h>
     18 #include <pthread.h>
     19 #include <assert.h>
     20 
     21 #include <sal/core/time.h>
     22 #include <sal/core/thread.h>
     23 #include <sal/core/sync.h>
     24 #include <sal/core/boot.h>
     25 #include <sal/core/spl.h>
     26 #include <sal/core/alloc.h>
     27 
     28 #include <sal/appl/sal.h>
     29 #include <sal/appl/io.h>
     30 #include <sal/appl/config.h>
     31 #include <shared/error.h>
     32 
     33 #ifdef BROADCOM_DEBUG
     34 /* { */
     35 #ifdef INCLUDE_BCM_SAL_PROFILE
     36 /* { */
     37 #if AGGRESSIVE_ALLOC_DEBUG_TESTING
     38 /* { */
     39 #include <sal/core/alloc.h>
     40 /* } */
     41 #endif
     42 /* } */
     43 #endif
     44 /* } */
     45 #endif /* BROADCOM_DEBUG */
     46 
     47 #if defined (__STRICT_ANSI__)
     48 #define RANDOM  rand
     49 #define SRANDOM srand
     50 #else
     51 #define RANDOM  random
     52 #define SRANDOM srandom
     53 #endif
     54 
     55 #if (defined(__DUNE_GTO_BCM_CPU__) || defined(__DUNE_WRX_BCM_CPU__) || defined(__DUNE_SLK_BCM_CPU__)) && !defined(INCLUDE_CPU_I2C)
     56 #define INCLUDE_CPU_I2C
     57 #endif
     58 
     59 #ifdef INCLUDE_CPU_I2C
     60 #include <fcntl.h>
     61 #include <linux/i2c.h>
     62 #include <linux/i2c-dev.h>
     63 #ifndef I2C_SMBUS_QUICK
     64 #include <linux/i2c.h>
     65 #endif
     66 #include <sys/ioctl.h>      /* ioctl */
     67 
     68 #define SAL_I2C_DEVICE_FILE_NAME_PREFIX "/dev/i2c-" /* i2c device is SAL_I2C_DEVICE_FILE_NAME_PREFIX + device number */
     69 #define SAL_I2C_MAX_NAME_LENGTH 64
     70 #define SAL_I2C_MAX_NOF_SLAVE_DEVS 128 /* Maximum number of slave devices (Addresses) on an I2C bus, numbered from 0 */
     71 #define SAL_I2C_MAX_ADDRESS_SIZE 4 /* Maximum number of bytes of an address in an I2C device (register address) */
     72 
     73 /* flags for sal_i2c_operation() */
     74 #define SAL_I2C_FLAGS_WRITE 1
     75 #define SAL_I2C_FLAGS_WRITE_SPLIT 2 /* Split the address and data writes */
     76 #define SAL_I2C_FLAGS_IGNORE_UNKNOWN_DEV_ERR_ON_WRITE 4
     77 #define SAL_I2C_MAX_NOF_BUSES 8 /* Maximum number of I2C buses supported which are consecutively numbered from 0 */
     78 #endif /* INCLUDE_CPU_I2C */
     79 
     80 
     81 /*
     82  * Function:
     83  *	sal_flash_sync
     84  * Purpose:
     85  *	For compatibility only.
     86  * Parameters:
     87  *	None
     88  * Returns:
     89  *	0 - success
     90  *	-1 - failed
     91  * Notes:
     92  *	Not supported for Unix.
     93  */
     94 
     95 int
     96 sal_flash_sync(void)
     97 {
     98     return(-1);
     99 }
    100 
    101 /*
    102  * Function:
    103  *	sal_flash_init
    104  * Purpose:
    105  *	For compatibility only.
    106  * Parameters:
    107  *	None
    108  * Returns:
    109  *	0 - success
    110  *	-1 - failed
    111  * Notes:
    112  *	Not supported for Unix.
    113  */
    114 
    115 int
    116 sal_flash_init(int format)
    117 {
    118     return(-1);
    119 }
    120 
    121 /*
    122  * Function:
    123  *	sal_flash_boot
    124  * Purpose:
    125  *	For compatibility only.
    126  * Parameters:
    127  *	None
    128  * Returns:
    129  *	0 - success
    130  *	-1 - failed
    131  * Notes:
    132  *	Not supported for Unix.
    133  */
    134 
    135 int
    136 sal_flash_boot(char *f)
    137 {
    138     return(-1);
    139 }
    140 
    141 /*
    142  * Function:
    143  *	sal_appl_init
    144  * Purpose:
    145  *	Initialize the SAL abstraction layer for Unix
    146  * Parameters:
    147  *	None
    148  * Returns:
    149  *	0 - success
    150  *	-1 - failed
    151  */
    152 
    153 int
    154 sal_appl_init(void)
    155 {
    156 #ifndef NO_FILEIO
    157     char		start_cwd[256];
    158 
    159     sal_getcwd(start_cwd, sizeof (start_cwd));
    160     sal_homedir_set(start_cwd);
    161 #endif
    162 
    163     sal_console_init();
    164     sal_config_refresh();
    165 
    166     DISPLAY_MEM ;
    167     return(0);
    168 }
    169 
    170 /*
    171  * Function:
    172  *	sal_reboot
    173  * Purpose:
    174  *	For compatibility only.
    175  * Parameters:
    176  *	None
    177  * Notes:
    178  *	Causes the Unix application to exit.
    179  */
    180 
    181 void
    182 sal_reboot(void)
    183 {
    184     exit(0);
    185 }
    186 
    187 /*
    188  * Function:
    189  *	sal_shell
    190  * Purpose:
    191  *	Fork a standard O/S shell.
    192  * Parameters:
    193  *	None
    194  */
    195 
    196 void
    197 sal_shell(void)
    198 {
    199     char *s = getenv("SHELL");
    200     /*    coverity[tainted_string]    */
    201     system(s ? s : "/bin/sh");
    202 }
    203 
    204 /*
    205  * Function:
    206  *	sal_led
    207  * Purpose:
    208  *	For compatibility only.
    209  * Parameters:
    210  *	v - pattern to show on LED display
    211  * Returns:
    212  *	Previous state of LEDs.
    213  * Notes:
    214  *	Not supported for Unix.
    215  */
    216 
    217 uint32
    218 sal_led(uint32 v)
    219 {
    220     static uint32	led = 0;
    221     uint32		led_prev;
    222 
    223     led_prev = led;
    224     led = v;
    225 
    226     return led_prev;
    227 }
    228 
    229 /*
    230  * Function:
    231  *	sal_led_string
    232  * Purpose:
    233  *	For compatibility only.
    234  * Parameters:
    235  *	s - string to show on LED display
    236  * Notes:
    237  *	Not supported for Unix.
    238  */
    239 
    240 void
    241 sal_led_string(const char *s)
    242 {
    243     COMPILER_REFERENCE(s);
    244 }
    245 
    246 /*
    247  * Function:
    248  *	sal_date_set
    249  * Purpose:
    250  *	For compatibility only.
    251  * Parameters:
    252  *	val - new system time
    253  * Returns:
    254  *	0 - success
    255  *	-1 - failure
    256  * Notes:
    257  *	Not supported for Unix.
    258  */
    259 
    260 int
    261 sal_date_set(sal_time_t *val)
    262 {
    263     sal_printf("Don't know how to set date on this platform (%lu)\n", *val);
    264     return -1;
    265 }
    266 
    267 /*
    268  * Function:
    269  *	sal_date_get
    270  * Purpose:
    271  *	For compatibility only.
    272  * Parameters:
    273  *	None
    274  * Returns:
    275  *	0 - success
    276  *	-1 - failure
    277  */
    278 
    279 int
    280 sal_date_get(sal_time_t *val)
    281 {
    282     time((time_t *) val);
    283     return 0;
    284 }
    285 
    286 #if !(defined(UNIX) && !defined(__STRICT_ANSI__))
    287 /*
    288  * Function:
    289  *	sal_strcasecmp
    290  * Purpose:
    291  *	Compare two strings ignoring the case of the characters.
    292  * Parameters:
    293  *	s1 - first string to compare
    294  *	s2 - second string to compare
    295  * Returns:
    296  *	0 if s1 and s2 are identical.
    297  *	negative integer if s1 < s2.
    298  *	positive integer if s1 > s2.
    299  * Notes
    300  *	See man page of strcasecmp for more info.
    301  */
    302 
    303 int
    304 sal_strcasecmp(const char *s1, const char *s2)
    305 {
    306     unsigned char c1, c2;
    307 
    308     do {
    309         c1 = tolower(*s1++);
    310         c2 = tolower(*s2++);
    311     } while (c1 == c2 && c1 != 0);
    312 
    313     return c1 - c2;
    314 }
    315 
    316 /*
    317  * Function:
    318  *	sal_strncasecmp
    319  * Purpose:
    320  *	Compare two strings ignoring the case of the characters.
    321  * Parameters:
    322  *	s1 - first string to compare
    323  *	s2 - second string to compare
    324  *	n - maximum number of characters to compare
    325  * Returns:
    326  *	0 if s1 and s2 are identical up to n characters.
    327  *	negative integer if s1 < s2 up to n characters.
    328  *	positive integer if s1 > s2 up to n characters.
    329  * Notes
    330  *	See man page of strncasecmp for more info.
    331  */
    332 
    333 int
    334 sal_strncasecmp(const char *s1, const char *s2, size_t n)
    335 {
    336     unsigned char c1, c2;
    337 
    338     if (n == 0) {
    339         return 0;
    340     }
    341     do {
    342         c1 = tolower(*s1++);
    343         c2 = tolower(*s2++);
    344     } while (--n && c1 == c2 && c1 != 0);
    345 
    346     return c1 - c2;
    347 }
    348 
    349 #endif /* !(defined(UNIX) && !defined(__STRICT_ANSI__)) */
    350 /*
    351  * Function:
    352  *  sal_strcasestr
    353  * Purpose:
    354  *  Finds the first occurrence of the substring needle in the string haystack
    355  * Parameters:
    356  *  haystack - string to be searched in
    357  *  needle   - substring to be searched for in haystack
    358  * Returns:
    359  *  These functions return a pointer to the beginning of the substring
    360  *  or NULL if the substring is not found.
    361  * Notes
    362  *  See man page of strncasestr for more info.
    363  */
    364 
    365 char *
    366 sal_strcasestr(const char *haystack, const char *needle)
    367 {
    368     char c, sc;
    369     size_t len;
    370 
    371     if ((c = *needle++) != 0) {
    372         c = tolower((unsigned char)c);
    373         len = strlen(needle);
    374         do {
    375             do {
    376                 if ((sc = *haystack++) == 0)
    377                     return (NULL);
    378             } while ((char)tolower((unsigned char)sc) != c);
    379         } while (sal_strncasecmp(haystack, needle, len) != 0);
    380         haystack--;
    381     }
    382     return ((char *)haystack);
    383 }
    384 
    385 
    386 /* Code for supporting I2C operations on I2C devices whose master is the CPU */
    387 
    388 #ifdef INCLUDE_CPU_I2C
    389 /* File descriptor for each I2C bus the CPU is connected to, a positive value means it is open */
    390 static int i2c_bus_filedesc[SAL_I2C_MAX_NOF_BUSES] = {0};
    391 
    392 /* open a Linux device file for an I2C bus */
    393 static int sal_i2c_init_fd(int* p_fd, uint8 bus_num)
    394 {
    395   char dev_file_name[SAL_I2C_MAX_NAME_LENGTH];
    396 
    397   sal_snprintf(dev_file_name, SAL_I2C_MAX_NAME_LENGTH, SAL_I2C_DEVICE_FILE_NAME_PREFIX"%d", (int)bus_num);
    398   
    399   /* Try to open the given i2c dev num */
    400   if ( ((*p_fd) = open(dev_file_name, O_RDWR)) <= 0)
    401   {
    402       sal_printf("ERROR in %s: Failed to open() I2C device file for bus number %u\n",
    403                  FUNCTION_NAME(), (unsigned)bus_num);
    404       return _SHR_E_FAIL;
    405   }
    406   return _SHR_E_NONE;
    407 }
    408 
    409 /* close a Linux device file for an I2C bus */
    410 static int sal_i2c_deinit_fd(int *fd)
    411 {
    412   /* close the I2C device */
    413   if (*fd > 0) {
    414       if (close(*fd)) {
    415           return _SHR_E_NOT_FOUND;
    416       }
    417       *fd = -1;
    418   }
    419   
    420   return _SHR_E_NONE;
    421 }
    422 
    423 /* Init CPU I2C */
    424 int sal_i2c_init()
    425 {
    426     return _SHR_E_NONE;
    427 }
    428 
    429 /* De-init CPU I2C */
    430 int sal_i2c_deinit()
    431 {
    432     int i, ret = _SHR_E_NONE;
    433     for (i = 0; i < SAL_I2C_MAX_NOF_BUSES; ++i) {
    434         ret |= sal_i2c_deinit_fd(i2c_bus_filedesc + i);
    435     }
    436     return ret ? _SHR_E_NOT_FOUND : _SHR_E_NONE;
    437 }
    438 
    439 
    440 /*
    441  * Perform an I2C access operation on an I2C device connected to the CPU.
    442  * The device file for the I2C bus needs to already be open.
    443  */
    444 static int sal_i2c_operation(
    445   int i2c_bus,    /* The number of the I2C bus to access on */
    446   uint16 i2c_dev, /* the device on the I2C bus (slave device ID/address) to be accessed */
    447   uint8 alen,    /* the length of the address in bytes, should be between 0 and 4. */
    448   uint8 dlen,    /* the length of the data to read. */
    449   uint32 addr,   /* The address in the device to be accessed (register address). Used if alen>0 */
    450   uint8 *data,   /* the buffer for the data to be read. */
    451   uint32 flags)  /* flags affecting function operation specifically SAL_I2C_FLAGS_WRITE indicated this is a write operation */
    452 {
    453     int i;
    454     unsigned bus = i2c_bus;
    455     uint32 value;
    456     struct i2c_rdwr_ioctl_data rw_data;
    457     struct i2c_msg i2c_rw_msg[2];
    458     uint8 addr_n_data[SAL_I2C_MAX_ADDRESS_SIZE + 256]; /* buffer to hold the address and for writes also the write data */
    459 
    460     if (bus >= SAL_I2C_MAX_NOF_BUSES || i2c_dev >= SAL_I2C_MAX_NOF_SLAVE_DEVS || alen > SAL_I2C_MAX_ADDRESS_SIZE) {
    461         sal_printf("I2c bus %u or I2C device 0x%x or address length %d out of range.\n",
    462                    bus, (unsigned)i2c_dev, (unsigned)alen);
    463         return _SHR_E_PARAM;
    464     }
    465 
    466     /* open the given i2c bus device file if it is not open */
    467     if (i2c_bus_filedesc[bus] <= 0) {
    468         if (sal_i2c_init_fd(i2c_bus_filedesc + bus, bus) != _SHR_E_NONE || i2c_bus_filedesc[bus] <= 0) {
    469             sal_printf("Failed to auto-open the device file.\n");
    470             return _SHR_E_FAIL;
    471         }
    472     }
    473 
    474     /* copy the address to addr_n_data as big endian */
    475     value = addr;
    476     for (i = alen ; i > 0 ; ) {
    477         addr_n_data[--i] = value & 0xff;
    478         value >>= 8;
    479     }
    480 
    481     /* init the i2c access struct */
    482     rw_data.msgs = &i2c_rw_msg[0];
    483     i2c_rw_msg[0].addr  = i2c_dev;
    484     i2c_rw_msg[0].flags = 0; /* I2C_M_WR */
    485     i2c_rw_msg[0].buf   = &addr_n_data[0];
    486     if (flags & SAL_I2C_FLAGS_WRITE) {
    487         if (flags & SAL_I2C_FLAGS_WRITE_SPLIT) { /* block write */
    488             rw_data.nmsgs = 2; /* two WRITE operations */
    489             i2c_rw_msg[0].len     = alen;
    490             i2c_rw_msg[1].addr    = i2c_dev;
    491             i2c_rw_msg[1].flags   = I2C_M_NOSTART;
    492             i2c_rw_msg[1].buf     = data;     /* write from input buffer */
    493             i2c_rw_msg[1].len     = dlen;
    494         } else {
    495             rw_data.nmsgs = 1; /* one WRITE operation */
    496             i2c_rw_msg[0].len = alen + dlen;
    497             sal_memcpy(addr_n_data + alen, data, dlen); /* copy write data after the address */
    498         }
    499     } else { /* read */
    500         if (alen) { /* We have an address so we need to first write it and then read */
    501             rw_data.nmsgs = 2;                /* WRITE + READ operations */
    502             i2c_rw_msg[0].len     = alen;
    503             i2c_rw_msg[1].addr    = i2c_dev;
    504             i2c_rw_msg[1].flags   = I2C_M_RD;
    505             i2c_rw_msg[1].buf     = data;     /* read to input buffer */
    506             i2c_rw_msg[1].len     = dlen;
    507         } else { /* No address, only read */
    508             rw_data.nmsgs = 1;                /* one READ operation */
    509             i2c_rw_msg[0].flags   = I2C_M_RD;
    510             i2c_rw_msg[0].buf     = data;     /* read to input buffer */
    511             i2c_rw_msg[0].len     = dlen;
    512         }
    513     }
    514 
    515     /* Perform the I2C messages/operations */
    516     while (ioctl(i2c_bus_filedesc[bus], I2C_RDWR, &rw_data) < 0) {
    517         if (errno == ENXIO &&
    518           (flags & (SAL_I2C_FLAGS_WRITE | SAL_I2C_FLAGS_IGNORE_UNKNOWN_DEV_ERR_ON_WRITE)) ==
    519           (SAL_I2C_FLAGS_WRITE | SAL_I2C_FLAGS_IGNORE_UNKNOWN_DEV_ERR_ON_WRITE)) {
    520             break;
    521         }
    522         /* sal_printf("ioctl I2C_RDWR failed in %s, %d, %s "
    523            "- error reading from bus %u slave device 0x%x, address 0x%x, error = %d\n",
    524            __FILE__, __LINE__, FUNCTION_NAME(), bus, (unsigned)i2c_dev, addr, errno); */
    525         if (errno != EINTR) {
    526             return _SHR_E_FAIL;
    527         }
    528     }
    529 #ifdef CPU_I2C_DUMP_MESSAGES
    530     {
    531         unsigned j, k;
    532         struct i2c_msg *p = rw_data.msgs;
    533         sal_printf("I2C %s ioctl(%d,", flags & SAL_I2C_FLAGS_WRITE ? "Write":"Read", i2c_bus_filedesc[bus]);
    534         for (j = rw_data.nmsgs; j > 0; --j, ++p) {
    535             sal_printf(" [addr=0x%x flags=0x%x len=%u, buf=0x", (unsigned)p->addr, (unsigned)p->flags, (unsigned)p->len);
    536             for (k = 0; k < p->len; ++k ) {
    537                 sal_printf("%.2x", (unsigned)p->buf[k]);
    538             }
    539             sal_printf("]");
    540         }
    541         sal_printf("\n");
    542     }
    543 #endif /* CPU_I2C_DUMP_MESSAGES */
    544 
    545     /* In read operations the output is now in the data buffer */
    546     return _SHR_E_NONE;
    547 }
    548 
    549 #endif /* INCLUDE_CPU_I2C */
    550 
    551 /*
    552  * Perform an I2C operations on an I2C device connected to the CPU's I2C controller.
    553  * The CPU is the I2C master.
    554  */
    555 
    556 /* 
    557  * Function     : sal_i2c_read
    558  * Purpose      : Provide i2c bus read functionality using CPU i2c controller
    559  * Returns      : 0 - success, otherwise - failure
    560  */
    561 int
    562 sal_i2c_read(
    563   int i2c_bus,    /* The number of the I2C bus to access on */
    564   uint16 i2c_dev, /* the device on the I2C bus (slave device ID/address) to be accessed */
    565   uint32 addr,    /* The address in the device to be accessed (register address). Used if alen>0 */
    566   uint8 addr_len, /* the length of the address in bytes, should be between 0 and 4. */
    567   uint8 *data,    /* the buffer for the data to be read. */
    568   uint8 data_len) /* the length of the data to read. */
    569 {
    570 #ifdef INCLUDE_CPU_I2C
    571     return sal_i2c_operation(i2c_bus, i2c_dev, addr_len, data_len, addr, data, 0);
    572 #else  /* INCLUDE_CPU_I2C */
    573     return _SHR_E_UNAVAIL;
    574 #endif /* INCLUDE_CPU_I2C */
    575 }
    576 
    577 /* 
    578  * Function     : sal_i2c_write
    579  * Purpose      : Provide i2c bus write functionality using CPU i2c controller    
    580  * Returns      : 0 - success, otherwise - failure
    581  */
    582 int
    583 sal_i2c_write(
    584   int i2c_bus,    /* The number of the I2C bus to access on */
    585   uint16 i2c_dev, /* the device on the I2C bus (slave device ID/address) to be accessed */
    586   uint32 addr,    /* The address in the device to be accessed (register address). Used if addr_len>0 */
    587   uint8 addr_len, /* the length of the address in bytes, should be between 0 and 4. */
    588   uint8 *data,    /* the buffer of the data to be written. */
    589   uint8 data_len) /* the length of the data to write. */
    590 {
    591 #ifdef INCLUDE_CPU_I2C
    592     return sal_i2c_operation(i2c_bus, i2c_dev, addr_len, data_len, addr, data, SAL_I2C_FLAGS_WRITE);
    593 #else  /* INCLUDE_CPU_I2C */
    594     return _SHR_E_UNAVAIL;
    595 #endif /* INCLUDE_CPU_I2C */
    596 }
    597 
    598 /* 
    599  * Function     : sal_i2c_write_split
    600  * Purpose      : Provide i2c bus write functionality using CPU i2c controller    
    601  *                Uses two Linux messages for the write instead of one.
    602  * Returns      : 0 - success, otherwise - failure
    603  */
    604 int
    605 sal_i2c_write_split(
    606   int i2c_bus,    /* The number of the I2C bus to access on */
    607   uint16 i2c_dev, /* the device on the I2C bus (slave device ID/address) to be accessed */
    608   uint32 addr,    /* The address in the device to be accessed (register address). Used if addr_len>0 */
    609   uint8 addr_len, /* the length of the address in bytes, should be between 0 and 4. */
    610   uint8 *data,    /* the buffer of the data to be written. */
    611   uint8 data_len) /* the length of the data to write. */
    612 {
    613 #ifdef INCLUDE_CPU_I2C
    614     return sal_i2c_operation(i2c_bus, i2c_dev, addr_len, data_len, addr, data,
    615       SAL_I2C_FLAGS_WRITE | SAL_I2C_FLAGS_WRITE_SPLIT);
    616 #else  /* INCLUDE_CPU_I2C */
    617     return _SHR_E_UNAVAIL;
    618 #endif /* INCLUDE_CPU_I2C */
    619 }
    620 
    621 /*
    622  * Function: cpu_i2c_device_present
    623  * Purpose: Probe the I2C bus using i2c_dev, report if a device responds.
    624  *          The I2C bus is released upon return.
    625  *          No further action is taken.
    626  *
    627  * Parameters:
    628  *    i2c_dev - I2C slave address
    629  *
    630  * Return:
    631  *     _SHR_E_NONE - An I2C device responds at the indicated slave address i2c_dev.
    632  *     otherwise  - No I2C response at the indicated saddr, or I/O error.
    633  */
    634 int
    635 sal_i2c_device_present(
    636   int i2c_bus,    /* The number of the I2C bus to access on */
    637   uint16 i2c_dev) /* the device on the I2C bus (slave device ID/address) to be accessed */
    638 {
    639 #ifdef INCLUDE_CPU_I2C
    640     struct i2c_smbus_ioctl_data smbus_data;
    641     unsigned bus = i2c_bus;
    642 
    643     if (bus >= SAL_I2C_MAX_NOF_BUSES || i2c_dev >= SAL_I2C_MAX_NOF_SLAVE_DEVS) {
    644         sal_printf("I2c bus %u or I2C device 0x%x out of range.\n",
    645                    bus, (unsigned)i2c_dev);
    646         return _SHR_E_PARAM;
    647     }
    648 
    649     /* open the given i2c bus device file if it is not open */
    650     if (i2c_bus_filedesc[bus] <= 0) {
    651         if (sal_i2c_init_fd(i2c_bus_filedesc + bus, bus) != _SHR_E_NONE || i2c_bus_filedesc[bus] <= 0) {
    652             sal_printf("Failed to auto-open the device file.\n");
    653             return _SHR_E_FAIL;
    654         }
    655     }
    656 
    657 
    658     if (ioctl(i2c_bus_filedesc[bus], I2C_SLAVE, i2c_dev) < 0) {
    659         /* ERROR HANDLING; you can check errno to see what went wrong */
    660         return _SHR_E_NOT_FOUND;
    661     }
    662 
    663     sal_memset(&smbus_data, 0, sizeof(smbus_data));
    664     smbus_data.read_write = I2C_SMBUS_QUICK;
    665     smbus_data.size = I2C_SMBUS_QUICK;
    666 
    667     if (ioctl(i2c_bus_filedesc[bus], I2C_SMBUS, &smbus_data) < 0) {
    668         /* ERROR HANDLING; you can check errno to see what went wrong */
    669        return _SHR_E_NOT_FOUND;
    670     }
    671     return _SHR_E_NONE;
    672 #else  /* INCLUDE_CPU_I2C */
    673     return _SHR_E_UNAVAIL;
    674 #endif /* INCLUDE_CPU_I2C */
    675 }
    676 
    677 /* 
    678  * Function     : sal_i2c_config_get 
    679  * Purpose      : Retrieve configurable i2c bus properties 
    680  * unit         : I2C controller 
    681  * flags        : SAL_I2C_* flags 
    682  */
    683 int
    684 sal_i2c_config_get(int unit, uint32 *flags)
    685 {
    686     return(-1); /* Not supported */
    687 }
    688 
    689 /* 
    690  * Function     : sal_i2c_config_set 
    691  * Purpose      : Configure i2c bus properties 
    692  * unit         : I2C controller 
    693  * flags        : SAL_I2C_* flags 
    694  */
    695 int
    696 sal_i2c_config_set(int unit, uint32 flags)
    697 {
    698     return(-1); /* Not supported */
    699 }