Beispiel #1
0
/*
 *  clone_open: - open a clone device node
 *  @inode: the external filesystem inode
 *  @file: the external filesystem file pointer
 *
 *  clone_open() is only used to open a clone device from a character device node in an external
 *  filesystem.  This is never called for direct opens of a specfs device node (for direct opens see
 *  spec_dev_open() in strspecfs.c).  The character device number from the inode is used to
 *  determine the shadow special filesystem (internal) inode and chain the open call.
 *
 *  This is the separation point where we convert the external device number to an internal device
 *  number.  The external device number is contained in inode->i_rdev.
 */
STATIC int
clone_open(struct inode *inode, struct file *file)
{
	int err;
	struct cdevsw *cdev;
	major_t major;
	minor_t minor;
	modID_t modid, instance;

#if defined HAVE_KFUNC_TO_KDEV_T
	minor = MINOR(kdev_t_to_nr(inode->i_rdev));
	major = MAJOR(kdev_t_to_nr(inode->i_rdev));
#else
	minor = MINOR(inode->i_rdev);
	major = MAJOR(inode->i_rdev);
#endif
	minor = cdev_minor(&clone_cdev, major, minor);
	major = clone_cdev.d_major;
	modid = clone_cdev.d_modid;
	err = -ENXIO;
	if (!(cdev = sdev_get(minor))) {
		goto exit;
	}
	instance = cdev->d_modid;
	err = spec_open(file, cdev, makedevice(modid, instance), CLONEOPEN);
	sdev_put(cdev);
      exit:
	return (err);
}
Beispiel #2
0
/**
 *  cdev_open: - open a character special device node
 *  @inode: the character device inode
 *  @file: the user file pointer
 *
 *  cdev_open() is only used to open a stream from a character device node in an external
 *  filesystem.  This is never called for direct opens of a specfs device node (for direct opens see
 *  spec_dev_open() in strspecfs.c).  It is also not used for direct opens of fifos, pipes or
 *  sockets.  Those devices provide their own file operations to the main operating system.  The
 *  character device number from the inode is used to determine the shadow special file system
 *  (internal) inode and chain the open call.
 *
 *  This is the separation point where we convert the external device number to an internal device
 *  number.  The external device number is contained in inode->i_rdev.
 *
 *  @inode is the inode in the external filesystem.
 *
 *  @file->f_op is the external file operations (character device, fifo) and must be replaced with
 *	our file operations.
 *
 *  @file->f_dentry is the external filesystem dentry for the device node.
 *  @file->f_vfsmnt is the external filesystem vfsmnt for the device node.
 *  @file exists on the file->f_dentry->d_inode->i_sb->s_files list.
 *
 *  What we should be doing here is get a fresh new dentry.  Find our inode from the device number,
 *  add it to the dentry.  Set the dentry->d_sb to the specfs super block, set dentry->d_parent =
 *  dget(file->f_dentry->d_parent), but do not add the dentry to the child list on the parent
 *  directory, nor do we hash the dentry.  Next we do a dentry open on the on the dentry and a file
 *  pointer swap on return.
 *
 *  Instead of farting around with dentries and such, just lookup the inode in the specfs replace
 *  the file->f_ops and chain the open with the specfs inode passed to the new open procedure.  For
 *  FIFOs we pass the external filesystem inode instead.
 */
STATIC int
cdev_open(struct inode *inode, struct file *file)
{
	int err;
	struct cdevsw *cdev;
	struct devnode *cmin;
	major_t major;
	minor_t minor;
	modID_t modid;
	dev_t dev;
	int sflag;

#if defined HAVE_KFUNC_TO_KDEV_T
	minor = MINOR(kdev_t_to_nr(inode->i_rdev));
	major = MAJOR(kdev_t_to_nr(inode->i_rdev));
#else
	minor = MINOR(inode->i_rdev);
	major = MAJOR(inode->i_rdev);
#endif
	if (!(cdev = sdev_get(major))) {
		return (-ENXIO);
	}
	minor = cdev_minor(cdev, major, minor);
	major = cdev->d_major;
	modid = cdev->d_modid;
	dev = makedevice(modid, minor);
	sflag = DRVOPEN;
	if (cdev->d_flag & D_CLONE)
		sflag = CLONEOPEN;
	else if ((cmin = cmin_get(cdev, minor)) && cmin->n_flag & D_CLONE)
		sflag = CLONEOPEN;
	err = spec_open(file, cdev, dev, sflag);
	sdev_put(cdev);
	return (err);
}
Beispiel #3
0
/**
 *  cloneopen: - open a clone special device
 *  @inode:	shadow special filesystem inode
 *  @file:	shadow special filesystem file pointer
 *
 *  cloneopen() is called only from within the shadow special filesystem.  This can occur by
 *  chaining from the external filesystem (e.g. openining a character device with clone major) or by
 *  direct open of the inode within the mounted shadow special filesystem.  Either way, the inode
 *  number has our extended device numbering as a inode number and we chain the call within the
 *  shadow special filesystem.
 */
static int
cloneopen(struct inode *inode, struct file *file)
{
	struct cdevsw *cdev;
	dev_t dev = inode->i_ino;

	if (file->private_data)
		/* Darn.  Somebody passed us a FIFO inode. */
		return (-EIO);

	if ((cdev = sdev_get(getminor(dev)))) {
		int err;

		dev = makedevice(cdev->d_modid, 0);
		err = spec_open(file, cdev, dev, CLONEOPEN);
		sdev_put(cdev);
		return (err);
	}
	return (-ENOENT);
}
Beispiel #4
0
static int spec_fdelay_create(fdelay_device_t *dev, int bus, int dev_fn)
{
	uint32_t base;

	dev->priv_io = spec_open(bus, dev_fn);

	if(!dev->priv_io)
	{
	 	fprintf(stderr,"Can't map the SPEC @ %x:%x\n", bus, dev_fn);
	 	return -1;
	}

	dev->writel = fd_spec_writel;
	dev->readl = fd_spec_readl;
	dev->base_addr = base;

	//spec_vuart_init(dev->priv_io, 0xe0500); /* for communication with WRCore during DMTD calibration */

    return 0;
}
Beispiel #5
0
int
ptyfs_open(void *v)
{
	struct vop_open_args /* {
		struct vnode *a_vp;
		int  a_mode;
		kauth_cred_t a_cred;
	} */ *ap = v;
	struct vnode *vp = ap->a_vp;
	struct ptyfsnode *ptyfs = VTOPTYFS(vp);

	switch (ptyfs->ptyfs_type) {
	case PTYFSpts:
	case PTYFSptc:
		return spec_open(v);
	case PTYFSroot:
		return 0;
	default:
		return EINVAL;
	}
}
Beispiel #6
0
STATIC int
nsdev_open(struct inode *inode, struct file *file)
{
	int err;
	struct cdevsw *cdev;
	struct dentry *dentry;
	major_t major;
	minor_t minor;
	modID_t modid, instance;
	dev_t dev;

#if defined HAVE_KFUNC_TO_KDEV_T
	minor = MINOR(kdev_t_to_nr(inode->i_rdev));
	major = MAJOR(kdev_t_to_nr(inode->i_rdev));
#else
	minor = MINOR(inode->i_rdev);
	major = MAJOR(inode->i_rdev);
#endif
	minor = cdev_minor(&nsdev_cdev, major, minor);
	major = nsdev_cdev.d_major;
	modid = nsdev_cdev.d_modid;
#ifdef HAVE_KMEMB_STRUCT_FILE_F_VFSMNT
	dentry = file->f_dentry;
#else
	dentry = file->f_path.dentry;
#endif
	err = -ENXIO;
	if (!(cdev = cdev_match((char *) dentry->d_name.name)))
		goto exit;
	err = -ENXIO;
	if (cdev == &nsdev_cdev)
		goto cdev_put_exit;	/* would loop */
	instance = cdev->d_modid;
	dev = makedevice(modid, instance);
	err = spec_open(file, cdev, dev, CLONEOPEN);
      cdev_put_exit:
	sdev_put(cdev);
      exit:
	return (err);
}
Beispiel #7
0
/**
 *  nsdevopen:	- open the named streams device
 *  @inode:	shadow special filesystem inode to open
 *  @file:	shadow special filesystem file pointer to open
 *
 *  This is rather simple.  We are going to do a redirected open on the a new device with the major
 *  device number mapped according to name.  We do this by nesting another spec_open() inside the
 *  first one with an adjusted device number. It helps that the orginal file pointer is stored with
 *  the args passed as private_data attached to the current file pointer.  We use this to find the
 *  original file pointer and dentry and get the name of the opened file.
 *
 *  If we don't find a reasonable match and kmod is equipped, we try to load the module with
 *  'streams-' prefixed to the name and run through the list again.  We could also generate the
 *  request from the path to the original dentry.
 */
static int
nsdevopen(struct inode *inode, struct file *file)
{
	struct cdevsw *cdev;
	struct dentry *dentry;
	int err;

#ifdef HAVE_KMEMB_STRUCT_FILE_F_VFSMNT
	dentry = file->f_dentry;
#else
	dentry = file->f_path.dentry;
#endif
	if ((cdev = cdev_match((char *) dentry->d_name.name))) {
		major_t major = cdev->d_modid;
		minor_t minor = getminor(inode->i_ino);
		dev_t dev = makedevice(major, minor);
		int sflag = (file->f_flags & O_CLONE) ? CLONEOPEN : DRVOPEN;

		err = spec_open(file, cdev, dev, sflag);
		sdev_put(cdev);
	} else
		err = -ENOENT;
	return (err);
}
Beispiel #8
0
/* based on minimal daemon code from the daemon-HOWTO */
int main(void) {       
        /* Our process ID and Session ID */
        pid_t pid, sid;       
        /* Fork off the parent process */
        pid = fork();
        if (pid < 0) {
                exit(EXIT_FAILURE);
        }
        /* If we got a good PID, then we can exit the parent process. */
        if (pid > 0) {
                exit(EXIT_SUCCESS);
        }
        /* Change the file mode mask */
        umask(0);
                
                
        /* Create a new SID for the child process */
        sid = setsid();
        if (sid < 0) {
                //syslog(LOG_ERR,"setsid() error. EXIT.");
                exit(EXIT_FAILURE);
        }

        /* Change the current working directory */
        if ((chdir("/")) < 0) {
                /* Log the failure */
                //syslog(LOG_ERR,"chdir() error. EXIT.");
                exit(EXIT_FAILURE);
        }
        
        /* Close out the standard file descriptors */
        close(STDIN_FILENO);
        close(STDOUT_FILENO);
        close(STDERR_FILENO);
        
        /* Daemon-specific initialization goes here */
                /* use syslog */
        setlogmask (LOG_UPTO (LOG_NOTICE));
        openlog ("spec_ptp2ntpd", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
        syslog (LOG_NOTICE, "Program started by User %d", getuid());

        // Attach to SPEC shared memory           
        int bar = BASE_BAR0;
        int bus = -1, dev_fn = -1;
        void *card;
        void *map_base;
        card = spec_open(bus, dev_fn);
        if(!card)
        {
            syslog(LOG_ERR, "Can't detect a SPEC card under the given "
                "adress. Make sure a SPEC card is present in your PC, "
                "the driver is loaded and you run the program as root. EXIT.\n");
            exit(1);
        }
        syslog(LOG_NOTICE,"Found SPEC at %x \n",(uint)card);

        map_base = spec_get_base(card, bar);
        if(!map_base || map_base == (void *) -1) {
            syslog(LOG_ERR,"mmap(/dev/mem): %s. EXIT.\n",  strerror(errno));
            syslog(LOG_ERR, "map_base = %x \n",(uint)map_base);
            exit(1);
        }
        syslog(LOG_NOTICE,"map_base = %u \n",(uint)map_base);
        syslog (LOG_NOTICE, "Attached to SPEC SHM at %x", (uint)map_base);
            
        // attach to NTP shared memory
        T = getShmTime(0);
        if (T==0) { /* error */
            syslog(LOG_ERR,"getShmTime() error");
            syslog(LOG_ERR,"EXITING.");
            exit(EXIT_FAILURE);
        } else {
            syslog (LOG_NOTICE, "Attached to NTP SHM at %x", (uint)T);
        }
        
        // initialize
        T->mode=1; // does it matter? set here or by NTP?
        T->leap=0; // ?
        T->precision=-10; //?
        T->nsamples=10; // ?
        shmdt(T); //detach
        
        struct timeval tv;
        uint32_t nsec_cycles, s_lsb,  usecs;
        double cycle = 1/125e6;
        uint32_t nsecs;
                        
        /* The Big Loop */
        while (1) {
            T = getShmTime(0); // attach to shared memory

            gettimeofday(&tv,NULL); // system time-stamp
            
            // WR time
            nsec_cycles = read_mem(map_base, 4 ); // read nanoseconds, in number of 62.5MHz ref cycles
            nsecs = (uint32_t) (cycle*nsec_cycles*1e9);
            usecs = (uint32_t) (cycle*nsec_cycles*1e6);
            s_lsb = read_mem(map_base, 8 ); // read utc lsb
            //s_msb = read_mem(map_base, 12 ); // read utc msb
            
            // clock time
            T->clockTimeStampSec =  s_lsb;
            T->clockTimeStampUSec = usecs; // offset 4 msec, just for fun
            T->clockTimeStampNSec = nsecs;
            
            // time stamp
            T->receiveTimeStampSec  = tv.tv_sec;
            T->receiveTimeStampUSec = tv.tv_usec;
            T->receiveTimeStampNSec = tv.tv_usec*1000;
            
            T->valid = 1;
            T->count += 1;
            
            shmdt(T); // detach, required here?

            syslog (LOG_NOTICE, "WR     time is %d.%09d ", (int)s_lsb,(int)nsecs);
            syslog (LOG_NOTICE, "system time is %d.%06d ", (int)tv.tv_sec,(int)tv.tv_usec);
            sleep(8); // minpoll is 4, so NTP reads every 16s
        }
    spec_close(card);
    closelog();
    exit(EXIT_SUCCESS);
}