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

嵌入式Linux

开发平台:

Unix_Linux

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