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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * IEEE 1394 for Linux
  3.  *
  4.  * Low level (host adapter) management.
  5.  *
  6.  * Copyright (C) 1999 Andreas E. Bombe
  7.  * Copyright (C) 1999 Emanuel Pirker
  8.  *
  9.  * This code is licensed under the GPL.  See the file COPYING in the root
  10.  * directory of the kernel sources for details.
  11.  */
  12. #include <linux/config.h>
  13. #include <linux/types.h>
  14. #include <linux/init.h>
  15. #include <linux/vmalloc.h>
  16. #include <linux/wait.h>
  17. #include "ieee1394_types.h"
  18. #include "hosts.h"
  19. #include "ieee1394_core.h"
  20. #include "highlevel.h"
  21. static LIST_HEAD(templates);
  22. static spinlock_t templates_lock = SPIN_LOCK_UNLOCKED;
  23. /*
  24.  * This function calls the add_host/remove_host hooks for every host currently
  25.  * registered.  Init == TRUE means add_host.
  26.  */
  27. void hl_all_hosts(struct hpsb_highlevel *hl, int init)
  28. {
  29. struct list_head *tlh, *hlh;
  30.         struct hpsb_host_template *tmpl;
  31.         struct hpsb_host *host;
  32.         spin_lock(&templates_lock);
  33. list_for_each(tlh, &templates) {
  34.                 tmpl = list_entry(tlh, struct hpsb_host_template, list);
  35. list_for_each(hlh, &tmpl->hosts) {
  36. host = list_entry(hlh, struct hpsb_host, list);
  37.                         if (host->initialized) {
  38.                                 if (init) {
  39.                                         if (hl->op->add_host) {
  40.                                                 hl->op->add_host(host);
  41.                                         }
  42.                                 } else {
  43.                                         if (hl->op->remove_host) {
  44.                                                 hl->op->remove_host(host);
  45.                                         }
  46.                                 }
  47.                         }
  48.                 }
  49.         }
  50.         spin_unlock(&templates_lock);
  51. }
  52. int hpsb_inc_host_usage(struct hpsb_host *host)
  53. {
  54. struct list_head *tlh, *hlh;
  55.         struct hpsb_host_template *tmpl;
  56.         int retval = 0;
  57. unsigned long flags;
  58.         spin_lock_irqsave(&templates_lock, flags);
  59. list_for_each(tlh, &templates) {
  60.                 tmpl = list_entry(tlh, struct hpsb_host_template, list);
  61. list_for_each(hlh, &tmpl->hosts) {
  62. if (host == list_entry(hlh, struct hpsb_host, list)) {
  63.                                 tmpl->devctl(host, MODIFY_USAGE, 1);
  64.                                 retval = 1;
  65.                                 break;
  66.                         }
  67.                 }
  68. if (retval)
  69. break;
  70.         }
  71.         spin_unlock_irqrestore(&templates_lock, flags);
  72.         return retval;
  73. }
  74. void hpsb_dec_host_usage(struct hpsb_host *host)
  75. {
  76.         host->template->devctl(host, MODIFY_USAGE, 0);
  77. }
  78. /*
  79.  * The following function is exported for module usage.  It will be called from
  80.  * the detect function of a adapter driver.
  81.  */
  82. struct hpsb_host *hpsb_get_host(struct hpsb_host_template *tmpl, 
  83.                                 size_t hd_size)
  84. {
  85.         struct hpsb_host *h;
  86.         h = vmalloc(sizeof(struct hpsb_host) + hd_size);
  87.         if (!h) return NULL;
  88.         memset(h, 0, sizeof(struct hpsb_host) + hd_size);
  89.         atomic_set(&h->generation, 0);
  90.         INIT_LIST_HEAD(&h->pending_packets);
  91.         spin_lock_init(&h->pending_pkt_lock);
  92.         sema_init(&h->tlabel_count, 64);
  93.         spin_lock_init(&h->tlabel_lock);
  94. INIT_TQUEUE(&h->timeout_tq, (void (*)(void*))abort_timedouts, h);
  95.         h->topology_map = h->csr.topology_map + 3;
  96.         h->speed_map = (u8 *)(h->csr.speed_map + 2);
  97.         h->template = tmpl;
  98.         if (hd_size)
  99.                 h->hostdata = &h->embedded_hostdata[0];
  100. list_add_tail(&h->list, &tmpl->hosts);
  101.         return h;
  102. }
  103. static void free_all_hosts(struct hpsb_host_template *tmpl)
  104. {
  105. struct list_head *hlh, *next;
  106.         struct hpsb_host *host;
  107. list_for_each_safe(hlh, next, &tmpl->hosts) {
  108. host = list_entry(hlh, struct hpsb_host, list);
  109.                 vfree(host);
  110.         }
  111. }
  112. static void init_hosts(struct hpsb_host_template *tmpl)
  113. {
  114.         int count;
  115. struct list_head *hlh;
  116.         struct hpsb_host *host;
  117.         count = tmpl->detect_hosts(tmpl);
  118. list_for_each(hlh, &tmpl->hosts) {
  119. host = list_entry(hlh, struct hpsb_host, list);
  120.                 if (tmpl->initialize_host(host)) {
  121.                         host->initialized = 1;
  122.                         highlevel_add_host(host);
  123.                         hpsb_reset_bus(host, LONG_RESET);
  124.                 }
  125.         }
  126.         tmpl->number_of_hosts = count;
  127.         HPSB_INFO("detected %d %s adapter%s", count, tmpl->name,
  128.                   (count != 1 ? "s" : ""));
  129. }
  130. static void shutdown_hosts(struct hpsb_host_template *tmpl)
  131. {
  132. struct list_head *hlh;
  133.         struct hpsb_host *host;
  134. list_for_each(hlh, &tmpl->hosts) {
  135. host = list_entry(hlh, struct hpsb_host, list);
  136.                 if (host->initialized) {
  137.                         highlevel_remove_host(host);
  138.                         host->initialized = 0;
  139.                         abort_requests(host);
  140.                         tmpl->release_host(host);
  141.                         while (test_bit(0, &host->timeout_tq.sync)) {
  142.                                 schedule();
  143.                         }
  144.                 }
  145.         }
  146.         free_all_hosts(tmpl);
  147.         tmpl->release_host(NULL);
  148.         tmpl->number_of_hosts = 0;
  149. }
  150. /*
  151.  * The following two functions are exported symbols for module usage.
  152.  */
  153. int hpsb_register_lowlevel(struct hpsb_host_template *tmpl)
  154. {
  155. INIT_LIST_HEAD(&tmpl->hosts);
  156. tmpl->number_of_hosts = 0;
  157.         spin_lock(&templates_lock);
  158. list_add_tail(&tmpl->list, &templates);
  159.         spin_unlock(&templates_lock);
  160. /* PCI cards should be smart and use the PCI detection layer, and
  161.  * not this one shot deal. detect_hosts() will be obsoleted soon. */
  162. if (tmpl->detect_hosts != NULL) {
  163. HPSB_DEBUG("Registered %s driver, initializing now", tmpl->name);
  164. init_hosts(tmpl);
  165. }
  166.         return 0;
  167. }
  168. void hpsb_unregister_lowlevel(struct hpsb_host_template *tmpl)
  169. {
  170.         shutdown_hosts(tmpl);
  171.         if (tmpl->number_of_hosts)
  172.                 HPSB_PANIC("attempted to remove busy host template "
  173.    "of %s at address 0x%p", tmpl->name, tmpl);
  174. else {
  175. spin_lock(&templates_lock);
  176. list_del(&tmpl->list);
  177. spin_unlock(&templates_lock);
  178. }
  179. }