labelcl.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:14k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*  labelcl - SGI's Hwgraph Compatibility Layer.
  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) 2001 Silicon Graphics, Inc.  All rights reserved.
  8. */
  9. #include <linux/types.h>
  10. #include <linux/slab.h>
  11. #include <asm/sn/sgi.h>
  12. #include <linux/devfs_fs.h>
  13. #include <linux/devfs_fs_kernel.h>
  14. #include <asm/sn/invent.h>
  15. #include <asm/sn/hcl.h>
  16. #include <asm/sn/labelcl.h>
  17. /*
  18. ** Very simple and dumb string table that supports only find/insert.
  19. ** In practice, if this table gets too large, we may need a more
  20. ** efficient data structure.   Also note that currently there is no 
  21. ** way to delete an item once it's added.  Therefore, name collision 
  22. ** will return an error.
  23. */
  24. struct string_table label_string_table;
  25. /*
  26.  * string_table_init - Initialize the given string table.
  27.  */
  28. void
  29. string_table_init(struct string_table *string_table)
  30. {
  31. string_table->string_table_head = NULL;
  32. string_table->string_table_generation = 0;
  33. /*
  34.  * We nedd to initialize locks here!
  35.  */
  36. return;
  37. }
  38. /*
  39.  * string_table_destroy - Destroy the given string table.
  40.  */
  41. void
  42. string_table_destroy(struct string_table *string_table)
  43. {
  44. struct string_table_item *item, *next_item;
  45. item = string_table->string_table_head;
  46. while (item) {
  47. next_item = item->next;
  48. STRTBL_FREE(item);
  49. item = next_item;
  50. }
  51. /*
  52.  * We need to destroy whatever lock we have here
  53.  */
  54. return;
  55. }
  56. /*
  57.  * string_table_insert - Insert an entry in the string table .. duplicate 
  58.  * names are not allowed.
  59.  */
  60. char *
  61. string_table_insert(struct string_table *string_table, char *name)
  62. {
  63. struct string_table_item *item, *new_item = NULL, *last_item = NULL;
  64. again:
  65. /*
  66.  * Need to lock the table ..
  67.  */
  68. item = string_table->string_table_head;
  69. last_item = NULL;
  70. while (item) {
  71. if (!strcmp(item->string, name)) {
  72. /*
  73.  * If we allocated space for the string and the found that
  74.  * someone else already entered it into the string table,
  75.  * free the space we just allocated.
  76.  */
  77. if (new_item)
  78. STRTBL_FREE(new_item);
  79. /*
  80.  * Search optimization: move the found item to the head
  81.  * of the list.
  82.  */
  83. if (last_item != NULL) {
  84. last_item->next = item->next;
  85. item->next = string_table->string_table_head;
  86. string_table->string_table_head = item;
  87. }
  88. goto out;
  89. }
  90. last_item = item;
  91. item=item->next;
  92. }
  93. /*
  94.  * name was not found, so add it to the string table.
  95.  */
  96. if (new_item == NULL) {
  97. long old_generation = string_table->string_table_generation;
  98. new_item = STRTBL_ALLOC(strlen(name));
  99. strcpy(new_item->string, name);
  100. /*
  101.  * While we allocated memory for the new string, someone else 
  102.  * changed the string table.
  103.  */
  104. if (old_generation != string_table->string_table_generation) {
  105. goto again;
  106. }
  107. } else {
  108. /* At this we only have the string table lock in access mode.
  109.  * Promote the access lock to an update lock for the string
  110.  * table insertion below.
  111.  */
  112. long old_generation = 
  113. string_table->string_table_generation;
  114. /*
  115.  * After we did the unlock and wer waiting for update
  116.  * lock someone could have potentially updated
  117.  * the string table. Check the generation number
  118.  * for this case. If it is the case we have to
  119.  * try all over again.
  120.  */
  121. if (old_generation != 
  122.     string_table->string_table_generation) {
  123. goto again;
  124. }
  125. }
  126. /*
  127.  * At this point, we're committed to adding new_item to the string table.
  128.  */
  129. new_item->next = string_table->string_table_head;
  130. item = string_table->string_table_head = new_item;
  131. string_table->string_table_generation++;
  132. out:
  133. /*
  134.  * Need to unlock here.
  135.  */
  136. return(item->string);
  137. }
  138. /*
  139.  * labelcl_info_create - Creates the data structure that will hold the
  140.  * device private information asscoiated with a devfs entry.
  141.  * The pointer to this structure is what gets stored in the devfs 
  142.  * (void * info).
  143.  */
  144. labelcl_info_t *
  145. labelcl_info_create()
  146. {
  147. labelcl_info_t *new = NULL;
  148. /* Initial allocation does not include any area for labels */
  149. if ( ( new = (labelcl_info_t *)kmalloc (sizeof(labelcl_info_t), GFP_KERNEL) ) == NULL )
  150. return NULL;
  151. memset (new, 0, sizeof(labelcl_info_t));
  152. new->hwcl_magic = LABELCL_MAGIC;
  153. return( new);
  154. }
  155. /*
  156.  * labelcl_info_destroy - Frees the data structure that holds the
  157.  *      device private information asscoiated with a devfs entry.  This 
  158.  * data structure was created by device_info_create().
  159.  *
  160.  * The caller is responsible for nulling the (void *info) in the 
  161.  * corresponding devfs entry.
  162.  */
  163. int
  164. labelcl_info_destroy(labelcl_info_t *labelcl_info)
  165. {
  166. if (labelcl_info == NULL)
  167. return(0);
  168. /* Free the label list */
  169. if (labelcl_info->label_list)
  170. kfree(labelcl_info->label_list);
  171. /* Now free the label info area */
  172. labelcl_info->hwcl_magic = 0;
  173. kfree(labelcl_info);
  174. return(0);
  175. }
  176. /*
  177.  * labelcl_info_add_LBL - Adds a new label entry in the labelcl info 
  178.  * structure.
  179.  *
  180.  * Error is returned if we find another label with the same name.
  181.  */
  182. int
  183. labelcl_info_add_LBL(devfs_handle_t de,
  184. char *info_name,
  185. arb_info_desc_t info_desc,
  186. arbitrary_info_t info)
  187. {
  188. labelcl_info_t *labelcl_info = NULL;
  189. int num_labels;
  190. int new_label_list_size;
  191. label_info_t *old_label_list, *new_label_list = NULL;
  192. char *name;
  193. int i;
  194. if (de == NULL)
  195. return(-1);
  196.         labelcl_info = devfs_get_info(de);
  197. if (labelcl_info == NULL)
  198. return(-1);
  199. if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
  200. return(-1);
  201. if (info_name == NULL)
  202. return(-1);
  203. if (strlen(info_name) >= LABEL_LENGTH_MAX)
  204. return(-1);
  205. name = string_table_insert(&label_string_table, info_name);
  206. num_labels = labelcl_info->num_labels;
  207. new_label_list_size = sizeof(label_info_t) * (num_labels+1);
  208. /*
  209.  * Create a new label info area.
  210.  */
  211. if (new_label_list_size != 0) {
  212. new_label_list = (label_info_t *) kmalloc(new_label_list_size, GFP_KERNEL);
  213. if (new_label_list == NULL)
  214. return(-1);
  215. }
  216. /*
  217.  * At this point, we are committed to adding the labelled info, 
  218.  * if there isn't already information there with the same name.
  219.  */
  220. old_label_list = labelcl_info->label_list;
  221. /* 
  222.  * Look for matching info name.
  223.  */
  224. for (i=0; i<num_labels; i++) {
  225. if (!strcmp(info_name, old_label_list[i].name)) {
  226. /* Not allowed to add duplicate labelled info names. */
  227. kfree(new_label_list);
  228. printk(KERN_WARNING "labelcl_info_add_LBL: Duplicate label name %s for vertex 0x%pn", info_name, (void *)de);
  229. return(-1);
  230. }
  231. new_label_list[i] = old_label_list[i]; /* structure copy */
  232. }
  233. new_label_list[num_labels].name = name;
  234. new_label_list[num_labels].desc = info_desc;
  235. new_label_list[num_labels].info = info;
  236. labelcl_info->num_labels = num_labels+1;
  237. labelcl_info->label_list = new_label_list;
  238. if (old_label_list != NULL)
  239. kfree(old_label_list);
  240. return(0);
  241. }
  242. /*
  243.  * labelcl_info_remove_LBL - Remove a label entry.
  244.  */
  245. int
  246. labelcl_info_remove_LBL(devfs_handle_t de,
  247.  char *info_name,
  248.  arb_info_desc_t *info_desc,
  249.  arbitrary_info_t *info)
  250. {
  251. labelcl_info_t *labelcl_info = NULL;
  252. int num_labels;
  253. int new_label_list_size;
  254. label_info_t *old_label_list, *new_label_list = NULL;
  255. arb_info_desc_t label_desc_found;
  256. arbitrary_info_t label_info_found;
  257. int i;
  258. if (de == NULL)
  259. return(-1);
  260. labelcl_info = devfs_get_info(de);
  261. if (labelcl_info == NULL)
  262. return(-1);
  263. if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
  264. return(-1);
  265. num_labels = labelcl_info->num_labels;
  266. if (num_labels == 0) {
  267. return(-1);
  268. }
  269. /*
  270.  * Create a new info area.
  271.  */
  272. new_label_list_size = sizeof(label_info_t) * (num_labels-1);
  273. if (new_label_list_size) {
  274. new_label_list = (label_info_t *) kmalloc(new_label_list_size, GFP_KERNEL);
  275. if (new_label_list == NULL)
  276. return(-1);
  277. }
  278. /*
  279.  * At this point, we are committed to removing the labelled info, 
  280.  * if it still exists.
  281.  */
  282. old_label_list = labelcl_info->label_list;
  283. /* 
  284.  * Find matching info name.
  285.  */
  286. for (i=0; i<num_labels; i++) {
  287. if (!strcmp(info_name, old_label_list[i].name)) {
  288. label_desc_found = old_label_list[i].desc;
  289. label_info_found = old_label_list[i].info;
  290. goto found;
  291. }
  292. if (i < num_labels-1) /* avoid walking off the end of the new vertex */
  293. new_label_list[i] = old_label_list[i]; /* structure copy */
  294. }
  295. /* The named info doesn't exist. */
  296. if (new_label_list)
  297. kfree(new_label_list);
  298. return(-1);
  299. found:
  300. /* Finish up rest of labelled info */
  301. for (i=i+1; i<num_labels; i++)
  302. new_label_list[i-1] = old_label_list[i]; /* structure copy */
  303. labelcl_info->num_labels = num_labels+1;
  304. labelcl_info->label_list = new_label_list;
  305. kfree(old_label_list);
  306. if (info != NULL)
  307. *info = label_info_found;
  308. if (info_desc != NULL)
  309. *info_desc = label_desc_found;
  310. return(0);
  311. }
  312. /*
  313.  * labelcl_info_replace_LBL - Replace an existing label entry with the 
  314.  * given new information.
  315.  *
  316.  * Label entry must exist.
  317.  */
  318. int
  319. labelcl_info_replace_LBL(devfs_handle_t de,
  320. char *info_name,
  321. arb_info_desc_t info_desc,
  322. arbitrary_info_t info,
  323. arb_info_desc_t *old_info_desc,
  324. arbitrary_info_t *old_info)
  325. {
  326. labelcl_info_t *labelcl_info = NULL;
  327. int num_labels;
  328. label_info_t *label_list;
  329. int i;
  330. if (de == NULL)
  331. return(-1);
  332. labelcl_info = devfs_get_info(de);
  333. if (labelcl_info == NULL)
  334. return(-1);
  335. if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
  336. return(-1);
  337. num_labels = labelcl_info->num_labels;
  338. if (num_labels == 0) {
  339. return(-1);
  340. }
  341. if (info_name == NULL)
  342. return(-1);
  343. label_list = labelcl_info->label_list;
  344. /* 
  345.  * Verify that information under info_name already exists.
  346.  */
  347. for (i=0; i<num_labels; i++)
  348. if (!strcmp(info_name, label_list[i].name)) {
  349. if (old_info != NULL)
  350. *old_info = label_list[i].info;
  351. if (old_info_desc != NULL)
  352. *old_info_desc = label_list[i].desc;
  353. label_list[i].info = info;
  354. label_list[i].desc = info_desc;
  355. return(0);
  356. }
  357. return(-1);
  358. }
  359. /*
  360.  * labelcl_info_get_LBL - Retrieve and return the information for the 
  361.  * given label entry.
  362.  */
  363. int
  364. labelcl_info_get_LBL(devfs_handle_t de,
  365.       char *info_name,
  366.       arb_info_desc_t *info_desc,
  367.       arbitrary_info_t *info)
  368. {
  369. labelcl_info_t *labelcl_info = NULL;
  370. int num_labels;
  371. label_info_t *label_list;
  372. int i;
  373. if (de == NULL)
  374. return(-1);
  375. labelcl_info = devfs_get_info(de);
  376. if (labelcl_info == NULL)
  377. return(-1);
  378. if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
  379. return(-1);
  380. num_labels = labelcl_info->num_labels;
  381. if (num_labels == 0) {
  382. return(-1);
  383. }
  384. label_list = labelcl_info->label_list;
  385. /* 
  386.  * Find information under info_name.
  387.  */
  388. for (i=0; i<num_labels; i++)
  389. if (!strcmp(info_name, label_list[i].name)) {
  390. if (info != NULL)
  391. *info = label_list[i].info;
  392. if (info_desc != NULL)
  393. *info_desc = label_list[i].desc;
  394. return(0);
  395. }
  396. return(-1);
  397. }
  398. /*
  399.  * labelcl_info_get_next_LBL - returns the next label entry on the list.
  400.  */
  401. int
  402. labelcl_info_get_next_LBL(devfs_handle_t de,
  403.    char *buffer,
  404.    arb_info_desc_t *info_descp,
  405.    arbitrary_info_t *infop,
  406.    labelcl_info_place_t *placeptr)
  407. {
  408. labelcl_info_t *labelcl_info = NULL;
  409. uint which_info;
  410. label_info_t *label_list;
  411. if ((buffer == NULL) && (infop == NULL))
  412. return(-1);
  413. if (placeptr == NULL)
  414. return(-1);
  415. if (de == NULL)
  416. return(-1);
  417. labelcl_info = devfs_get_info(de);
  418. if (labelcl_info == NULL)
  419. return(-1);
  420. if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
  421. return(-1);
  422. which_info = *placeptr;
  423. if (which_info >= labelcl_info->num_labels) {
  424. return(-1);
  425. }
  426. label_list = (label_info_t *) labelcl_info->label_list;
  427. if (buffer != NULL)
  428. strcpy(buffer, label_list[which_info].name);
  429. if (infop)
  430. *infop = label_list[which_info].info;
  431. if (info_descp)
  432. *info_descp = label_list[which_info].desc;
  433. *placeptr = which_info + 1;
  434. return(0);
  435. }
  436. int
  437. labelcl_info_replace_IDX(devfs_handle_t de,
  438. int index,
  439. arbitrary_info_t info,
  440. arbitrary_info_t *old_info)
  441. {
  442. arbitrary_info_t *info_list_IDX;
  443. labelcl_info_t *labelcl_info = NULL;
  444. if (de == NULL) {
  445. printk(KERN_ALERT "labelcl: NULL devfs handle given.n");
  446. return(-1);
  447. }
  448. labelcl_info = devfs_get_info(de);
  449. if (labelcl_info == NULL) {
  450. printk(KERN_ALERT "labelcl: Entry does not have info pointer.n");
  451. return(-1);
  452. }
  453. if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
  454. return(-1);
  455. if ( (index < 0) || (index >= HWGRAPH_NUM_INDEX_INFO) )
  456. return(-1);
  457. /*
  458.  * Replace information at the appropriate index in this vertex with 
  459.  * the new info.
  460.  */
  461. info_list_IDX = labelcl_info->IDX_list;
  462. if (old_info != NULL)
  463. *old_info = info_list_IDX[index];
  464. info_list_IDX[index] = info;
  465. return(0);
  466. }
  467. /*
  468.  * labelcl_info_connectpt_set - Sets the connectpt.
  469.  */
  470. int
  471. labelcl_info_connectpt_set(struct devfs_entry *de,
  472.   struct devfs_entry *connect_de)
  473. {
  474. arbitrary_info_t old_info;
  475. int rv;
  476. rv = labelcl_info_replace_IDX(de, HWGRAPH_CONNECTPT, 
  477. (arbitrary_info_t) connect_de, &old_info);
  478. if (rv) {
  479. return(rv);
  480. }
  481. return(0);
  482. }
  483. /*
  484.  * labelcl_info_get_IDX - Returns the information pointed at by index.
  485.  *
  486.  */
  487. int
  488. labelcl_info_get_IDX(devfs_handle_t de,
  489. int index,
  490. arbitrary_info_t *info)
  491. {
  492. arbitrary_info_t *info_list_IDX;
  493. labelcl_info_t *labelcl_info = NULL;
  494. if (de == NULL)
  495. return(-1);
  496. labelcl_info = devfs_get_info(de);
  497. if (labelcl_info == NULL)
  498. return(-1);
  499. if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
  500. return(-1);
  501. if ( (index < 0) || (index >= HWGRAPH_NUM_INDEX_INFO) )
  502. return(-1);
  503. /*
  504.  * Return information at the appropriate index in this vertex.
  505.  */
  506. info_list_IDX = labelcl_info->IDX_list;
  507. if (info != NULL)
  508. *info = info_list_IDX[index];
  509. return(0);
  510. }
  511. /*
  512.  * labelcl_info_connectpt_get - Retrieve the connect point for a device entry.
  513.  */
  514. struct devfs_entry *
  515. labelcl_info_connectpt_get(struct devfs_entry *de)
  516. {
  517. int rv;
  518. arbitrary_info_t info;
  519. rv = labelcl_info_get_IDX(de, HWGRAPH_CONNECTPT, &info);
  520. if (rv)
  521. return(NULL);
  522. return((struct devfs_entry *)info);
  523. }