devsupport.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:31k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id$
  2.  *
  3.  * This file is subject to the terms and conditions of the GNU General Public
  4.  * License.  See the file "COPYING" in the main directory of this archive
  5.  * for more details.
  6.  *
  7.  * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc.
  8.  * Copyright (C) 2000 by Colin Ngam
  9.  */
  10. #include <linux/types.h>
  11. #include <linux/mm.h>
  12. #include <linux/slab.h>
  13. #include <asm/sn/sgi.h>
  14. #include <asm/sn/invent.h>
  15. #include <asm/sn/hcl.h>
  16. #include <asm/sn/iobus.h>
  17. #include <asm/sn/iograph.h>
  18. /* 
  19.  * Interfaces in this file are all platform-independent AND IObus-independent.
  20.  * Be aware that there may be macro equivalents to each of these hiding in
  21.  * header files which supercede these functions.
  22.  */
  23. /* =====Generic iobus support===== */
  24. /* String table to hold names of interrupts. */
  25. #ifdef LATER
  26. static struct string_table device_desc_string_table;
  27. #endif
  28. /* One time initialization for device descriptor support. */
  29. static void
  30. device_desc_init(void)
  31. {
  32. #ifdef LATER
  33. string_table_init(&device_desc_string_table);
  34. #endif
  35. FIXME("device_desc_init");
  36. }
  37. /* Drivers use these interfaces to manage device descriptors */
  38. static device_desc_t
  39. device_desc_alloc(void)
  40. {
  41. #ifdef LATER
  42. device_desc_t device_desc;
  43. device_desc = (device_desc_t)kmem_zalloc(sizeof(struct device_desc_s), 0);
  44. device_desc->intr_target = GRAPH_VERTEX_NONE;
  45. ASSERT(device_desc->intr_policy == 0);
  46. device_desc->intr_swlevel = -1;
  47. ASSERT(device_desc->intr_name == NULL);
  48. ASSERT(device_desc->flags == 0);
  49. ASSERT(!(device_desc->flags & D_IS_ASSOC));
  50. return(device_desc);
  51. #else
  52. FIXME("device_desc_alloc");
  53. return((device_desc_t)0);
  54. #endif
  55. }
  56. void
  57. device_desc_free(device_desc_t device_desc)
  58. {
  59. #ifdef LATER
  60. if (!(device_desc->flags & D_IS_ASSOC)) /* sanity */
  61. kfree(device_desc);
  62. #endif
  63. FIXME("device_desc_free");
  64. }
  65. device_desc_t
  66. device_desc_dup(devfs_handle_t dev)
  67. {
  68. #ifdef LATER
  69. device_desc_t orig_device_desc, new_device_desc;
  70. new_device_desc = device_desc_alloc();
  71. orig_device_desc = device_desc_default_get(dev);
  72. if (orig_device_desc)
  73. *new_device_desc = *orig_device_desc;/* small structure copy */
  74. else {
  75. device_driver_t driver;
  76. ilvl_t pri;
  77. /* 
  78.  * Use the driver's thread priority in 
  79.  * case the device thread priority has not
  80.  * been given.
  81.  */
  82. if (driver = device_driver_getbydev(dev)) {
  83. pri = device_driver_thread_pri_get(driver);
  84. device_desc_intr_swlevel_set(new_device_desc,pri);
  85. }
  86. }
  87. new_device_desc->flags &= ~D_IS_ASSOC;
  88. return(new_device_desc);
  89. #else
  90. FIXME("device_desc_dup");
  91. return((device_desc_t)0);
  92. #endif
  93. }
  94. device_desc_t
  95. device_desc_default_get(devfs_handle_t dev)
  96. {
  97. #ifdef LATER
  98. graph_error_t rc;
  99. device_desc_t device_desc;
  100. rc = hwgraph_info_get_LBL(dev, INFO_LBL_DEVICE_DESC, (arbitrary_info_t *)&device_desc);
  101. if (rc == GRAPH_SUCCESS)
  102. return(device_desc);
  103. else
  104. return(NULL);
  105. #else
  106. FIXME("device_desc_default_get");
  107. return((device_desc_t)0);
  108. #endif
  109. }
  110. void
  111. device_desc_default_set(devfs_handle_t dev, device_desc_t new_device_desc)
  112. {
  113. #ifdef LATER
  114. graph_error_t rc;
  115. device_desc_t old_device_desc = NULL;
  116. if (new_device_desc) {
  117. new_device_desc->flags |= D_IS_ASSOC;
  118. rc = hwgraph_info_add_LBL(dev, INFO_LBL_DEVICE_DESC, 
  119. (arbitrary_info_t)new_device_desc);
  120. if (rc == GRAPH_DUP) {
  121. rc = hwgraph_info_replace_LBL(dev, INFO_LBL_DEVICE_DESC, 
  122. (arbitrary_info_t)new_device_desc, 
  123. (arbitrary_info_t *)&old_device_desc);
  124. ASSERT(rc == GRAPH_SUCCESS);
  125. }
  126. hwgraph_info_export_LBL(dev, INFO_LBL_DEVICE_DESC,
  127. sizeof(struct device_desc_s));
  128. } else {
  129. rc = hwgraph_info_remove_LBL(dev, INFO_LBL_DEVICE_DESC,
  130. (arbitrary_info_t *)&old_device_desc);
  131. }
  132. if (old_device_desc) {
  133. ASSERT(old_device_desc->flags & D_IS_ASSOC);
  134. old_device_desc->flags &= ~D_IS_ASSOC;
  135. device_desc_free(old_device_desc);
  136. }
  137. #endif
  138. FIXME("device_desc_default_set");
  139. }
  140. devfs_handle_t
  141. device_desc_intr_target_get(device_desc_t device_desc)
  142. {
  143. #ifdef LATER
  144. return(device_desc->intr_target);
  145. #else
  146. FIXME("device_desc_intr_target_get");
  147. return((devfs_handle_t)0);
  148. #endif
  149. }
  150. int
  151. device_desc_intr_policy_get(device_desc_t device_desc)
  152. {
  153. #ifdef LATER
  154. return(device_desc->intr_policy);
  155. #else
  156. FIXME("device_desc_intr_policy_get");
  157. return(0);
  158. #endif
  159. }
  160. ilvl_t
  161. device_desc_intr_swlevel_get(device_desc_t device_desc)
  162. {
  163. #ifdef LATER
  164. return(device_desc->intr_swlevel);
  165. #else
  166. FIXME("device_desc_intr_swlevel_get");
  167. return((ilvl_t)0);
  168. #endif
  169. }
  170. char *
  171. device_desc_intr_name_get(device_desc_t device_desc)
  172. {
  173. #ifdef LATER
  174. return(device_desc->intr_name);
  175. #else
  176. FIXME("device_desc_intr_name_get");
  177. return(NULL);
  178. #endif
  179. }
  180. int
  181. device_desc_flags_get(device_desc_t device_desc)
  182. {
  183. #ifdef LATER
  184. return(device_desc->flags);
  185. #else
  186. FIXME("device_desc_flags_get");
  187. return(0);
  188. #endif
  189. }
  190. void
  191. device_desc_intr_target_set(device_desc_t device_desc, devfs_handle_t target)
  192. {
  193. if ( device_desc != (device_desc_t)0 )
  194. device_desc->intr_target = target;
  195. }
  196. void
  197. device_desc_intr_policy_set(device_desc_t device_desc, int policy)
  198. {
  199. if ( device_desc != (device_desc_t)0 )
  200. device_desc->intr_policy = policy;
  201. }
  202. void
  203. device_desc_intr_swlevel_set(device_desc_t device_desc, ilvl_t swlevel)
  204. {
  205. if ( device_desc != (device_desc_t)0 )
  206. device_desc->intr_swlevel = swlevel;
  207. }
  208. void
  209. device_desc_intr_name_set(device_desc_t device_desc, char *name)
  210. {
  211. #ifdef LATER
  212. if ( device_desc != (device_desc_t)0 )
  213. device_desc->intr_name = string_table_insert(&device_desc_string_table, name);
  214. #else
  215. FIXME("device_desc_intr_name_set");
  216. #endif
  217. }
  218. void
  219. device_desc_flags_set(device_desc_t device_desc, int flags)
  220. {
  221. if ( device_desc != (device_desc_t)0 )
  222. device_desc->flags = flags;
  223. }
  224. /*============= device admin registry routines ===================== */
  225. /* Linked list of <admin-name,admin-val> pairs */
  226. typedef struct dev_admin_list_s {
  227. struct dev_admin_list_s *admin_next;  /* next entry in the
  228.  * list 
  229.  */
  230. char *admin_name; /* info label */
  231. char *admin_val; /* actual info */
  232. } dev_admin_list_t;
  233. /* Device/Driver administration registry */
  234. typedef struct dev_admin_registry_s {
  235. mrlock_t reg_lock; /* To allow
  236.  * exclusive
  237.  * access
  238.  */
  239. dev_admin_list_t *reg_first; /* first entry in 
  240.  * the list
  241.  */
  242. dev_admin_list_t **reg_last; /* pointer to the
  243.  * next to last entry
  244.  * in the last which 
  245.  * is also the place
  246.  * where the new
  247.  * entry gets
  248.  * inserted
  249.  */
  250. } dev_admin_registry_t;
  251. /*
  252. ** device_driver_s associates a device driver prefix with device switch entries.
  253. */
  254. struct device_driver_s {
  255. struct device_driver_s *dd_next; /* next element on hash chain */
  256. struct device_driver_s *dd_prev; /* previous element on hash chain */
  257. char *dd_prefix; /* driver prefix string */
  258. struct bdevsw *dd_bdevsw; /* driver's bdevsw */
  259. struct cdevsw *dd_cdevsw; /* driver's cdevsw */
  260. /* driver administration specific data structures need to
  261.  * maintain the list of <driver-paramater,value> pairs
  262.  */
  263. dev_admin_registry_t dd_dev_admin_registry;
  264. ilvl_t dd_thread_pri; /* default thread priority for
  265.  *  all this driver's
  266.  * threads.
  267.  */
  268. };
  269. #define NEW(_p) (_p = kmalloc(sizeof(*_p), GFP_KERNEL))
  270. #define FREE(_p) (kmem_free(_p))
  271. /*
  272.  * helpful lock macros
  273.  */
  274. #define DEV_ADMIN_REGISTRY_INITLOCK(lockp,name) mrinit(lockp,name)
  275. #define DEV_ADMIN_REGISTRY_RDLOCK(lockp) mraccess(lockp)        
  276. #define DEV_ADMIN_REGISTRY_WRLOCK(lockp) mrupdate(lockp)        
  277. #define DEV_ADMIN_REGISTRY_UNLOCK(lockp) mrunlock(lockp)
  278. /* Initialize the registry 
  279.  */
  280. static void
  281. dev_admin_registry_init(dev_admin_registry_t *registry)
  282. {
  283. #ifdef LATER
  284. if ( registry != (dev_admin_registry_t *)0 )
  285. DEV_ADMIN_REGISTRY_INITLOCK(&registry->reg_lock,
  286.     "dev_admin_registry_lock");
  287. registry->reg_first = NULL;
  288. registry->reg_last = &registry->reg_first;
  289. }
  290. #else
  291. FIXME("dev_admin_registry_init");
  292. #endif
  293. }
  294. /*
  295.  * add an <name , value > entry to the dev admin registry.
  296.  * if the name already exists in the registry then change the
  297.  * value iff the new value differs from the old value.
  298.  * if the name doesn't exist a new list entry is created and put
  299.  * at the end.
  300.  */
  301. static void
  302. dev_admin_registry_add(dev_admin_registry_t *registry,
  303.        char *name,
  304.        char *val)
  305. {
  306. #ifdef LATER
  307. dev_admin_list_t *reg_entry;
  308. dev_admin_list_t *scan = 0;
  309. DEV_ADMIN_REGISTRY_WRLOCK(&registry->reg_lock);
  310. /* check if the name already exists in the registry */
  311. scan = registry->reg_first;
  312. while (scan) {
  313. if (strcmp(scan->admin_name,name) == 0) {
  314. /* name is there in the registry */
  315. if (strcmp(scan->admin_val,val)) {
  316. /* old value != new value 
  317.  * reallocate  memory and copy the new value
  318.  */
  319. FREE(scan->admin_val);
  320. scan->admin_val = 
  321. (char *)kern_calloc(1,strlen(val)+1);
  322. strcpy(scan->admin_val,val);
  323. goto out;
  324. }
  325. goto out; /* old value == new value */
  326. }
  327. scan = scan->admin_next;
  328. }
  329. /* name is not there in the registry.
  330.  * allocate memory for the new registry entry 
  331.  */
  332. NEW(reg_entry);
  333. reg_entry->admin_next    = 0;
  334. reg_entry->admin_name = (char *)kern_calloc(1,strlen(name)+1);
  335. strcpy(reg_entry->admin_name,name);
  336. reg_entry->admin_val = (char *)kern_calloc(1,strlen(val)+1);
  337. strcpy(reg_entry->admin_val,val);
  338. /* add the entry at the end of the registry */
  339. *(registry->reg_last) = reg_entry;
  340. registry->reg_last = &reg_entry->admin_next;
  341. out: DEV_ADMIN_REGISTRY_UNLOCK(&registry->reg_lock);
  342. #endif
  343. FIXME("dev_admin_registry_add");
  344. }
  345. /*
  346.  * check if there is an info corr. to a particular
  347.  * name starting from the cursor position in the 
  348.  * registry
  349.  */
  350. static char *
  351. dev_admin_registry_find(dev_admin_registry_t *registry,char *name)
  352. {
  353. #ifdef LATER
  354. dev_admin_list_t *scan = 0;
  355. DEV_ADMIN_REGISTRY_RDLOCK(&registry->reg_lock);
  356. scan = registry->reg_first;
  357. while (scan) {
  358. if (strcmp(scan->admin_name,name) == 0) {
  359. DEV_ADMIN_REGISTRY_UNLOCK(&registry->reg_lock);
  360. return scan->admin_val;
  361. }
  362. scan = scan->admin_next;
  363. }
  364. DEV_ADMIN_REGISTRY_UNLOCK(&registry->reg_lock);
  365. return 0;
  366. #else
  367. FIXME("dev_admin_registry_find");
  368. return(NULL);
  369. #endif
  370. }
  371. /*============= MAIN DEVICE/ DRIVER ADMINISTRATION INTERFACE================ */
  372. /*
  373.  * return any labelled info associated with a device.
  374.  * called by any kernel code including device drivers.
  375.  */
  376. char *
  377. device_admin_info_get(devfs_handle_t dev_vhdl,
  378.       char *info_lbl)
  379. {
  380. #ifdef LATER
  381. char *info = 0;
  382. /* return value need not be GRAPH_SUCCESS as the labelled
  383.  * info may not be present
  384.  */
  385. (void)hwgraph_info_get_LBL(dev_vhdl,info_lbl,
  386.    (arbitrary_info_t *)&info);
  387. return info;
  388. #else
  389. FIXME("device_admin_info_get");
  390. return(NULL);
  391. #endif
  392. }
  393. /*
  394.  * set labelled info associated with a device.
  395.  * called by hwgraph infrastructure . may also be called
  396.  * by device drivers etc.
  397.  */
  398. int
  399. device_admin_info_set(devfs_handle_t dev_vhdl,
  400.       char *dev_info_lbl,
  401.       char *dev_info_val)
  402. {
  403. #ifdef LATER
  404. graph_error_t rv;
  405. arbitrary_info_t old_info;
  406. /* Handle the labelled info
  407.  * intr_target
  408.  * sw_level 
  409.  * in a special way. These are part of device_desc_t
  410.  * Right now this is the only case where we have 
  411.  * a set of related device_admin attributes which 
  412.  * are grouped together.
  413.  * In case there is a need for another set we need to
  414.  * take a more generic approach to solving this.
  415.  * Basically a registry should be implemented. This
  416.  * registry is initialized with the callbacks for the
  417.  * attributes which need to handled in a special way
  418.  * For example:
  419.  * Consider
  420.  *  device_desc
  421.  * intr_target
  422.  * intr_swlevel
  423.  * register "do_intr_target" for intr_target
  424.  * register "do_intr_swlevel" for intr_swlevel.
  425.  * When the device_admin interface layer gets an <attr,val> pair
  426.  * it looks in the registry to see if there is a function registered to
  427.  * handle "attr. If not follow the default path of setting the <attr,val>
  428.  * as labelled information hanging off the vertex.
  429.  * In the above example:
  430.  * "do_intr_target" does what is being done below for the ADMIN_LBL_INTR_TARGET
  431.  * case
  432.  */
  433. if (!strcmp(dev_info_lbl,ADMIN_LBL_INTR_TARGET) ||
  434.     !strcmp(dev_info_lbl,ADMIN_LBL_INTR_SWLEVEL)) {
  435. device_desc_t device_desc;
  436. /* Check if there is a default device descriptor
  437.  * information for this vertex. If not dup one .
  438.  */
  439. if (!(device_desc = device_desc_default_get(dev_vhdl))) {
  440. device_desc = device_desc_dup(dev_vhdl);
  441. device_desc_default_set(dev_vhdl,device_desc);
  442. }
  443. if (!strcmp(dev_info_lbl,ADMIN_LBL_INTR_TARGET)) {
  444. /* Check if a target cpu has been specified
  445.  * for this device by a device administration
  446.  * directive
  447.  */
  448. #ifdef DEBUG
  449. printf(ADMIN_LBL_INTR_TARGET
  450.        " dev = 0x%x "
  451.        "dev_admin_info = %s"
  452.        " target = 0x%xn",
  453.        dev_vhdl,
  454.        dev_info_lbl,
  455.        hwgraph_path_to_vertex(dev_info_val));
  456. #endif
  457. device_desc->intr_target = 
  458. hwgraph_path_to_vertex(dev_info_val);
  459. } else if (!strcmp(dev_info_lbl,ADMIN_LBL_INTR_SWLEVEL)) {
  460. /* Check if the ithread priority level  has been 
  461.  * specified for this device by a device administration
  462.  * directive
  463.  */
  464. #ifdef DEBUG
  465. printf(ADMIN_LBL_INTR_SWLEVEL
  466.        " dev = 0x%x "
  467.        "dev_admin_info = %s"
  468.        " sw level = 0x%xn",
  469.        dev_vhdl,
  470.        dev_info_lbl,
  471.        atoi(dev_info_val));
  472. #endif
  473. device_desc->intr_swlevel = atoi(dev_info_val);
  474. }
  475. }
  476. if (!dev_info_val)
  477. rv = hwgraph_info_remove_LBL(dev_vhdl,
  478.      dev_info_lbl,
  479.      &old_info);
  480. else {
  481. rv = hwgraph_info_add_LBL(dev_vhdl,
  482.   dev_info_lbl,
  483.   (arbitrary_info_t)dev_info_val);
  484. if (rv == GRAPH_DUP)  {
  485. rv = hwgraph_info_replace_LBL(dev_vhdl,
  486.       dev_info_lbl,
  487.       (arbitrary_info_t)dev_info_val,
  488.       &old_info);
  489. }
  490. }
  491. ASSERT(rv == GRAPH_SUCCESS);
  492. #endif
  493. FIXME("device_admin_info_set");
  494. return 0;
  495. }
  496. /*
  497.  * return labelled info associated with a device driver
  498.  * called by kernel code including device drivers
  499.  */
  500. char *
  501. device_driver_admin_info_get(char *driver_prefix,
  502.      char *driver_info_lbl)
  503. {
  504. #ifdef LATER
  505. device_driver_t driver;
  506. driver = device_driver_get(driver_prefix);
  507. return (dev_admin_registry_find(&driver->dd_dev_admin_registry,
  508. driver_info_lbl));
  509. #else
  510. FIXME("device_driver_admin_info_get");
  511. return(NULL);
  512. #endif
  513. }
  514. /*
  515.  * set labelled info associated with a device driver.
  516.  * called by hwgraph infrastructure . may also be called
  517.  * from drivers etc.
  518.  */
  519. int
  520. device_driver_admin_info_set(char *driver_prefix,
  521.      char *driver_info_lbl,
  522.      char *driver_info_val)
  523. {
  524. #ifdef LATER
  525. device_driver_t driver;
  526. driver = device_driver_get(driver_prefix);
  527. dev_admin_registry_add(&driver->dd_dev_admin_registry,
  528.        driver_info_lbl,
  529.        driver_info_val);
  530. #endif
  531. FIXME("device_driver_admin_info_set");
  532. return 0;
  533. }
  534. /*================== device / driver  admin support routines================*/
  535. /* static tables created by lboot */
  536. extern dev_admin_info_t dev_admin_table[];
  537. extern dev_admin_info_t drv_admin_table[];
  538. extern int dev_admin_table_size;
  539. extern int drv_admin_table_size;
  540. /* Extend the device admin table to allow the kernel startup code to 
  541.  * provide some device specific administrative hints
  542.  */
  543. #define ADMIN_TABLE_CHUNK 100
  544. static dev_admin_info_t extended_dev_admin_table[ADMIN_TABLE_CHUNK];
  545. static int extended_dev_admin_table_size = 0;
  546. static mrlock_t extended_dev_admin_table_lock;
  547. /* Initialize the extended device admin table */
  548. void
  549. device_admin_table_init(void)
  550. {
  551. #ifdef LATER
  552. extended_dev_admin_table_size = 0;
  553. mrinit(&extended_dev_admin_table_lock,
  554.        "extended_dev_admin_table_lock");
  555. #endif
  556. FIXME("device_admin_table_init");
  557. }
  558. /* Add <device-name , parameter-name , parameter-value> triple to
  559.  * the extended device administration info table. This is helpful
  560.  * for kernel startup code to put some hints before the hwgraph
  561.  * is setup 
  562.  */
  563. void
  564. device_admin_table_update(char *name,char *label,char *value)
  565. {
  566. #ifdef LATER
  567. dev_admin_info_t *p;
  568. mrupdate(&extended_dev_admin_table_lock);
  569. /* Safety check that we haven't exceeded array limits */
  570. ASSERT(extended_dev_admin_table_size < ADMIN_TABLE_CHUNK);
  571. if (extended_dev_admin_table_size == ADMIN_TABLE_CHUNK)
  572. goto out;
  573. /* Get the pointer to the entry in the table where we are
  574.  * going to put the new information 
  575.  */
  576. p = &extended_dev_admin_table[extended_dev_admin_table_size++];
  577. /* Allocate memory for the strings and copy them in */
  578. p->dai_name = (char *)kern_calloc(1,strlen(name)+1);
  579. strcpy(p->dai_name,name);
  580. p->dai_param_name = (char *)kern_calloc(1,strlen(label)+1);
  581. strcpy(p->dai_param_name,label);
  582. p->dai_param_val = (char *)kern_calloc(1,strlen(value)+1);
  583. strcpy(p->dai_param_val,value);
  584. out: mrunlock(&extended_dev_admin_table_lock);
  585. #endif
  586. FIXME("device_admin_table_update");
  587. }
  588. /* Extend the device driver  admin table to allow the kernel startup code to 
  589.  * provide some device driver specific administrative hints
  590.  */
  591. static dev_admin_info_t extended_drv_admin_table[ADMIN_TABLE_CHUNK];
  592. static int extended_drv_admin_table_size = 0;
  593. mrlock_t extended_drv_admin_table_lock;
  594. /* Initialize the extended device driver admin table */
  595. void
  596. device_driver_admin_table_init(void)
  597. {
  598. #ifdef LATER
  599. extended_drv_admin_table_size = 0;
  600. mrinit(&extended_drv_admin_table_lock,
  601.        "extended_drv_admin_table_lock");
  602. #endif
  603. FIXME("device_driver_admin_table_init");
  604. }
  605. /* Add <device-driver prefix , parameter-name , parameter-value> triple to
  606.  * the extended device administration info table. This is helpful
  607.  * for kernel startup code to put some hints before the hwgraph
  608.  * is setup 
  609.  */
  610. void
  611. device_driver_admin_table_update(char *name,char *label,char *value)
  612. {
  613. #ifdef LATER
  614. dev_admin_info_t *p;
  615. mrupdate(&extended_dev_admin_table_lock);
  616. /* Safety check that we haven't exceeded array limits */
  617. ASSERT(extended_drv_admin_table_size < ADMIN_TABLE_CHUNK);
  618. if (extended_drv_admin_table_size == ADMIN_TABLE_CHUNK)
  619. goto out;
  620. /* Get the pointer to the entry in the table where we are
  621.  * going to put the new information 
  622.  */
  623. p = &extended_drv_admin_table[extended_drv_admin_table_size++];
  624. /* Allocate memory for the strings and copy them in */
  625. p->dai_name = (char *)kern_calloc(1,strlen(name)+1);
  626. strcpy(p->dai_name,name);
  627. p->dai_param_name = (char *)kern_calloc(1,strlen(label)+1);
  628. strcpy(p->dai_param_name,label);
  629. p->dai_param_val = (char *)kern_calloc(1,strlen(value)+1);
  630. strcpy(p->dai_param_val,value);
  631. out: mrunlock(&extended_drv_admin_table_lock);
  632. #endif
  633. FIXME("device_driver_admin_table_update");
  634. }
  635. /*
  636.  * keeps on adding the labelled info for each new (lbl,value) pair
  637.  * that it finds in the static dev admin table (  created by lboot)
  638.  * and the extended dev admin table ( created if at all by the kernel startup
  639.  *  code) corresponding to a device in the hardware graph.
  640.  */
  641. void
  642. device_admin_info_update(devfs_handle_t dev_vhdl)
  643. {
  644. #ifdef LATER
  645. int i = 0;
  646. dev_admin_info_t *scan;
  647. devfs_handle_t scan_vhdl;
  648. /* Check the static device administration info table */
  649. scan = dev_admin_table;
  650. while (i < dev_admin_table_size) {
  651. scan_vhdl = hwgraph_path_to_dev(scan->dai_name);
  652. if (scan_vhdl == dev_vhdl) {
  653. device_admin_info_set(dev_vhdl,
  654.       scan->dai_param_name,
  655.       scan->dai_param_val);
  656. }
  657. if (scan_vhdl != NODEV)
  658. hwgraph_vertex_unref(scan_vhdl);
  659. scan++;i++;
  660. }
  661. i = 0;
  662. /* Check the extended device administration info table */
  663. scan = extended_dev_admin_table;
  664. while (i < extended_dev_admin_table_size) {
  665. scan_vhdl = hwgraph_path_to_dev(scan->dai_name);
  666. if (scan_vhdl == dev_vhdl) {
  667. device_admin_info_set(dev_vhdl,
  668.       scan->dai_param_name,
  669.       scan->dai_param_val);
  670. }
  671. if (scan_vhdl != NODEV)
  672. hwgraph_vertex_unref(scan_vhdl);
  673. scan++;i++;
  674. }
  675. #endif
  676. FIXME("device_admin_info_update");
  677. }
  678. /* looks up the static drv admin table ( created by the lboot) and the extended
  679.  * drv admin table (created if at all by the kernel startup code) 
  680.  * for this driver specific administration info and adds it to the admin info 
  681.  * associated with this device driver's object
  682.  */
  683. void
  684. device_driver_admin_info_update(device_driver_t driver)
  685. {
  686. #ifdef LATER
  687. int i = 0;
  688. dev_admin_info_t *scan;
  689. /* Check the static device driver administration info table */
  690. scan = drv_admin_table;
  691. while (i < drv_admin_table_size) {
  692. if (strcmp(scan->dai_name,driver->dd_prefix) == 0) {
  693. dev_admin_registry_add(&driver->dd_dev_admin_registry,
  694. scan->dai_param_name,
  695.   scan->dai_param_val);
  696. }
  697. scan++;i++;
  698. }
  699. i = 0;
  700. /* Check the extended device driver administration info table */
  701. scan = extended_drv_admin_table;
  702. while (i < extended_drv_admin_table_size) {
  703. if (strcmp(scan->dai_name,driver->dd_prefix) == 0) {
  704. dev_admin_registry_add(&driver->dd_dev_admin_registry,
  705. scan->dai_param_name,
  706.   scan->dai_param_val);
  707. }
  708. scan++;i++;
  709. }
  710. #endif
  711. FIXME("device_driver_admin_info_update");
  712. }
  713. /* =====Device Driver Support===== */
  714. /*
  715. ** Generic device driver support routines for use by kernel modules that
  716. ** deal with device drivers (but NOT for use by the drivers themselves).
  717. ** EVERY registered driver currently in the system -- static or loadable --
  718. ** has an entry in the device_driver_hash table.  A pointer to such an entry
  719. ** serves as a generic device driver handle.
  720. */
  721. #define DEVICE_DRIVER_HASH_SIZE 32
  722. #ifdef LATER
  723. lock_t device_driver_lock[DEVICE_DRIVER_HASH_SIZE];
  724. device_driver_t device_driver_hash[DEVICE_DRIVER_HASH_SIZE];
  725. static struct string_table driver_prefix_string_table;
  726. #endif
  727. /*
  728. ** Initialize device driver infrastructure.
  729. */
  730. void
  731. device_driver_init(void)
  732. {
  733. #ifdef LATER
  734. int i;
  735. extern void alenlist_init(void);
  736. extern void hwgraph_init(void);
  737. extern void device_desc_init(void);
  738. ASSERT(DEVICE_DRIVER_NONE == NULL);
  739. alenlist_init();
  740. hwgraph_init();
  741. device_desc_init();
  742. string_table_init(&driver_prefix_string_table);
  743. for (i=0; i<DEVICE_DRIVER_HASH_SIZE; i++) {
  744. spin_lock_init(&device_driver_lock[i]);
  745. device_driver_hash[i] = NULL;
  746. }
  747. /* Initialize static drivers from master.c table */
  748. for (i=0; i<static_devsw_count; i++) {
  749. device_driver_t driver;
  750. static_device_driver_desc_t desc;
  751. int pri;
  752. desc = &static_device_driver_table[i];
  753. driver = device_driver_get(desc->sdd_prefix);
  754. if (!driver)
  755. driver = device_driver_alloc(desc->sdd_prefix);
  756. pri = device_driver_sysgen_thread_pri_get(desc->sdd_prefix);
  757. device_driver_thread_pri_set(driver, pri);
  758. device_driver_devsw_put(driver, desc->sdd_bdevsw, desc->sdd_cdevsw);
  759. }
  760. #endif
  761. FIXME("device_driver_init");
  762. }
  763. /*
  764. ** Hash a prefix string into a hash table chain.
  765. */
  766. static int
  767. driver_prefix_hash(char *prefix)
  768. {
  769. #ifdef LATER
  770. int accum = 0;
  771. char nextchar;
  772. while (nextchar = *prefix++)
  773. accum = accum ^ nextchar;
  774. return(accum % DEVICE_DRIVER_HASH_SIZE);
  775. #else
  776. FIXME("driver_prefix_hash");
  777. return(0);
  778. #endif
  779. }
  780. /*
  781. ** Allocate a driver handle.
  782. ** Returns the driver handle, or NULL if the driver prefix 
  783. ** already has a handle.
  784. ** 
  785. ** Upper layers prevent races among device_driver_alloc,
  786. ** device_driver_free, and device_driver_get*.
  787. */
  788. device_driver_t
  789. device_driver_alloc(char *prefix)
  790. {
  791. #ifdef LATER
  792. int which_hash;
  793. device_driver_t new_driver;
  794. unsigned long s;
  795. which_hash = driver_prefix_hash(prefix);
  796. new_driver = kern_calloc(1, sizeof(*new_driver));
  797. ASSERT(new_driver != NULL);
  798. new_driver->dd_prev = NULL;
  799. new_driver->dd_prefix = string_table_insert(&driver_prefix_string_table, prefix);
  800. new_driver->dd_bdevsw = NULL;
  801. new_driver->dd_cdevsw = NULL;
  802. dev_admin_registry_init(&new_driver->dd_dev_admin_registry);
  803. device_driver_admin_info_update(new_driver);
  804. s = mutex_spinlock(&device_driver_lock[which_hash]);
  805. #if DEBUG
  806. {
  807. device_driver_t drvscan;
  808. /* Make sure we haven't already added a driver with this prefix */
  809. drvscan = device_driver_hash[which_hash];
  810. while (drvscan && 
  811.         strcmp(drvscan->dd_prefix, prefix)) {
  812. drvscan = drvscan->dd_next;
  813. }
  814. ASSERT(!drvscan);
  815. }
  816. #endif /* DEBUG */
  817. /* Add new_driver to front of hash chain. */
  818. new_driver->dd_next = device_driver_hash[which_hash];
  819. if (new_driver->dd_next)
  820. new_driver->dd_next->dd_prev = new_driver;
  821. device_driver_hash[which_hash] = new_driver;
  822. mutex_spinunlock(&device_driver_lock[which_hash], s);
  823. return(new_driver);
  824. #else
  825. FIXME("device_driver_alloc");
  826. return((device_driver_t)0);
  827. #endif
  828. }
  829. /*
  830. ** Free a driver handle.
  831. **
  832. ** Statically loaded drivers should never device_driver_free.
  833. ** Dynamically loaded drivers device_driver_free when either an
  834. ** unloaded driver is unregistered, or when an unregistered driver
  835. ** is unloaded.
  836. */
  837. void
  838. device_driver_free(device_driver_t driver)
  839. {
  840. #ifdef LATER
  841. int which_hash;
  842. unsigned long s;
  843. if (!driver)
  844. return;
  845. which_hash = driver_prefix_hash(driver->dd_prefix);
  846. s = mutex_spinlock(&device_driver_lock[which_hash]);
  847. #if DEBUG
  848. {
  849. device_driver_t drvscan;
  850. /* Make sure we're dealing with the right list */
  851. drvscan = device_driver_hash[which_hash];
  852. while (drvscan && (drvscan != driver))
  853. drvscan = drvscan->dd_next;
  854. ASSERT(drvscan);
  855. }
  856. #endif /* DEBUG */
  857. if (driver->dd_next)
  858. driver->dd_next->dd_prev = driver->dd_prev;
  859. if (driver->dd_prev)
  860. driver->dd_prev->dd_next = driver->dd_next;
  861. else
  862. device_driver_hash[which_hash] = driver->dd_next;
  863. mutex_spinunlock(&device_driver_lock[which_hash], s);
  864. driver->dd_next = NULL; /* sanity */
  865. driver->dd_prev = NULL; /* sanity */
  866. driver->dd_prefix = NULL; /* sanity */
  867. if (driver->dd_bdevsw) {
  868. driver->dd_bdevsw->d_driver = NULL;
  869. driver->dd_bdevsw = NULL;
  870. }
  871. if (driver->dd_cdevsw) {
  872. if (driver->dd_cdevsw->d_str) {
  873. str_free_mux_node(driver);
  874. }
  875. driver->dd_cdevsw->d_driver = NULL;
  876. driver->dd_cdevsw = NULL;
  877. }
  878. kern_free(driver);
  879. #endif
  880. FIXME("device_driver_free");
  881. }
  882. /*
  883. ** Given a device driver prefix, return a handle to the caller.
  884. */
  885. device_driver_t
  886. device_driver_get(char *prefix)
  887. {
  888. #ifdef LATER
  889. int which_hash;
  890. device_driver_t drvscan;
  891. unsigned long s;
  892. if (prefix == NULL)
  893. return(NULL);
  894. which_hash = driver_prefix_hash(prefix);
  895. s = mutex_spinlock(&device_driver_lock[which_hash]);
  896. drvscan = device_driver_hash[which_hash];
  897. while (drvscan && strcmp(drvscan->dd_prefix, prefix))
  898. drvscan = drvscan->dd_next;
  899. mutex_spinunlock(&device_driver_lock[which_hash], s);
  900. return(drvscan);
  901. #else
  902. FIXME("device_driver_get");
  903. return((device_driver_t)0);
  904. #endif
  905. }
  906. /*
  907. ** Given a block or char special file devfs_handle_t, find the 
  908. ** device driver that controls it.
  909. */
  910. device_driver_t
  911. device_driver_getbydev(devfs_handle_t device)
  912. {
  913. #ifdef LATER
  914. struct bdevsw *my_bdevsw;
  915. struct cdevsw *my_cdevsw;
  916. my_cdevsw = get_cdevsw(device);
  917. if (my_cdevsw != NULL)
  918. return(my_cdevsw->d_driver);
  919. my_bdevsw = get_bdevsw(device);
  920. if (my_bdevsw != NULL)
  921. return(my_bdevsw->d_driver);
  922. #endif
  923. FIXME("device_driver_getbydev");
  924. return((device_driver_t)0);
  925. }
  926. /*
  927. ** Associate a driver with bdevsw/cdevsw pointers.
  928. **
  929. ** Statically loaded drivers are permanently and automatically associated
  930. ** with the proper bdevsw/cdevsw.  Dynamically loaded drivers associate
  931. ** themselves when the driver is registered, and disassociate when the
  932. ** driver unregisters.
  933. **
  934. ** Returns 0 on success, -1 on failure (devsw already associated with driver)
  935. */
  936. int
  937. device_driver_devsw_put(device_driver_t driver,
  938. struct bdevsw *my_bdevsw,
  939. struct cdevsw *my_cdevsw)
  940. {
  941. #ifdef LATER
  942. int i;
  943. if (!driver)
  944. return(-1);
  945. /* Trying to re-register data?  */
  946. if (((my_bdevsw != NULL) && (driver->dd_bdevsw != NULL)) ||
  947.     ((my_cdevsw != NULL) && (driver->dd_cdevsw != NULL)))
  948. return(-1);
  949. if (my_bdevsw != NULL) {
  950. driver->dd_bdevsw = my_bdevsw;
  951. my_bdevsw->d_driver = driver;
  952. for (i = 0; i < bdevmax; i++) {
  953. if (driver->dd_bdevsw->d_flags == bdevsw[i].d_flags) {
  954. bdevsw[i].d_driver = driver;
  955. break;
  956. }
  957. }
  958. }
  959. if (my_cdevsw != NULL) {
  960. driver->dd_cdevsw = my_cdevsw;
  961. my_cdevsw->d_driver = driver;
  962. for (i = 0; i < cdevmax; i++) {
  963. if (driver->dd_cdevsw->d_flags == cdevsw[i].d_flags) {
  964. cdevsw[i].d_driver = driver;
  965. break;
  966. }
  967. }
  968. }
  969. #endif
  970. FIXME("device_driver_devsw_put");
  971. return(0);
  972. }
  973. /*
  974. ** Given a driver, return the corresponding bdevsw and cdevsw pointers.
  975. */
  976. void
  977. device_driver_devsw_get( device_driver_t driver, 
  978. struct bdevsw **bdevswp,
  979. struct cdevsw **cdevswp)
  980. {
  981. if (!driver) {
  982. *bdevswp = NULL;
  983. *cdevswp = NULL;
  984. } else {
  985. *bdevswp = driver->dd_bdevsw;
  986. *cdevswp = driver->dd_cdevsw;
  987. }
  988. }
  989. /*
  990.  * device_driver_thread_pri_set
  991.  * Given a driver try to set its thread priority.
  992.  * Returns 0 on success , -1 on failure.
  993.  */ 
  994. int
  995. device_driver_thread_pri_set(device_driver_t driver,ilvl_t pri)
  996. {
  997. if (!driver)
  998. return(-1);
  999. driver->dd_thread_pri = pri;
  1000. return(0);
  1001. }
  1002. /*
  1003.  * device_driver_thread_pri_get
  1004.  *  Given a driver return the driver thread priority.
  1005.  *  If the driver is NULL return invalid driver thread
  1006.  *  priority.
  1007.  */
  1008. ilvl_t
  1009. device_driver_thread_pri_get(device_driver_t driver)
  1010. {
  1011. if (driver)
  1012. return(driver->dd_thread_pri);
  1013. else
  1014. return(DRIVER_THREAD_PRI_INVALID);
  1015. }
  1016. /*
  1017. ** Given a device driver, return it's handle (prefix).
  1018. */
  1019. void
  1020. device_driver_name_get(device_driver_t driver, char *buffer, int length)
  1021. {
  1022. if (driver == NULL)
  1023. return;
  1024. strncpy(buffer, driver->dd_prefix, length);
  1025. }
  1026. /*
  1027. ** Associate a pointer-sized piece of information with a device.
  1028. */
  1029. void 
  1030. device_info_set(devfs_handle_t device, void *info)
  1031. {
  1032. #ifdef LATER
  1033. hwgraph_fastinfo_set(device, (arbitrary_info_t)info);
  1034. #endif
  1035. FIXME("device_info_set");
  1036. }
  1037. /*
  1038. ** Retrieve a pointer-sized piece of information associated with a device.
  1039. */
  1040. void *
  1041. device_info_get(devfs_handle_t device)
  1042. {
  1043. #ifdef LATER
  1044. return((void *)hwgraph_fastinfo_get(device));
  1045. #else
  1046. FIXME("device_info_get");
  1047. return(NULL);
  1048. #endif
  1049. }
  1050. /*
  1051.  * Find the thread priority for a device, from the various
  1052.  * sysgen files.
  1053.  */
  1054. int
  1055. device_driver_sysgen_thread_pri_get(char *dev_prefix)
  1056. {
  1057. #ifdef LATER
  1058. int pri;
  1059. char *pri_s;
  1060. char *class;
  1061. extern default_intr_pri;
  1062. extern disk_intr_pri;
  1063. extern serial_intr_pri;
  1064. extern parallel_intr_pri;
  1065. extern tape_intr_pri;
  1066. extern graphics_intr_pri;
  1067. extern network_intr_pri;
  1068. extern scsi_intr_pri;
  1069. extern audio_intr_pri;
  1070. extern video_intr_pri;
  1071. extern external_intr_pri;
  1072. extern tserialio_intr_pri;
  1073. /* Check if there is a thread priority specified for
  1074.  * this driver's thread thru admin hints. If so 
  1075.  * use that value. Otherwise set it to its default
  1076.  * class value, otherwise set it to the default
  1077.  * value.
  1078.  */
  1079. if (pri_s = device_driver_admin_info_get(dev_prefix,
  1080. ADMIN_LBL_THREAD_PRI)) {
  1081. pri = atoi(pri_s);
  1082. } else if (class = device_driver_admin_info_get(dev_prefix,
  1083. ADMIN_LBL_THREAD_CLASS)) {
  1084. if (strcmp(class, "disk") == 0)
  1085. pri = disk_intr_pri;
  1086. else if (strcmp(class, "serial") == 0)
  1087. pri = serial_intr_pri;
  1088. else if (strcmp(class, "parallel") == 0)
  1089. pri = parallel_intr_pri;
  1090. else if (strcmp(class, "tape") == 0)
  1091. pri = tape_intr_pri;
  1092. else if (strcmp(class, "graphics") == 0)
  1093. pri = graphics_intr_pri;
  1094. else if (strcmp(class, "network") == 0)
  1095. pri = network_intr_pri;
  1096. else if (strcmp(class, "scsi") == 0)
  1097. pri = scsi_intr_pri;
  1098. else if (strcmp(class, "audio") == 0)
  1099. pri = audio_intr_pri;
  1100. else if (strcmp(class, "video") == 0)
  1101. pri = video_intr_pri;
  1102. else if (strcmp(class, "external") == 0)
  1103. pri = external_intr_pri;
  1104. else if (strcmp(class, "tserialio") == 0)
  1105. pri = tserialio_intr_pri;
  1106. else
  1107. pri = default_intr_pri;
  1108. } else
  1109. pri = default_intr_pri;
  1110. if (pri > 255)
  1111. pri = 255;
  1112. else if (pri < 0)
  1113. pri = 0;
  1114. return pri;
  1115. #else
  1116. FIXME("device_driver_sysgen_thread_pri_get");
  1117. return(-1);
  1118. #endif
  1119. }