Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
FMC Software Support
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
0
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Projects
FMC Software Support
Commits
0f4decbb
Commit
0f4decbb
authored
4 years ago
by
Federico Vaga
Browse files
Options
Downloads
Patches
Plain Diff
lib: basic implementation
Signed-off-by:
Federico Vaga
<
federico.vaga@cern.ch
>
parent
11706246
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
lib/fmc/core.h
+19
-0
19 additions, 0 deletions
lib/fmc/core.h
lib/libfmc.c
+345
-0
345 additions, 0 deletions
lib/libfmc.c
with
364 additions
and
0 deletions
lib/fmc/core.h
+
19
−
0
View file @
0f4decbb
...
...
@@ -7,6 +7,25 @@
#ifndef _FMC_CORE_H
#define _FMC_CORE_H
#include
<stdbool.h>
const
char
*
fmc_version_get
(
void
);
struct
fmc_tkn
;
#define FMC_ID_INVALID 0xFFFFFFFF
unsigned
int
*
fmc_carrier_id_list_get
(
void
);
void
fmc_carrier_id_list_put
(
unsigned
int
*
id_list
);
unsigned
int
*
fmc_slot_id_list_get
(
struct
fmc_tkn
*
tkn
);
void
fmc_slot_id_list_put
(
unsigned
int
*
id_list
);
struct
fmc_tkn
*
fmc_carrier_open
(
unsigned
int
carrier_id
);
void
fmc_carrier_close
(
struct
fmc_tkn
*
tkn
);
bool
fmc_slot_is_present
(
struct
fmc_tkn
*
tkn
,
unsigned
int
slot_n
);
bool
fmc_slot_is_fru_valid
(
struct
fmc_tkn
*
tkn
,
unsigned
int
slot_n
);
int
fmc_slot_geo_address
(
struct
fmc_tkn
*
tkn
,
unsigned
int
slot_n
,
unsigned
int
*
ga
);
#endif
/* _FMC_CORE_H */
This diff is collapsed.
Click to expand it.
lib/libfmc.c
+
345
−
0
View file @
0f4decbb
...
...
@@ -4,7 +4,18 @@
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include
<stdlib.h>
#include
<stdio.h>
#include
<stdbool.h>
#include
<unistd.h>
#include
<sys/types.h>
#include
<sys/stat.h>
#include
<fcntl.h>
#include
<assert.h>
#include
<glob.h>
#include
<errno.h>
#include
<string.h>
#include
<libgen.h>
#include
<fmc/core.h>
#ifndef GIT_VERSION
...
...
@@ -14,6 +25,29 @@
static
const
char
*
libfmc_version
=
GIT_VERSION
;
const
char
*
libfmc_version_full
=
"libfmc version:"
GIT_VERSION
;
#ifndef BIT
#define BIT(_n) (1 << _n)
#endif
#define FMC_SLOT_PRESENT BIT(0)
#define FMC_SLOT_FRU_VALID BIT(1)
#define MAX_PATH_LEN 128
#define MAX_SYS_LEN 16
struct
fmc_slot
{
unsigned
int
id
;
unsigned
long
flags
;
unsigned
int
ga
;
char
eeprom_type
[
MAX_SYS_LEN
];
};
struct
fmc_carrier
{
unsigned
int
id
;
struct
fmc_slot
**
slot
;
unsigned
int
n_slots
;
};
/**
* Return the FMC library version
* @return return the FMC library version as string
...
...
@@ -22,3 +56,314 @@ const char *fmc_version_get(void)
{
return
libfmc_version
;
}
static
struct
fmc_slot
*
__fmc_slot_get
(
struct
fmc_carrier
*
carrier
,
unsigned
int
slot_n
)
{
int
i
;
for
(
i
=
0
;
i
<
carrier
->
n_slots
;
++
i
)
if
(
carrier
->
slot
[
i
]
->
id
==
slot_n
)
return
carrier
->
slot
[
i
];
return
NULL
;
}
static
bool
fmc_slot_is_flag_set
(
struct
fmc_tkn
*
tkn
,
unsigned
int
slot_n
,
unsigned
int
flag
)
{
struct
fmc_carrier
*
carrier
=
(
struct
fmc_carrier
*
)
tkn
;
struct
fmc_slot
*
slot
=
__fmc_slot_get
(
carrier
,
slot_n
);
if
(
!
slot
)
return
false
;
return
(
slot
->
flags
&
flag
);
}
static
int
__fmc_sys_read_string
(
struct
fmc_carrier
*
carr
,
unsigned
int
slot_n
,
const
char
*
name
,
char
*
str
,
unsigned
int
max_len
)
{
char
path
[
MAX_PATH_LEN
];
int
fd
;
int
ret
;
snprintf
(
path
,
MAX_PATH_LEN
,
"/sys/class/fmc/fmc-carrier-%d/fmc-slot-%d.%d/%s"
,
carr
->
id
,
carr
->
id
,
slot_n
,
name
);
fd
=
open
(
path
,
O_RDONLY
);
if
(
fd
<
0
)
return
-
1
;
ret
=
read
(
fd
,
str
,
max_len
);
close
(
fd
);
return
ret
;
}
static
int
__fmc_sys_read_int
(
struct
fmc_carrier
*
carr
,
unsigned
int
slot_n
,
const
char
*
name
,
unsigned
int
*
val
)
{
char
buf
[
MAX_SYS_LEN
];
int
ret
;
ret
=
__fmc_sys_read_string
(
carr
,
slot_n
,
name
,
buf
,
MAX_SYS_LEN
);
if
(
ret
<
0
)
return
ret
;
ret
=
sscanf
(
buf
,
"%d"
,
val
);
if
(
ret
!=
1
)
return
-
1
;
return
0
;
}
static
bool
__fmc_slot_is_present
(
struct
fmc_carrier
*
carr
,
unsigned
int
slot_n
)
{
int
err
;
unsigned
int
val
;
err
=
__fmc_sys_read_int
(
carr
,
slot_n
,
"present"
,
&
val
);
if
(
err
<
0
)
return
false
;
return
val
;
}
static
bool
__fmc_slot_is_fru_valid
(
struct
fmc_carrier
*
carr
,
unsigned
int
slot_n
)
{
int
err
;
unsigned
int
val
;
err
=
__fmc_sys_read_int
(
carr
,
slot_n
,
"fru_valid"
,
&
val
);
if
(
err
<
0
)
return
false
;
return
val
;
}
static
int
__fmc_slot_ga_get
(
struct
fmc_carrier
*
carr
,
unsigned
int
slot_n
,
unsigned
int
*
ga
)
{
int
err
;
err
=
__fmc_sys_read_int
(
carr
,
slot_n
,
"fmc_ga"
,
ga
);
if
(
err
)
*
ga
=
0xFF
;
return
err
;
}
static
int
fmc_carrier_slots_init
(
struct
fmc_carrier
*
carr
)
{
char
pattern
[
MAX_PATH_LEN
];
glob_t
g
;
int
err
,
i
;
snprintf
(
pattern
,
MAX_PATH_LEN
,
"/sys/class/fmc/fmc-carrier-%d/fmc-slot-%d.*"
,
carr
->
id
,
carr
->
id
);
err
=
glob
(
pattern
,
0
,
NULL
,
&
g
);
if
(
err
==
GLOB_NOMATCH
)
goto
err_glob
;
carr
->
n_slots
=
g
.
gl_pathc
;
carr
->
slot
=
calloc
(
carr
->
n_slots
,
sizeof
(
struct
fmc_slot
*
));
if
(
!
carr
->
slot
)
{
errno
=
ENOMEM
;
goto
err_alloc
;
}
for
(
i
=
0
;
i
<
carr
->
n_slots
;
i
++
)
{
carr
->
slot
[
i
]
=
malloc
(
sizeof
(
*
carr
->
slot
[
i
]));
memset
(
carr
->
slot
[
i
],
0
,
sizeof
(
*
carr
->
slot
[
i
]));
sscanf
(
basename
(
g
.
gl_pathv
[
i
]),
"fmc-slot-%*d.%d"
,
&
carr
->
slot
[
i
]
->
id
);
__fmc_slot_ga_get
(
carr
,
carr
->
slot
[
i
]
->
id
,
&
carr
->
slot
[
i
]
->
ga
);
if
(
__fmc_slot_is_present
(
carr
,
carr
->
slot
[
i
]
->
id
))
carr
->
slot
[
i
]
->
flags
|=
FMC_SLOT_PRESENT
;
if
(
__fmc_slot_is_fru_valid
(
carr
,
carr
->
slot
[
i
]
->
id
))
carr
->
slot
[
i
]
->
flags
|=
FMC_SLOT_FRU_VALID
;
}
globfree
(
&
g
);
return
0
;
err_alloc:
globfree
(
&
g
);
err_glob:
return
-
1
;
}
static
void
fmc_carrier_slots_cleanup
(
struct
fmc_carrier
*
carr
)
{
int
i
;
for
(
i
=
0
;
i
<
carr
->
n_slots
;
i
++
)
free
(
carr
->
slot
[
i
]);
free
(
carr
->
slot
);
}
/**
* Check whether the an FMC mezzanine is present or not
* @param[in] tkn: FMC carrier token
* @param[in] slot_n: FMC slot number (LUN)
*
* @return true if present; false if not present or error
*/
bool
fmc_slot_is_present
(
struct
fmc_tkn
*
tkn
,
unsigned
int
slot_n
)
{
return
fmc_slot_is_flag_set
(
tkn
,
slot_n
,
FMC_SLOT_PRESENT
);
}
/**
* Check whether the an FMC mezzanine is present or not
* @param[in] tkn: FMC carrier token
* @param[in] slot_n: FMC slot number (LUN)
*
* @return true if the FRU is valid; false if the FRU is not valid or error
*/
bool
fmc_slot_is_fru_valid
(
struct
fmc_tkn
*
tkn
,
unsigned
int
slot_n
)
{
return
fmc_slot_is_flag_set
(
tkn
,
slot_n
,
FMC_SLOT_FRU_VALID
);
}
/**
* Get the slot geographical address
* @param[in] tkn: FMC carrier token
* @param[in] slot_n: FMC slot number (LUN)
* @param[out] ga: geographical address
*
* @return on success 0, otherwise -1 and errono is appropriately set
*/
int
fmc_slot_geo_address
(
struct
fmc_tkn
*
tkn
,
unsigned
int
slot_n
,
unsigned
int
*
ga
)
{
struct
fmc_carrier
*
carrier
=
(
struct
fmc_carrier
*
)
tkn
;
struct
fmc_slot
*
slot
=
__fmc_slot_get
(
carrier
,
slot_n
);
if
(
!
slot
)
return
-
1
;
*
ga
=
slot
->
ga
;
return
0
;
}
/**
* Open an FMC carrier
*
* @param[in] carrier_id: carrier identifier
* @return on success a valid pointer, otherwise NULL and errono is
* appropriately set
*/
struct
fmc_tkn
*
fmc_carrier_open
(
unsigned
int
carrier_id
)
{
struct
fmc_carrier
*
carr
;
int
ret
;
carr
=
malloc
(
sizeof
(
*
carr
));
if
(
!
carr
)
return
NULL
;
memset
(
carr
,
0
,
sizeof
(
*
carr
));
carr
->
id
=
carrier_id
;
ret
=
fmc_carrier_slots_init
(
carr
);
if
(
ret
<
0
)
goto
err_slots
;
return
(
struct
fmc_tkn
*
)
carr
;
err_slots:
free
(
carr
);
return
NULL
;
}
/**
* Close a previously opened FMC carrier
*
* @param[in] tkn: FMC carrier token
*/
void
fmc_carrier_close
(
struct
fmc_tkn
*
tkn
)
{
if
(
tkn
)
{
struct
fmc_carrier
*
carr
=
(
struct
fmc_carrier
*
)
tkn
;
fmc_carrier_slots_cleanup
(
carr
);
free
(
carr
);
}
}
/**
* Identifiers list of available carrier
* @return on success a list of identifiers terminated by
* FMC_ID_INVALID
*/
unsigned
int
*
fmc_carrier_id_list_get
(
void
)
{
glob_t
g
;
int
err
,
i
;
unsigned
int
*
id_list
;
err
=
glob
(
"/sys/class/fmc/fmc-carrier-*"
,
0
,
NULL
,
&
g
);
if
(
err
==
GLOB_NOMATCH
)
goto
err_glob
;
id_list
=
calloc
(
g
.
gl_pathc
+
1
,
sizeof
(
unsigned
int
));
if
(
!
id_list
)
goto
err_alloc
;
for
(
i
=
0
;
i
<
g
.
gl_pathc
;
i
++
)
{
int
ret
=
sscanf
(
g
.
gl_pathv
[
i
],
"/sys/class/fmc/fmc-carrier-%d"
,
&
id_list
[
i
]);
if
(
ret
!=
1
)
goto
err_scanf
;
}
id_list
[
i
]
=
FMC_ID_INVALID
;
globfree
(
&
g
);
return
id_list
;
err_scanf:
free
(
id_list
);
err_alloc:
globfree
(
&
g
);
err_glob:
return
NULL
;
}
/**
* Identifiers list of available slots on a given carrier
* @return on success a list of identifiers terminated by
* FMC_ID_INVALID
*/
unsigned
int
*
fmc_slot_id_list_get
(
struct
fmc_tkn
*
tkn
)
{
struct
fmc_carrier
*
carrier
=
(
struct
fmc_carrier
*
)
tkn
;
unsigned
int
*
id_list
;
int
i
;
id_list
=
calloc
(
carrier
->
n_slots
+
1
,
sizeof
(
unsigned
int
));
if
(
!
id_list
)
goto
err_alloc
;
for
(
i
=
0
;
i
<
carrier
->
n_slots
;
++
i
)
id_list
[
i
]
=
carrier
->
slot
[
i
]
->
id
;
id_list
[
i
]
=
FMC_ID_INVALID
;
return
id_list
;
err_alloc:
return
NULL
;
}
static
void
fmc_id_list_put
(
unsigned
int
*
id_list
)
{
free
(
id_list
);
}
void
fmc_carrier_id_list_put
(
unsigned
int
*
id_list
)
{
fmc_id_list_put
(
id_list
);
}
void
fmc_slot_id_list_put
(
unsigned
int
*
id_list
)
{
fmc_id_list_put
(
id_list
);
}
This diff is collapsed.
Click to expand it.
Preview
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment