📄 hcl.c
字号:
/* $Id$ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * hcl - SGI's Hardware Graph compatibility layer. * * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. * Copyright (C) 2000 by Colin Ngam */#include <linux/types.h>#include <linux/config.h>#include <linux/slab.h>#include <linux/ctype.h>#include <linux/module.h>#include <linux/init.h>#include <asm/sn/sgi.h>#include <linux/devfs_fs.h>#include <linux/devfs_fs_kernel.h>#include <asm/io.h>#include <asm/sn/iograph.h>#include <asm/sn/invent.h>#include <asm/sn/hcl.h>#include <asm/sn/labelcl.h>#define HCL_NAME "SGI-HWGRAPH COMPATIBILITY DRIVER"#define HCL_TEMP_NAME "HCL_TEMP_NAME_USED_FOR_HWGRAPH_VERTEX_CREATE"#define HCL_TEMP_NAME_LEN 44 #define HCL_VERSION "1.0"devfs_handle_t hwgraph_root = NULL;/* * Debug flag definition. */#define OPTION_NONE 0x00#define HCL_DEBUG_NONE 0x00000#define HCL_DEBUG_ALL 0x0ffff#if defined(CONFIG_HCL_DEBUG)static unsigned int hcl_debug_init __initdata = HCL_DEBUG_NONE;#endifstatic unsigned int hcl_debug = HCL_DEBUG_NONE;static unsigned int boot_options = OPTION_NONE;/* * Some Global definitions. */spinlock_t hcl_spinlock;devfs_handle_t hcl_handle = NULL;/* * HCL device driver. * The purpose of this device driver is to provide a facility * for User Level Apps e.g. hinv, ioconfig etc. an ioctl path * to manipulate label entries without having to implement * system call interfaces. This methodology will enable us to * make this feature module loadable. */static int hcl_open(struct inode * inode, struct file * filp){ if (hcl_debug) { printk("HCL: hcl_open called.\n"); } return(0);}static int hcl_close(struct inode * inode, struct file * filp){ if (hcl_debug) { printk("HCL: hcl_close called.\n"); } return(0);}static int hcl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg){ if (hcl_debug) { printk("HCL: hcl_ioctl called.\n"); } switch (cmd) { default: if (hcl_debug) { printk("HCL: hcl_ioctl cmd = 0x%x\n", cmd); } } return(0);}struct file_operations hcl_fops = { NULL, /* lseek - default */ NULL, /* read - general block-dev read */ NULL, /* write - general block-dev write */ NULL, /* readdir - bad */ NULL, /* poll */ hcl_ioctl, /* ioctl */ NULL, /* mmap */ hcl_open, /* open */ NULL, /* flush */ hcl_close, /* release */ NULL, /* fsync */ NULL, /* fasync */ NULL, /* check_media_change */ NULL, /* revalidate */ NULL /* lock */};/* * init_hcl() - Boot time initialization. Ensure that it is called * after devfs has been initialized. * * For now this routine is being called out of devfs/base.c. Actually * Not a bad place to be .. * */#ifdef MODULEint init_module (void)#elseint __init init_hcl(void)#endif{ extern void string_table_init(struct string_table *); extern struct string_table label_string_table; int rv = 0; printk ("\n%s: v%s Colin Ngam (cngam@sgi.com)\n", HCL_NAME, HCL_VERSION);#if defined(CONFIG_HCL_DEBUG) && !defined(MODULE) hcl_debug = hcl_debug_init; printk ("%s: hcl_debug: 0x%0x\n", HCL_NAME, hcl_debug);#endif printk ("\n%s: boot_options: 0x%0x\n", HCL_NAME, boot_options); spin_lock_init(&hcl_spinlock); /* * Create the hwgraph_root on devfs. */ rv = hwgraph_path_add(NULL, "hw", &hwgraph_root); if (rv) printk ("init_hcl: Failed to create hwgraph_root. Error = %d.\n", rv); /* * Create the hcl driver to support inventory entry manipulations. * By default, it is expected that devfs is mounted on /dev. * */ hcl_handle = hwgraph_register(hwgraph_root, ".hcl", 0, DEVFS_FL_AUTO_DEVNUM, 0, 0, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, &hcl_fops, NULL); if (hcl_handle == NULL) { panic("HCL: Unable to create HCL Driver in init_hcl().\n"); return(0); } /* * Initialize the HCL string table. */ string_table_init(&label_string_table); return(0);}/* * hcl_setup() - Process boot time parameters if given. * "hcl=" * This routine gets called only if "hcl=" is given in the * boot line and before init_hcl(). * * We currently do not have any boot options .. when we do, * functionalities can be added here. * */static int __init hcl_setup(char *str){ while ( (*str != '\0') && !isspace (*str) ) { printk("HCL: Boot time parameter %s\n", str);#ifdef CONFIG_HCL_DEBUG if (strncmp (str, "all", 3) == 0) { hcl_debug_init |= HCL_DEBUG_ALL; str += 3; } else return 0;#endif if (*str != ',') return 0; ++str; } return 1;}__setup("hcl=", hcl_setup);/* * Set device specific "fast information". * */voidhwgraph_fastinfo_set(devfs_handle_t de, arbitrary_info_t fastinfo){ if (hcl_debug) { printk("HCL: hwgraph_fastinfo_set handle 0x%p fastinfo %ld\n", de, fastinfo); } labelcl_info_replace_IDX(de, HWGRAPH_FASTINFO, fastinfo, NULL);}/* * Get device specific "fast information". * */arbitrary_info_thwgraph_fastinfo_get(devfs_handle_t de){ arbitrary_info_t fastinfo; int rv; if (!de) { printk(KERN_WARNING "HCL: hwgraph_fastinfo_get handle given is NULL.\n"); return(-1); } rv = labelcl_info_get_IDX(de, HWGRAPH_FASTINFO, &fastinfo); if (rv == 0) return(fastinfo); return(0);}/* * hwgraph_connectpt_set - Sets the connect point handle in de to the * given connect_de handle. By default, the connect point of the * devfs node is the parent. This effectively changes this assumption. */inthwgraph_connectpt_set(devfs_handle_t de, devfs_handle_t connect_de){ int rv; if (!de) return(-1); rv = labelcl_info_connectpt_set(de, connect_de); return(rv);}/* * hwgraph_connectpt_get: Returns the entry's connect point in the devfs * tree. */devfs_handle_thwgraph_connectpt_get(devfs_handle_t de){ int rv; arbitrary_info_t info; devfs_handle_t connect; rv = labelcl_info_get_IDX(de, HWGRAPH_CONNECTPT, &info); if (rv != 0) { return(NULL); } connect = (devfs_handle_t)info; return(connect);}/* * hwgraph_mk_dir - Creates a directory entry with devfs. * Note that a directory entry in devfs can have children * but it cannot be a char|block special file. */devfs_handle_thwgraph_mk_dir(devfs_handle_t de, const char *name, unsigned int namelen, void *info){ int rv; labelcl_info_t *labelcl_info = NULL; devfs_handle_t new_devfs_handle = NULL; devfs_handle_t parent = NULL; /* * Create the device info structure for hwgraph compatiblity support. */ labelcl_info = labelcl_info_create(); if (!labelcl_info) return(NULL); /* * Create a devfs entry. */ new_devfs_handle = devfs_mk_dir(de, name, (void *)labelcl_info); if (!new_devfs_handle) { labelcl_info_destroy(labelcl_info); return(NULL); } /* * Get the parent handle. */ parent = devfs_get_parent (new_devfs_handle); /* * To provide the same semantics as the hwgraph, set the connect point. */ rv = hwgraph_connectpt_set(new_devfs_handle, parent); if (!rv) { /* * We need to clean up! */ } /* * If the caller provides a private data pointer, save it in the * labelcl info structure(fastinfo). This can be retrieved via * hwgraph_fastinfo_get() */ if (info) hwgraph_fastinfo_set(new_devfs_handle, (arbitrary_info_t)info); return(new_devfs_handle);}/* * hwgraph_vertex_create - Create a vertex by giving it a temp name. *//* * hwgraph_path_add - Create a directory node with the given path starting * from the given devfs_handle_t. */extern char * dev_to_name(devfs_handle_t, char *, uint);inthwgraph_path_add(devfs_handle_t fromv, char *path, devfs_handle_t *new_de){ unsigned int namelen = strlen(path); int rv; /* * We need to handle the case when fromv is NULL .. * in this case we need to create the path from the * hwgraph root! */ if (fromv == NULL) fromv = hwgraph_root; /* * check the entry doesn't already exist, if it does * then we simply want new_de to point to it (otherwise * we'll overwrite the existing labelcl_info struct) */ rv = hwgraph_edge_get(fromv, path, new_de); if (rv) { /* couldn't find entry so we create it */ *new_de = hwgraph_mk_dir(fromv, path, namelen, NULL); if (new_de == NULL) return(-1); else return(0); } else return(0);}/* * hwgraph_register - Creates a file entry with devfs. * Note that a file entry cannot have children .. it is like a * char|block special vertex in hwgraph. */devfs_handle_thwgraph_register(devfs_handle_t de, const char *name, unsigned int namelen, unsigned int flags, unsigned int major, unsigned int minor, umode_t mode, uid_t uid, gid_t gid, struct file_operations *fops, void *info){ int rv; void *labelcl_info = NULL; devfs_handle_t new_devfs_handle = NULL; devfs_handle_t parent = NULL; /* * Create the labelcl info structure for hwgraph compatiblity support. */ labelcl_info = labelcl_info_create(); if (!labelcl_info) return(NULL); /* * Create a devfs entry. */ new_devfs_handle = devfs_register(de, name, flags, major, minor, mode, fops, labelcl_info); if (!new_devfs_handle) { labelcl_info_destroy((labelcl_info_t *)labelcl_info); return(NULL); } /* * Get the parent handle. */ if (de == NULL) parent = devfs_get_parent (new_devfs_handle); else parent = de; /* * To provide the same semantics as the hwgraph, set the connect point. */ rv = hwgraph_connectpt_set(new_devfs_handle, parent); if (rv) { /* * We need to clean up! */ printk("HCL: Unable to set the connect point to it's parent 0x%p\n", new_devfs_handle); } /* * If the caller provides a private data pointer, save it in the * labelcl info structure(fastinfo). This can be retrieved via * hwgraph_fastinfo_get() */ if (info) hwgraph_fastinfo_set(new_devfs_handle, (arbitrary_info_t)info); return(new_devfs_handle);}/* * hwgraph_mk_symlink - Create a symbolic link. */inthwgraph_mk_symlink(devfs_handle_t de, const char *name, unsigned int namelen, unsigned int flags, const char *link, unsigned int linklen, devfs_handle_t *handle, void *info){ void *labelcl_info = NULL; int status = 0; devfs_handle_t new_devfs_handle = NULL; /* * Create the labelcl info structure for hwgraph compatiblity support. */ labelcl_info = labelcl_info_create(); if (!labelcl_info) return(-1); /* * Create a symbolic link devfs entry. */ status = devfs_mk_symlink(de, name, flags, link, &new_devfs_handle, labelcl_info); if ( (!new_devfs_handle) || (!status) ){ labelcl_info_destroy((labelcl_info_t *)labelcl_info); return(-1); } /* * If the caller provides a private data pointer, save it in the * labelcl info structure(fastinfo). This can be retrieved via * hwgraph_fastinfo_get() */ if (info) hwgraph_fastinfo_set(new_devfs_handle, (arbitrary_info_t)info); *handle = new_devfs_handle;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -