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

嵌入式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/slab.h>
  12. #include <asm/sn/sgi.h>
  13. #include <asm/sn/iobus.h>
  14. #include <asm/sn/iograph.h>
  15. #include <asm/sn/invent.h>
  16. #include <asm/sn/hcl.h>
  17. #include <asm/sn/labelcl.h>
  18. #include <asm/sn/xtalk/xtalk.h>
  19. #include <asm/sn/xtalk/xswitch.h>
  20. #include <asm/sn/xtalk/xwidget.h>
  21. #include <asm/sn/xtalk/xtalk_private.h>
  22. #define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))
  23. #define DEL(ptr) (kfree(ptr))
  24. int                     xswitch_devflag = D_MP;
  25. /*
  26.  * This file provides generic support for Crosstalk
  27.  * Switches, in a way that insulates crosstalk providers
  28.  * from specifics about the switch chips being used.
  29.  */
  30. #include <asm/sn/xtalk/xbow.h>
  31. #define DEV_FUNC(dev,func)      xbow_##func
  32. #if !defined(DEV_FUNC)
  33. /*
  34.  * There is more than one possible provider
  35.  * for this platform. We need to examine the
  36.  * master vertex of the current vertex for
  37.  * a provider function structure, and indirect
  38.  * through the appropriately named member.
  39.  */
  40. #define DEV_FUNC(dev,func) xwidget_to_provider_fns(dev)->func
  41. static xswitch_provider_t *
  42. xwidget_to_provider_fns(devfs_handle_t xconn)
  43. {
  44.     devfs_handle_t            busv;
  45.     xswitch_info_t          xswitch_info;
  46.     xswitch_provider_t      provider_fns;
  47.     busv = hwgraph_connectpt_get(xconn_vhdl);
  48.     ASSERT(busv != GRAPH_VERTEX_NONE);
  49.     xswitch_info = xswitch_info_get(busv);
  50.     ASSERT(xswitch_info != NULL);
  51.     provider_fns = xswitch_info->xswitch_fns;
  52.     ASSERT(provider_fns != NULL);
  53.     return provider_fns;
  54. }
  55. #endif
  56. #define XSWITCH_CENSUS_BIT(port) (1<<(port))
  57. #define XSWITCH_CENSUS_PORT_MIN (0x0)
  58. #define XSWITCH_CENSUS_PORT_MAX (0xF)
  59. #define XSWITCH_CENSUS_PORTS (0x10)
  60. #define XSWITCH_WIDGET_PRESENT(infop,port) ((infop)->census & XSWITCH_CENSUS_BIT(port))
  61. static char             xswitch_info_fingerprint[] = "xswitch_info";
  62. struct xswitch_info_s {
  63.     char                   *fingerprint;
  64.     unsigned                census;
  65.     devfs_handle_t            vhdl[XSWITCH_CENSUS_PORTS];
  66.     devfs_handle_t            master_vhdl[XSWITCH_CENSUS_PORTS];
  67.     xswitch_provider_t     *xswitch_fns;
  68. };
  69. xswitch_info_t
  70. xswitch_info_get(devfs_handle_t xwidget)
  71. {
  72.     xswitch_info_t          xswitch_info;
  73.     xswitch_info = (xswitch_info_t)
  74. hwgraph_fastinfo_get(xwidget);
  75. #ifdef LATER
  76.     if ((xswitch_info != NULL) &&
  77. (xswitch_info->fingerprint != xswitch_info_fingerprint))
  78. #ifdef SUPPORT_PRINTING_V_FORMAT
  79. PRINT_PANIC("%v xswitch_info_get bad fingerprint", xwidget);
  80. #else
  81. PRINT_PANIC("%x xswitch_info_get bad fingerprint", xwidget);
  82. #endif
  83. #endif /* LATER */
  84.     return (xswitch_info);
  85. }
  86. void
  87. xswitch_info_vhdl_set(xswitch_info_t xswitch_info,
  88.       xwidgetnum_t port,
  89.       devfs_handle_t xwidget)
  90. {
  91. #if XSWITCH_CENSUS_PORT_MIN
  92.     if (port < XSWITCH_CENSUS_PORT_MIN)
  93. return;
  94. #endif
  95.     if (port > XSWITCH_CENSUS_PORT_MAX)
  96. return;
  97.     xswitch_info->vhdl[port - XSWITCH_CENSUS_PORT_MIN] = xwidget;
  98. }
  99. devfs_handle_t
  100. xswitch_info_vhdl_get(xswitch_info_t xswitch_info,
  101.       xwidgetnum_t port)
  102. {
  103. #ifdef LATER
  104.     if (xswitch_info == NULL)
  105. PRINT_PANIC("xswitch_info_vhdl_get: null xswitch_info");
  106. #endif
  107. #if XSWITCH_CENSUS_PORT_MIN
  108.     if (port < XSWITCH_CENSUS_PORT_MIN)
  109. return GRAPH_VERTEX_NONE;
  110. #endif
  111.     if (port > XSWITCH_CENSUS_PORT_MAX)
  112. return GRAPH_VERTEX_NONE;
  113.     return xswitch_info->vhdl[port - XSWITCH_CENSUS_PORT_MIN];
  114. }
  115. /*
  116.  * Some systems may allow for multiple switch masters.  On such systems,
  117.  * we assign a master for each port on the switch.  These interfaces
  118.  * establish and retrieve that assignment.
  119.  */
  120. void
  121. xswitch_info_master_assignment_set(xswitch_info_t xswitch_info,
  122.    xwidgetnum_t port,
  123.    devfs_handle_t master_vhdl)
  124. {
  125. #if XSWITCH_CENSUS_PORT_MIN
  126.     if (port < XSWITCH_CENSUS_PORT_MIN)
  127. return;
  128. #endif
  129.     if (port > XSWITCH_CENSUS_PORT_MAX)
  130. return;
  131.     xswitch_info->master_vhdl[port - XSWITCH_CENSUS_PORT_MIN] = master_vhdl;
  132. }
  133. devfs_handle_t
  134. xswitch_info_master_assignment_get(xswitch_info_t xswitch_info,
  135.    xwidgetnum_t port)
  136. {
  137. #if XSWITCH_CENSUS_PORT_MIN
  138.     if (port < XSWITCH_CENSUS_PORT_MIN)
  139. return GRAPH_VERTEX_NONE;
  140. #endif
  141.     if (port > XSWITCH_CENSUS_PORT_MAX)
  142. return GRAPH_VERTEX_NONE;
  143.     return xswitch_info->master_vhdl[port - XSWITCH_CENSUS_PORT_MIN];
  144. }
  145. void
  146. xswitch_info_set(devfs_handle_t xwidget, xswitch_info_t xswitch_info)
  147. {
  148.     xswitch_info->fingerprint = xswitch_info_fingerprint;
  149.     hwgraph_fastinfo_set(xwidget, (arbitrary_info_t) xswitch_info);
  150. }
  151. xswitch_info_t
  152. xswitch_info_new(devfs_handle_t xwidget)
  153. {
  154.     xswitch_info_t          xswitch_info;
  155.     xswitch_info = xswitch_info_get(xwidget);
  156.     if (xswitch_info == NULL) {
  157. int                     port;
  158. NEW(xswitch_info);
  159. xswitch_info->census = 0;
  160. for (port = XSWITCH_CENSUS_PORT_MIN;
  161.      port <= XSWITCH_CENSUS_PORT_MAX;
  162.      port++) {
  163.     xswitch_info_vhdl_set(xswitch_info, port,
  164.   GRAPH_VERTEX_NONE);
  165.     xswitch_info_master_assignment_set(xswitch_info,
  166.        port,
  167.        GRAPH_VERTEX_NONE);
  168. }
  169. xswitch_info_set(xwidget, xswitch_info);
  170.     }
  171.     return xswitch_info;
  172. }
  173. void
  174. xswitch_provider_register(devfs_handle_t busv,
  175.   xswitch_provider_t * xswitch_fns)
  176. {
  177.     xswitch_info_t          xswitch_info = xswitch_info_get(busv);
  178.     ASSERT(xswitch_info);
  179.     xswitch_info->xswitch_fns = xswitch_fns;
  180. }
  181. void
  182. xswitch_info_link_is_ok(xswitch_info_t xswitch_info, xwidgetnum_t port)
  183. {
  184.     xswitch_info->census |= XSWITCH_CENSUS_BIT(port);
  185. }
  186. int
  187. xswitch_info_link_ok(xswitch_info_t xswitch_info, xwidgetnum_t port)
  188. {
  189. #if XSWITCH_CENSUS_PORT_MIN
  190.     if (port < XSWITCH_CENSUS_PORT_MIN)
  191. return 0;
  192. #endif
  193.     if (port > XSWITCH_CENSUS_PORT_MAX)
  194. return 0;
  195.     return (xswitch_info->census & XSWITCH_CENSUS_BIT(port));
  196. }
  197. int
  198. xswitch_reset_link(devfs_handle_t xconn_vhdl)
  199. {
  200.     return DEV_FUNC(xconn_vhdl, reset_link)
  201. (xconn_vhdl);
  202. }
  203. /* Given a vertex handle to the xswitch get its logical
  204.  * id.
  205.  */
  206. int
  207. xswitch_id_get(devfs_handle_t xconn_vhdl)
  208. {
  209.     arbitrary_info_t  xbow_num;
  210.     graph_error_t rv;
  211.     rv = hwgraph_info_get_LBL(xconn_vhdl,INFO_LBL_XSWITCH_ID,&xbow_num);
  212.     ASSERT(rv == GRAPH_SUCCESS);
  213.     return(xbow_num);
  214. }
  215. /* Given a vertex handle to the xswitch set its logical
  216.  * id.
  217.  */
  218. void
  219. xswitch_id_set(devfs_handle_t xconn_vhdl,int xbow_num)
  220. {
  221.     graph_error_t rv;
  222.     rv = hwgraph_info_add_LBL(xconn_vhdl,INFO_LBL_XSWITCH_ID,
  223.       (arbitrary_info_t)xbow_num);
  224.     ASSERT(rv == GRAPH_SUCCESS);
  225. }