Commit f819a1e9 authored by Alessandro Rubini's avatar Alessandro Rubini

lib: new directory; only init and cleanup by now

parent ebd5848f
......@@ -22,3 +22,4 @@ all: modules
modules_install clean modules:
$(MAKE) -C $(LINUX) M=$(shell /bin/pwd) $@
$(MAKE) -C tools M=$(shell /bin/pwd) $@
$(MAKE) -C lib $@
fdelay-init.o: fdelay-init.c /usr/include/stdio.h /usr/include/features.h \
/usr/include/bits/predefs.h /usr/include/sys/cdefs.h \
/usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
/usr/include/gnu/stubs-32.h \
/usr/lib/gcc/i486-linux-gnu/4.4.5/include/stddef.h \
/usr/include/bits/types.h /usr/include/bits/typesizes.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/i486-linux-gnu/4.4.5/include/stdarg.h \
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
/usr/include/bits/stdio.h /usr/include/stdint.h \
/usr/include/bits/wchar.h /usr/include/stdlib.h /usr/include/sys/types.h \
/usr/include/time.h /usr/include/endian.h /usr/include/bits/endian.h \
/usr/include/bits/byteswap.h /usr/include/sys/select.h \
/usr/include/bits/select.h /usr/include/bits/sigset.h \
/usr/include/bits/time.h /usr/include/sys/sysmacros.h \
/usr/include/bits/pthreadtypes.h /usr/include/alloca.h \
/usr/include/unistd.h /usr/include/bits/posix_opt.h \
/usr/include/bits/confname.h /usr/include/getopt.h /usr/include/glob.h \
/usr/include/string.h /usr/include/xlocale.h /usr/include/bits/string.h \
/usr/include/bits/string2.h /usr/include/errno.h \
/usr/include/bits/errno.h /usr/include/linux/errno.h \
/usr/include/asm/errno.h /usr/include/asm-generic/errno.h \
/usr/include/asm-generic/errno-base.h /usr/include/assert.h \
/usr/include/fcntl.h /usr/include/bits/fcntl.h /usr/include/sys/stat.h \
/usr/include/bits/stat.h /data/morgana/tmp/zio/include/linux/zio.h \
/data/morgana/tmp/zio/include/linux/zio-user.h ../fine-delay.h fdelay.h
*.a
fdelay-list
# This is not a kbuild Makefile. It is a plain Makefile so it can be copied
LIB = libfdelay.a
LOBJ := fdelay-init.o
CFLAGS = -Wall -ggdb -O2 -I.. -I$(ZIO)/include
LDFLAGS = -L. -lfdelay
DEMOSRC = fdelay-list.c
DEMOS := $(DEMOSRC:.c=)
modules all: lib demos
lib: $(LIB)
demos: $(DEMOS)
%: %.c
$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
$(LIB): $(LOBJ)
ar r $@ $^
clean:
rm -f $(LIB) .depend *.o *~
.depend: Makefile $(wildcard *.c *.h ../*.h)
$(CC) $(CFLAGS) -M $(LOBJ:.o=.c) -o $@
-include .depend
/*
* Initializing and cleaning up the fdelay library
*
* Copyright (C) 2012 CERN (www.cern.ch)
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2 as published by the Free Software Foundation or, at your
* option, any later version.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <glob.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/zio.h>
#include <linux/zio-user.h>
#include <fine-delay.h>
#define FDELAY_INTERNAL
#include "fdelay.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
static struct __fdelay_board *fd_boards;
static int fd_nboards;
/* Init the library: return the number of boards found */
int fdelay_init(void)
{
glob_t glob_dev, glob_sys;
struct __fdelay_board *b;
int i, j;
/* Look for boards in /dev: old and new pathnames: only one matches */
glob("/dev/zio-fd-*-0-0-ctrl", 0, NULL, &glob_dev);
glob("/dev/zio/zio-fd-*-0-0-ctrl", GLOB_APPEND, NULL, &glob_dev);
/* And look in /sys as well */
glob("/sys/bus/zio/devices/zio-fd-*",0 , NULL, &glob_sys);
assert(glob_dev.gl_pathc == glob_sys.gl_pathc);
/* Allocate as needed */
fd_nboards = glob_dev.gl_pathc;
if (!fd_nboards) {
fd_boards = NULL;
return 0;
}
fd_boards = calloc(glob_dev.gl_pathc, sizeof(fd_boards[0]));
if (!fd_boards) {
globfree(&glob_dev);
globfree(&glob_sys);
return -1;
}
for (i = 0, b = fd_boards; i < fd_nboards; i++, b++) {
b->sysbase = strdup(glob_sys.gl_pathv[i]);
b->devbase = strdup(glob_dev.gl_pathv[i]);
/* trim the "-0-0-ctrl" at the end */
b->devbase[strlen(b->devbase) - strlen("-0-0-ctrl")] = '\0';
/* extract dev_id */
sscanf(b->sysbase, "%*[^f]fd-%x", &b->dev_id);
for (j = 0; j < ARRAY_SIZE(b->fd); j++)
b->fd[j] = -1;
if (fdelay_is_verbose()) {
fprintf(stderr, "%s: %04x %s %s\n", __func__,
b->dev_id, b->sysbase, b->devbase);
}
}
globfree(&glob_dev);
globfree(&glob_sys);
return i;
}
/* Free and check */
void fdelay_exit(void)
{
struct __fdelay_board *b;
int i, j, err;
for (i = 0, err = 0, b = fd_boards; i < fd_nboards; i++, b++) {
for (j = 0; j < ARRAY_SIZE(b->fd); j++) {
if (b->fd[j] >= 0) {
close(b->fd[j]);
err++;
}
}
if (err)
fprintf(stderr, "%s: device %s was still open\n",
__func__, b->devbase);
free(b->sysbase);
free(b->devbase);
}
if(fd_nboards)
free(fd_boards);
}
/* Open one specific device. -1 arguments mean "not installed" */
struct fdelay_board *fdelay_open(int offset, int dev_id)
{
struct __fdelay_board *b = NULL;
int i;
if (offset >= fd_nboards) {
errno = ENODEV;
return NULL;
}
if (offset >= 0) {
b = fd_boards + offset;
if (dev_id >= 0 && dev_id != b->dev_id) {
errno = EINVAL;
return NULL;
}
return (void *)b;
}
if (dev_id < 0) {
errno = EINVAL;
return NULL;
}
for (i = 0, b = fd_boards; i < fd_nboards; i++, b++)
if (b->dev_id == dev_id)
return (void *)b;
errno = ENODEV;
return NULL;
}
int fdelay_close(struct fdelay_board *userb)
{
__define_board(b, userb);
int j;
for (j = 0; j < ARRAY_SIZE(b->fd); j++)
if (b->fd[j] >= 0)
close(b->fd[j]);
return 0;
}
/* Silly thing that lists installed fine-delay boards */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define FDELAY_INTERNAL /* hack... */
#include "fdelay.h"
int main(int argc, char **argv)
{
int i, j;
struct __fdelay_board *b;
struct fdelay_board *ub;
i = fdelay_init();
if (i < 0) {
fprintf(stderr, "%s: fdelay_init(): %s\n", argv[0],
strerror(errno));
exit(1);
}
printf("%s: found %i boards\n", argv[0], i);
for (j = 0; j < i; j++) {
ub = fdelay_open(j, -1);
b = (typeof(b))ub;
printf(" dev_id %04x, %s, %s\n", b->dev_id, b->devbase,
b->sysbase);
}
fdelay_exit();
return 0;
}
/*
* The "official" fine-delay API
*
* Copyright (C) 2012 CERN (www.cern.ch)
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2 as published by the Free Software Foundation or, at your
* option, any later version.
*/
#ifndef __FDELAY_H__
#define __FDELAY_H__
/* Opaque data type used as token */
struct fdelay_board;
/* Please see the manual for the meaning of arguments and return values */
extern int fdelay_init(void);
extern void fdelay_exit(void);
extern struct fdelay_board *fdelay_open(int offset, int dev_id);
extern int fdelay_close(struct fdelay_board *);
#ifdef FDELAY_INTERNAL /* Libray users should ignore what follows */
/* Internal structure */
struct __fdelay_board {
int dev_id;
char *devbase;
char *sysbase;
int fd[5]; /* The 5 channels */
};
static inline int fdelay_is_verbose(void)
{
return getenv("FDELAY_LIB_VERBOSE") != 0;
}
#define __define_board(b, ub) struct __fdelay_board *b = (void *)(ub)
#endif /* FDELAY_INTERNAL */
#endif /* __FDELAY_H__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment