📄 devsupport.c
字号:
#define ilvt_t int/* $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. * * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. * Copyright (C) 2000 by Colin Ngam */#include <linux/types.h>#include <linux/mm.h>#include <linux/slab.h>#include <asm/sn/sgi.h>#include <asm/sn/invent.h>#include <asm/sn/hcl.h>#include <asm/sn/iobus.h>#include <asm/sn/iograph.h>/* * Interfaces in this file are all platform-independent AND IObus-independent. * Be aware that there may be macro equivalents to each of these hiding in * header files which supercede these functions. *//* =====Generic iobus support===== *//* String table to hold names of interrupts. */#ifdef notyetstatic struct string_table device_desc_string_table;#endif/* One time initialization for device descriptor support. */static voiddevice_desc_init(void){#ifdef notyet string_table_init(&device_desc_string_table);#endif FIXME("device_desc_init");}/* Drivers use these interfaces to manage device descriptors */static device_desc_tdevice_desc_alloc(void){#ifdef notyet device_desc_t device_desc; device_desc = (device_desc_t)kmem_zalloc(sizeof(struct device_desc_s), 0); device_desc->intr_target = GRAPH_VERTEX_NONE; ASSERT(device_desc->intr_policy == 0); device_desc->intr_swlevel = -1; ASSERT(device_desc->intr_name == NULL); ASSERT(device_desc->flags == 0); ASSERT(!(device_desc->flags & D_IS_ASSOC)); return(device_desc);#else FIXME("device_desc_alloc"); return((device_desc_t)0);#endif}voiddevice_desc_free(device_desc_t device_desc){#ifdef notyet if (!(device_desc->flags & D_IS_ASSOC)) /* sanity */ kfree(device_desc);#endif FIXME("device_desc_free");}device_desc_tdevice_desc_dup(devfs_handle_t dev){#ifdef notyet device_desc_t orig_device_desc, new_device_desc; new_device_desc = device_desc_alloc(); orig_device_desc = device_desc_default_get(dev); if (orig_device_desc) *new_device_desc = *orig_device_desc;/* small structure copy */ else { device_driver_t driver; ilvl_t pri; /* * Use the driver's thread priority in * case the device thread priority has not * been given. */ if (driver = device_driver_getbydev(dev)) { pri = device_driver_thread_pri_get(driver); device_desc_intr_swlevel_set(new_device_desc,pri); } } new_device_desc->flags &= ~D_IS_ASSOC; return(new_device_desc);#else FIXME("device_desc_dup"); return((device_desc_t)0);#endif}device_desc_t device_desc_default_get(devfs_handle_t dev){#ifdef notyet graph_error_t rc; device_desc_t device_desc; rc = hwgraph_info_get_LBL(dev, INFO_LBL_DEVICE_DESC, (arbitrary_info_t *)&device_desc); if (rc == GRAPH_SUCCESS) return(device_desc); else return(NULL);#else FIXME("device_desc_default_get"); return((device_desc_t)0);#endif}void device_desc_default_set(devfs_handle_t dev, device_desc_t new_device_desc){#ifdef notyet graph_error_t rc; device_desc_t old_device_desc = NULL; if (new_device_desc) { new_device_desc->flags |= D_IS_ASSOC; rc = hwgraph_info_add_LBL(dev, INFO_LBL_DEVICE_DESC, (arbitrary_info_t)new_device_desc); if (rc == GRAPH_DUP) { rc = hwgraph_info_replace_LBL(dev, INFO_LBL_DEVICE_DESC, (arbitrary_info_t)new_device_desc, (arbitrary_info_t *)&old_device_desc); ASSERT(rc == GRAPH_SUCCESS); } hwgraph_info_export_LBL(dev, INFO_LBL_DEVICE_DESC, sizeof(struct device_desc_s)); } else { rc = hwgraph_info_remove_LBL(dev, INFO_LBL_DEVICE_DESC, (arbitrary_info_t *)&old_device_desc); } if (old_device_desc) { ASSERT(old_device_desc->flags & D_IS_ASSOC); old_device_desc->flags &= ~D_IS_ASSOC; device_desc_free(old_device_desc); }#endif FIXME("device_desc_default_set");}devfs_handle_tdevice_desc_intr_target_get(device_desc_t device_desc){#ifdef notyet return(device_desc->intr_target);#else FIXME("device_desc_intr_target_get"); return((devfs_handle_t)0);#endif}intdevice_desc_intr_policy_get(device_desc_t device_desc){#ifdef notyet return(device_desc->intr_policy);#else FIXME("device_desc_intr_policy_get"); return(0);#endif}ilvl_tdevice_desc_intr_swlevel_get(device_desc_t device_desc){#ifdef notyet return(device_desc->intr_swlevel);#else FIXME("device_desc_intr_swlevel_get"); return((ilvl_t)0);#endif}char *device_desc_intr_name_get(device_desc_t device_desc){#ifdef notyet return(device_desc->intr_name);#else FIXME("device_desc_intr_name_get"); return(NULL);#endif}intdevice_desc_flags_get(device_desc_t device_desc){#ifdef notyet return(device_desc->flags);#else FIXME("device_desc_flags_get"); return(0);#endif}voiddevice_desc_intr_target_set(device_desc_t device_desc, devfs_handle_t target){ if ( device_desc != (device_desc_t)0 ) device_desc->intr_target = target;}voiddevice_desc_intr_policy_set(device_desc_t device_desc, int policy){ if ( device_desc != (device_desc_t)0 ) device_desc->intr_policy = policy;}voiddevice_desc_intr_swlevel_set(device_desc_t device_desc, ilvl_t swlevel){ if ( device_desc != (device_desc_t)0 ) device_desc->intr_swlevel = swlevel;}voiddevice_desc_intr_name_set(device_desc_t device_desc, char *name){#ifdef notyet if ( device_desc != (device_desc_t)0 ) device_desc->intr_name = string_table_insert(&device_desc_string_table, name);#else FIXME("device_desc_intr_name_set");#endif}voiddevice_desc_flags_set(device_desc_t device_desc, int flags){ if ( device_desc != (device_desc_t)0 ) device_desc->flags = flags;}/*============= device admin registry routines ===================== *//* Linked list of <admin-name,admin-val> pairs */typedef struct dev_admin_list_s { struct dev_admin_list_s *admin_next; /* next entry in the * list */ char *admin_name; /* info label */ char *admin_val; /* actual info */} dev_admin_list_t;/* Device/Driver administration registry */typedef struct dev_admin_registry_s { mrlock_t reg_lock; /* To allow * exclusive * access */ dev_admin_list_t *reg_first; /* first entry in * the list */ dev_admin_list_t **reg_last; /* pointer to the * next to last entry * in the last which * is also the place * where the new * entry gets * inserted */} dev_admin_registry_t;/*** device_driver_s associates a device driver prefix with device switch entries.*/struct device_driver_s { struct device_driver_s *dd_next; /* next element on hash chain */ struct device_driver_s *dd_prev; /* previous element on hash chain */ char *dd_prefix; /* driver prefix string */ struct bdevsw *dd_bdevsw; /* driver's bdevsw */ struct cdevsw *dd_cdevsw; /* driver's cdevsw */ /* driver administration specific data structures need to * maintain the list of <driver-paramater,value> pairs */ dev_admin_registry_t dd_dev_admin_registry; ilvl_t dd_thread_pri; /* default thread priority for * all this driver's * threads. */};#define NEW(_p) (_p = kmalloc(sizeof(*_p), GFP_KERNEL))#define FREE(_p) (kmem_free(_p)) /* * helpful lock macros */#define DEV_ADMIN_REGISTRY_INITLOCK(lockp,name) mrinit(lockp,name)#define DEV_ADMIN_REGISTRY_RDLOCK(lockp) mraccess(lockp) #define DEV_ADMIN_REGISTRY_WRLOCK(lockp) mrupdate(lockp) #define DEV_ADMIN_REGISTRY_UNLOCK(lockp) mrunlock(lockp)/* Initialize the registry */static voiddev_admin_registry_init(dev_admin_registry_t *registry){#ifdef notyet if ( registry != (dev_admin_registry_t *)0 ) DEV_ADMIN_REGISTRY_INITLOCK(®istry->reg_lock, "dev_admin_registry_lock"); registry->reg_first = NULL; registry->reg_last = ®istry->reg_first; }#else FIXME("dev_admin_registry_init");#endif}/* * add an <name , value > entry to the dev admin registry. * if the name already exists in the registry then change the * value iff the new value differs from the old value. * if the name doesn't exist a new list entry is created and put * at the end. */static voiddev_admin_registry_add(dev_admin_registry_t *registry, char *name, char *val){#ifdef notyet dev_admin_list_t *reg_entry; dev_admin_list_t *scan = 0; DEV_ADMIN_REGISTRY_WRLOCK(®istry->reg_lock); /* check if the name already exists in the registry */ scan = registry->reg_first; while (scan) { if (strcmp(scan->admin_name,name) == 0) { /* name is there in the registry */ if (strcmp(scan->admin_val,val)) { /* old value != new value * reallocate memory and copy the new value */ FREE(scan->admin_val); scan->admin_val = (char *)kern_calloc(1,strlen(val)+1); strcpy(scan->admin_val,val); goto out; } goto out; /* old value == new value */ } scan = scan->admin_next; } /* name is not there in the registry. * allocate memory for the new registry entry */ NEW(reg_entry); reg_entry->admin_next = 0; reg_entry->admin_name = (char *)kern_calloc(1,strlen(name)+1); strcpy(reg_entry->admin_name,name); reg_entry->admin_val = (char *)kern_calloc(1,strlen(val)+1); strcpy(reg_entry->admin_val,val); /* add the entry at the end of the registry */ *(registry->reg_last) = reg_entry; registry->reg_last = ®_entry->admin_next;out: DEV_ADMIN_REGISTRY_UNLOCK(®istry->reg_lock);#endif FIXME("dev_admin_registry_add");}/* * check if there is an info corr. to a particular * name starting from the cursor position in the * registry */static char *dev_admin_registry_find(dev_admin_registry_t *registry,char *name){#ifdef notyet dev_admin_list_t *scan = 0; DEV_ADMIN_REGISTRY_RDLOCK(®istry->reg_lock); scan = registry->reg_first; while (scan) { if (strcmp(scan->admin_name,name) == 0) { DEV_ADMIN_REGISTRY_UNLOCK(®istry->reg_lock); return scan->admin_val; } scan = scan->admin_next; } DEV_ADMIN_REGISTRY_UNLOCK(®istry->reg_lock); return 0;#else FIXME("dev_admin_registry_find"); return(NULL);#endif}/*============= MAIN DEVICE/ DRIVER ADMINISTRATION INTERFACE================ *//* * return any labelled info associated with a device. * called by any kernel code including device drivers. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -