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

嵌入式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/hcl_util.h>
  19. #include <asm/sn/xtalk/xtalk.h>
  20. #include <asm/sn/xtalk/xswitch.h>
  21. #include <asm/sn/xtalk/xwidget.h>
  22. #include <asm/sn/xtalk/xtalk_private.h>
  23. /*
  24.  * Implement crosstalk provider operations.  The xtalk* layer provides a
  25.  * platform-independent interface for crosstalk devices.  This layer
  26.  * switches among the possible implementations of a crosstalk adapter.
  27.  *
  28.  * On platforms with only one possible xtalk provider, macros can be
  29.  * set up at the top that cause the table lookups and indirections to
  30.  * completely disappear.
  31.  */
  32. #define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))
  33. #define DEL(ptr) (kfree(ptr))
  34. char                    widget_info_fingerprint[] = "widget_info";
  35. cdl_p                   xtalk_registry = NULL;
  36. #include <asm/sn/agent.h>
  37. #define DEV_FUNC(dev,func) hub_##func
  38. #define CAST_PIOMAP(x) ((hub_piomap_t)(x))
  39. #define CAST_DMAMAP(x) ((hub_dmamap_t)(x))
  40. #define CAST_INTR(x) ((hub_intr_t)(x))
  41. /* =====================================================================
  42.  *            Function Table of Contents
  43.  */
  44. xtalk_piomap_t          xtalk_piomap_alloc(devfs_handle_t, device_desc_t, iopaddr_t, size_t, size_t, unsigned);
  45. void                    xtalk_piomap_free(xtalk_piomap_t);
  46. caddr_t                 xtalk_piomap_addr(xtalk_piomap_t, iopaddr_t, size_t);
  47. void                    xtalk_piomap_done(xtalk_piomap_t);
  48. caddr_t                 xtalk_piotrans_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, unsigned);
  49. caddr_t                 xtalk_pio_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, xtalk_piomap_t *, unsigned);
  50. void                    xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *);
  51. caddr_t                 xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned);
  52. static caddr_t          null_xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned);
  53. xtalk_dmamap_t          xtalk_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned);
  54. void                    xtalk_dmamap_free(xtalk_dmamap_t);
  55. iopaddr_t               xtalk_dmamap_addr(xtalk_dmamap_t, paddr_t, size_t);
  56. alenlist_t              xtalk_dmamap_list(xtalk_dmamap_t, alenlist_t, unsigned);
  57. void                    xtalk_dmamap_done(xtalk_dmamap_t);
  58. iopaddr_t               xtalk_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned);
  59. alenlist_t              xtalk_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned);
  60. void xtalk_dmamap_drain(xtalk_dmamap_t);
  61. void xtalk_dmaaddr_drain(devfs_handle_t, iopaddr_t, size_t);
  62. void xtalk_dmalist_drain(devfs_handle_t, alenlist_t);
  63. xtalk_intr_t            xtalk_intr_alloc(devfs_handle_t, device_desc_t, devfs_handle_t);
  64. xtalk_intr_t            xtalk_intr_alloc_nothd(devfs_handle_t, device_desc_t, devfs_handle_t);
  65. void                    xtalk_intr_free(xtalk_intr_t);
  66. int                     xtalk_intr_connect(xtalk_intr_t, intr_func_t, intr_arg_t, xtalk_intr_setfunc_t, void *, void *);
  67. void                    xtalk_intr_disconnect(xtalk_intr_t);
  68. devfs_handle_t            xtalk_intr_cpu_get(xtalk_intr_t);
  69. int                     xtalk_error_handler(devfs_handle_t, int, ioerror_mode_t, ioerror_t *);
  70. int                     xtalk_error_devenable(devfs_handle_t, int, int);
  71. void                    xtalk_provider_startup(devfs_handle_t);
  72. void                    xtalk_provider_shutdown(devfs_handle_t);
  73. devfs_handle_t            xtalk_intr_dev_get(xtalk_intr_t);
  74. xwidgetnum_t            xtalk_intr_target_get(xtalk_intr_t);
  75. xtalk_intr_vector_t     xtalk_intr_vector_get(xtalk_intr_t);
  76. iopaddr_t               xtalk_intr_addr_get(struct xtalk_intr_s *);
  77. void                   *xtalk_intr_sfarg_get(xtalk_intr_t);
  78. devfs_handle_t            xtalk_pio_dev_get(xtalk_piomap_t);
  79. xwidgetnum_t            xtalk_pio_target_get(xtalk_piomap_t);
  80. iopaddr_t               xtalk_pio_xtalk_addr_get(xtalk_piomap_t);
  81. ulong                   xtalk_pio_mapsz_get(xtalk_piomap_t);
  82. caddr_t                 xtalk_pio_kvaddr_get(xtalk_piomap_t);
  83. devfs_handle_t            xtalk_dma_dev_get(xtalk_dmamap_t);
  84. xwidgetnum_t            xtalk_dma_target_get(xtalk_dmamap_t);
  85. xwidget_info_t          xwidget_info_chk(devfs_handle_t);
  86. xwidget_info_t          xwidget_info_get(devfs_handle_t);
  87. void                    xwidget_info_set(devfs_handle_t, xwidget_info_t);
  88. devfs_handle_t            xwidget_info_dev_get(xwidget_info_t);
  89. xwidgetnum_t            xwidget_info_id_get(xwidget_info_t);
  90. devfs_handle_t            xwidget_info_master_get(xwidget_info_t);
  91. xwidgetnum_t            xwidget_info_masterid_get(xwidget_info_t);
  92. xwidget_part_num_t      xwidget_info_part_num_get(xwidget_info_t);
  93. xwidget_mfg_num_t       xwidget_info_mfg_num_get(xwidget_info_t);
  94. char  *xwidget_info_name_get(xwidget_info_t);
  95. void                    xtalk_init(void);
  96. void                    xtalk_provider_register(devfs_handle_t, xtalk_provider_t *);
  97. void                    xtalk_provider_unregister(devfs_handle_t);
  98. xtalk_provider_t       *xtalk_provider_fns_get(devfs_handle_t);
  99. int                     xwidget_driver_register(xwidget_part_num_t, 
  100. xwidget_mfg_num_t, 
  101. char *, unsigned);
  102. void                    xwidget_driver_unregister(char *);
  103. int                     xwidget_register(xwidget_hwid_t, devfs_handle_t, 
  104.  xwidgetnum_t, devfs_handle_t, 
  105.  xwidgetnum_t, async_attach_t);
  106. int xwidget_unregister(devfs_handle_t);
  107. void                    xwidget_error_register(devfs_handle_t, error_handler_f *,
  108.        error_handler_arg_t);
  109. void                    xwidget_reset(devfs_handle_t);
  110. char *xwidget_name_get(devfs_handle_t);
  111. #if !defined(DEV_FUNC)
  112. /*
  113.  * There is more than one possible provider
  114.  * for this platform. We need to examine the
  115.  * master vertex of the current vertex for
  116.  * a provider function structure, and indirect
  117.  * through the appropriately named member.
  118.  */
  119. #define DEV_FUNC(dev,func) xwidget_to_provider_fns(dev)->func
  120. #define CAST_PIOMAP(x) ((xtalk_piomap_t)(x))
  121. #define CAST_DMAMAP(x) ((xtalk_dmamap_t)(x))
  122. #define CAST_INTR(x) ((xtalk_intr_t)(x))
  123. static xtalk_provider_t *
  124. xwidget_to_provider_fns(devfs_handle_t xconn)
  125. {
  126.     xwidget_info_t          widget_info;
  127.     xtalk_provider_t       *provider_fns;
  128.     widget_info = xwidget_info_get(xconn);
  129.     ASSERT(widget_info != NULL);
  130.     provider_fns = xwidget_info_pops_get(widget_info);
  131.     ASSERT(provider_fns != NULL);
  132.     return (provider_fns);
  133. }
  134. #endif
  135. /*
  136.  * Many functions are not passed their vertex
  137.  * information directly; rather, they must
  138.  * dive through a resource map. These macros
  139.  * are available to coordinate this detail.
  140.  */
  141. #define PIOMAP_FUNC(map,func) DEV_FUNC(map->xp_dev,func)
  142. #define DMAMAP_FUNC(map,func) DEV_FUNC(map->xd_dev,func)
  143. #define INTR_FUNC(intr,func) DEV_FUNC(intr_hdl->xi_dev,func)
  144. /* =====================================================================
  145.  *                    PIO MANAGEMENT
  146.  *
  147.  *      For mapping system virtual address space to
  148.  *      xtalk space on a specified widget
  149.  */
  150. xtalk_piomap_t
  151. xtalk_piomap_alloc(devfs_handle_t dev, /* set up mapping for this device */
  152.    device_desc_t dev_desc, /* device descriptor */
  153.    iopaddr_t xtalk_addr, /* map for this xtalk_addr range */
  154.    size_t byte_count,
  155.    size_t byte_count_max, /* maximum size of a mapping */
  156.    unsigned flags)
  157. { /* defined in sys/pio.h */
  158.     return (xtalk_piomap_t) DEV_FUNC(dev, piomap_alloc)
  159. (dev, dev_desc, xtalk_addr, byte_count, byte_count_max, flags);
  160. }
  161. void
  162. xtalk_piomap_free(xtalk_piomap_t xtalk_piomap)
  163. {
  164.     PIOMAP_FUNC(xtalk_piomap, piomap_free)
  165. (CAST_PIOMAP(xtalk_piomap));
  166. }
  167. caddr_t
  168. xtalk_piomap_addr(xtalk_piomap_t xtalk_piomap, /* mapping resources */
  169.   iopaddr_t xtalk_addr, /* map for this xtalk address */
  170.   size_t byte_count)
  171. { /* map this many bytes */
  172.     return PIOMAP_FUNC(xtalk_piomap, piomap_addr)
  173. (CAST_PIOMAP(xtalk_piomap), xtalk_addr, byte_count);
  174. }
  175. void
  176. xtalk_piomap_done(xtalk_piomap_t xtalk_piomap)
  177. {
  178.     PIOMAP_FUNC(xtalk_piomap, piomap_done)
  179. (CAST_PIOMAP(xtalk_piomap));
  180. }
  181. caddr_t
  182. xtalk_piotrans_addr(devfs_handle_t dev, /* translate for this device */
  183.     device_desc_t dev_desc, /* device descriptor */
  184.     iopaddr_t xtalk_addr, /* Crosstalk address */
  185.     size_t byte_count, /* map this many bytes */
  186.     unsigned flags)
  187. { /* (currently unused) */
  188.     return DEV_FUNC(dev, piotrans_addr)
  189. (dev, dev_desc, xtalk_addr, byte_count, flags);
  190. }
  191. caddr_t
  192. xtalk_pio_addr(devfs_handle_t dev, /* translate for this device */
  193.        device_desc_t dev_desc, /* device descriptor */
  194.        iopaddr_t addr, /* starting address (or offset in window) */
  195.        size_t byte_count, /* map this many bytes */
  196.        xtalk_piomap_t *mapp, /* where to return the map pointer */
  197.        unsigned flags)
  198. { /* PIO flags */
  199.     xtalk_piomap_t          map = 0;
  200.     caddr_t                 res;
  201.     if (mapp)
  202. *mapp = 0; /* record "no map used" */
  203.     res = xtalk_piotrans_addr
  204. (dev, dev_desc, addr, byte_count, flags);
  205.     if (res)
  206. return res; /* xtalk_piotrans worked */
  207.     map = xtalk_piomap_alloc
  208. (dev, dev_desc, addr, byte_count, byte_count, flags);
  209.     if (!map)
  210. return res; /* xtalk_piomap_alloc failed */
  211.     res = xtalk_piomap_addr
  212. (map, addr, byte_count);
  213.     if (!res) {
  214. xtalk_piomap_free(map);
  215. return res; /* xtalk_piomap_addr failed */
  216.     }
  217.     if (mapp)
  218. *mapp = map; /* pass back map used */
  219.     return res; /* xtalk_piomap_addr succeeded */
  220. }
  221. /* =====================================================================
  222.  *            EARLY PIOTRANS SUPPORT
  223.  *
  224.  *      There are places where drivers (mgras, for instance)
  225.  *      need to get PIO translations before the infrastructure
  226.  *      is extended to them (setting up textports, for
  227.  *      instance). These drivers should call
  228.  *      xtalk_early_piotrans_addr with their xtalk ID
  229.  *      information, a sequence number (so we can use the second
  230.  *      mgras for instance), and the usual piotrans parameters.
  231.  *
  232.  *      Machine specific code should provide an implementation
  233.  *      of early_piotrans_addr, and present a pointer to this
  234.  *      function to xtalk_set_early_piotrans_addr so it can be
  235.  *      used by clients without the clients having to know what
  236.  *      platform or what xtalk provider is in use.
  237.  */
  238. static xtalk_early_piotrans_addr_f null_xtalk_early_piotrans_addr;
  239. xtalk_early_piotrans_addr_f *impl_early_piotrans_addr = null_xtalk_early_piotrans_addr;
  240. /* xtalk_set_early_piotrans_addr:
  241.  * specify the early_piotrans_addr implementation function.
  242.  */
  243. void
  244. xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *impl)
  245. {
  246.     impl_early_piotrans_addr = impl;
  247. }
  248. /* xtalk_early_piotrans_addr:
  249.  * figure out a PIO address for the "nth" crosstalk widget that
  250.  * matches the specified part and mfgr number. Returns NULL if
  251.  * there is no such widget, or if the requested mapping can not
  252.  * be constructed.
  253.  * Limitations on which crosstalk slots (and busses) are
  254.  * checked, and definitions of the ordering of the search across
  255.  * the crosstalk slots, are defined by the platform.
  256.  */
  257. caddr_t
  258. xtalk_early_piotrans_addr(xwidget_part_num_t part_num,
  259.   xwidget_mfg_num_t mfg_num,
  260.   int which,
  261.   iopaddr_t xtalk_addr,
  262.   size_t byte_count,
  263.   unsigned flags)
  264. {
  265.     return impl_early_piotrans_addr
  266. (part_num, mfg_num, which, xtalk_addr, byte_count, flags);
  267. }
  268. /* null_xtalk_early_piotrans_addr:
  269.  * used as the early_piotrans_addr implementation until and
  270.  * unless a real implementation is provided. In DEBUG kernels,
  271.  * we want to know who is calling before the implementation is
  272.  * registered; in non-DEBUG kernels, return NULL representing
  273.  * lack of mapping support.
  274.  */
  275. /*ARGSUSED */
  276. static caddr_t
  277. null_xtalk_early_piotrans_addr(xwidget_part_num_t part_num,
  278.        xwidget_mfg_num_t mfg_num,
  279.        int which,
  280.        iopaddr_t xtalk_addr,
  281.        size_t byte_count,
  282.        unsigned flags)
  283. {
  284. #if DEBUG
  285.     PRINT_PANIC("null_xtalk_early_piotrans_addr");
  286. #endif
  287.     return NULL;
  288. }
  289. /* =====================================================================
  290.  *                    DMA MANAGEMENT
  291.  *
  292.  *      For mapping from crosstalk space to system
  293.  *      physical space.
  294.  */
  295. xtalk_dmamap_t
  296. xtalk_dmamap_alloc(devfs_handle_t dev, /* set up mappings for this device */
  297.    device_desc_t dev_desc, /* device descriptor */
  298.    size_t byte_count_max, /* max size of a mapping */
  299.    unsigned flags)
  300. { /* defined in dma.h */
  301.     return (xtalk_dmamap_t) DEV_FUNC(dev, dmamap_alloc)
  302. (dev, dev_desc, byte_count_max, flags);
  303. }
  304. void
  305. xtalk_dmamap_free(xtalk_dmamap_t xtalk_dmamap)
  306. {
  307.     DMAMAP_FUNC(xtalk_dmamap, dmamap_free)
  308. (CAST_DMAMAP(xtalk_dmamap));
  309. }
  310. iopaddr_t
  311. xtalk_dmamap_addr(xtalk_dmamap_t xtalk_dmamap, /* use these mapping resources */
  312.   paddr_t paddr, /* map for this address */
  313.   size_t byte_count)
  314. { /* map this many bytes */
  315.     return DMAMAP_FUNC(xtalk_dmamap, dmamap_addr)
  316. (CAST_DMAMAP(xtalk_dmamap), paddr, byte_count);
  317. }
  318. alenlist_t
  319. xtalk_dmamap_list(xtalk_dmamap_t xtalk_dmamap, /* use these mapping resources */
  320.   alenlist_t alenlist, /* map this Address/Length List */
  321.   unsigned flags)
  322. {
  323.     return DMAMAP_FUNC(xtalk_dmamap, dmamap_list)
  324. (CAST_DMAMAP(xtalk_dmamap), alenlist, flags);
  325. }
  326. void
  327. xtalk_dmamap_done(xtalk_dmamap_t xtalk_dmamap)
  328. {
  329.     DMAMAP_FUNC(xtalk_dmamap, dmamap_done)
  330. (CAST_DMAMAP(xtalk_dmamap));
  331. }
  332. iopaddr_t
  333. xtalk_dmatrans_addr(devfs_handle_t dev, /* translate for this device */
  334.     device_desc_t dev_desc, /* device descriptor */
  335.     paddr_t paddr, /* system physical address */
  336.     size_t byte_count, /* length */
  337.     unsigned flags)
  338. { /* defined in dma.h */
  339.     return DEV_FUNC(dev, dmatrans_addr)
  340. (dev, dev_desc, paddr, byte_count, flags);
  341. }
  342. alenlist_t
  343. xtalk_dmatrans_list(devfs_handle_t dev, /* translate for this device */
  344.     device_desc_t dev_desc, /* device descriptor */
  345.     alenlist_t palenlist, /* system address/length list */
  346.     unsigned flags)
  347. { /* defined in dma.h */
  348.     return DEV_FUNC(dev, dmatrans_list)
  349. (dev, dev_desc, palenlist, flags);
  350. }
  351. void
  352. xtalk_dmamap_drain(xtalk_dmamap_t map)
  353. {
  354.     DMAMAP_FUNC(map, dmamap_drain)
  355. (CAST_DMAMAP(map));
  356. }
  357. void
  358. xtalk_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size)
  359. {
  360.     DEV_FUNC(dev, dmaaddr_drain)
  361. (dev, addr, size);
  362. }
  363. void
  364. xtalk_dmalist_drain(devfs_handle_t dev, alenlist_t list)
  365. {
  366.     DEV_FUNC(dev, dmalist_drain)
  367. (dev, list);
  368. }
  369. /* =====================================================================
  370.  *                    INTERRUPT MANAGEMENT
  371.  *
  372.  *      Allow crosstalk devices to establish interrupts
  373.  */
  374. /*
  375.  * Allocate resources required for an interrupt as specified in intr_desc.
  376.  * Return resource handle in intr_hdl.
  377.  */
  378. xtalk_intr_t
  379. xtalk_intr_alloc(devfs_handle_t dev, /* which Crosstalk device */
  380.  device_desc_t dev_desc, /* device descriptor */
  381.  devfs_handle_t owner_dev)
  382. { /* owner of this interrupt */
  383.     return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc)
  384. (dev, dev_desc, owner_dev);
  385. }
  386. /*
  387.  * Allocate resources required for an interrupt as specified in dev_desc.
  388.  * Unconditionally setup resources to be non-threaded.
  389.  * Return resource handle in intr_hdl.
  390.  */
  391. xtalk_intr_t
  392. xtalk_intr_alloc_nothd(devfs_handle_t dev, /* which Crosstalk device */
  393.   device_desc_t dev_desc, /* device descriptor */
  394.   devfs_handle_t owner_dev) /* owner of this interrupt */
  395. {
  396.     return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc_nothd)
  397. (dev, dev_desc, owner_dev);
  398. }
  399. /*
  400.  * Free resources consumed by intr_alloc.
  401.  */
  402. void
  403. xtalk_intr_free(xtalk_intr_t intr_hdl)
  404. {
  405.     INTR_FUNC(intr_hdl, intr_free)
  406. (CAST_INTR(intr_hdl));
  407. }
  408. /*
  409.  * Associate resources allocated with a previous xtalk_intr_alloc call with the
  410.  * described handler, arg, name, etc.
  411.  *
  412.  * Returns 0 on success, returns <0 on failure.
  413.  */
  414. int
  415. xtalk_intr_connect(xtalk_intr_t intr_hdl, /* xtalk intr resource handle */
  416.    intr_func_t intr_func, /* xtalk intr handler */
  417.    intr_arg_t intr_arg, /* arg to intr handler */
  418.    xtalk_intr_setfunc_t setfunc, /* func to set intr hw */
  419.    void *setfunc_arg, /* arg to setfunc */
  420.    void *thread)
  421. { /* intr thread to use */
  422.     return INTR_FUNC(intr_hdl, intr_connect)
  423. (CAST_INTR(intr_hdl), intr_func, intr_arg, setfunc, setfunc_arg, thread);
  424. }
  425. /*
  426.  * Disassociate handler with the specified interrupt.
  427.  */
  428. void
  429. xtalk_intr_disconnect(xtalk_intr_t intr_hdl)
  430. {
  431.     INTR_FUNC(intr_hdl, intr_disconnect)
  432. (CAST_INTR(intr_hdl));
  433. }
  434. /*
  435.  * Return a hwgraph vertex that represents the CPU currently
  436.  * targeted by an interrupt.
  437.  */
  438. devfs_handle_t
  439. xtalk_intr_cpu_get(xtalk_intr_t intr_hdl)
  440. {
  441.     return INTR_FUNC(intr_hdl, intr_cpu_get)
  442. (CAST_INTR(intr_hdl));
  443. }
  444. /*
  445.  * =====================================================================
  446.  *                      ERROR MANAGEMENT
  447.  */
  448. /*
  449.  * xtalk_error_handler:
  450.  * pass this error on to the handler registered
  451.  * at the specified xtalk connecdtion point,
  452.  * or complain about it here if there is no handler.
  453.  *
  454.  * This routine plays two roles during error delivery
  455.  * to most widgets: first, the external agent (heart,
  456.  * hub, or whatever) calls in with the error and the
  457.  * connect point representing the crosstalk switch,
  458.  * or whatever crosstalk device is directly connected
  459.  * to the agent.
  460.  *
  461.  * If there is a switch, it will generally look at the
  462.  * widget number stashed in the ioerror structure; and,
  463.  * if the error came from some widget other than the
  464.  * switch, it will call back into xtalk_error_handler
  465.  * with the connection point of the offending port.
  466.  */
  467. int
  468. xtalk_error_handler(
  469.        devfs_handle_t xconn,
  470.        int error_code,
  471.        ioerror_mode_t mode,
  472.        ioerror_t *ioerror)
  473. {
  474.     xwidget_info_t          xwidget_info;
  475. #if DEBUG && ERROR_DEBUG
  476. #ifdef SUPPORT_PRINTING_V_FORMAT
  477.     printk("%v: xtalk_error_handlern", xconn);
  478. #else
  479.     printk("%x: xtalk_error_handlern", xconn);
  480. #endif
  481. #endif
  482.     xwidget_info = xwidget_info_get(xconn);
  483.     /* Make sure that xwidget_info is a valid pointer before derefencing it.
  484.      * We could come in here during very early initialization. 
  485.      */
  486.     if (xwidget_info && xwidget_info->w_efunc)
  487. return xwidget_info->w_efunc
  488.     (xwidget_info->w_einfo,
  489.      error_code, mode, ioerror);
  490.     /*
  491.      * no error handler registered for
  492.      * the offending port. it's not clear
  493.      * what needs to be done, but reporting
  494.      * it would be a good thing, unless it
  495.      * is a mode that requires nothing.
  496.      */
  497.     if ((mode == MODE_DEVPROBE) || (mode == MODE_DEVUSERERROR) ||
  498. (mode == MODE_DEVREENABLE))
  499. return IOERROR_HANDLED;
  500. #ifdef LATER
  501. #ifdef SUPPORT_PRINTING_V_FORMAT
  502.     PRINT_WARNING("Xbow at %v encountered Fatal error", xconn);
  503. #else
  504.     PRINT_WARNING("Xbow at %x encountered Fatal error", xconn);
  505. #endif
  506. #endif /* LATER */
  507.     ioerror_dump("xtalk", error_code, mode, ioerror);
  508.     return IOERROR_UNHANDLED;
  509. }
  510. int
  511. xtalk_error_devenable(devfs_handle_t xconn_vhdl, int devnum, int error_code)
  512. {
  513.     return DEV_FUNC(xconn_vhdl, error_devenable) (xconn_vhdl, devnum, error_code);
  514. }
  515. /* =====================================================================
  516.  *                    CONFIGURATION MANAGEMENT
  517.  */
  518. /*
  519.  * Startup a crosstalk provider
  520.  */
  521. void
  522. xtalk_provider_startup(devfs_handle_t xtalk_provider)
  523. {
  524.     DEV_FUNC(xtalk_provider, provider_startup)
  525. (xtalk_provider);
  526. }
  527. /*
  528.  * Shutdown a crosstalk provider
  529.  */
  530. void
  531. xtalk_provider_shutdown(devfs_handle_t xtalk_provider)
  532. {
  533.     DEV_FUNC(xtalk_provider, provider_shutdown)
  534. (xtalk_provider);
  535. }
  536. /* 
  537.  * Enable a device on a xtalk widget 
  538.  */
  539. void
  540. xtalk_widgetdev_enable(devfs_handle_t xconn_vhdl, int devnum)
  541. {
  542.     DEV_FUNC(xconn_vhdl, widgetdev_enable) (xconn_vhdl, devnum);
  543. }
  544. /* 
  545.  * Shutdown a device on a xtalk widget 
  546.  */
  547. void
  548. xtalk_widgetdev_shutdown(devfs_handle_t xconn_vhdl, int devnum)
  549. {
  550.     DEV_FUNC(xconn_vhdl, widgetdev_shutdown) (xconn_vhdl, devnum);
  551. }
  552. int
  553. xtalk_dma_enabled(devfs_handle_t xconn_vhdl)
  554. {
  555.     return DEV_FUNC(xconn_vhdl, dma_enabled) (xconn_vhdl);
  556. }
  557. /*
  558.  * Generic crosstalk functions, for use with all crosstalk providers
  559.  * and all crosstalk devices.
  560.  */
  561. /****** Generic crosstalk interrupt interfaces ******/
  562. devfs_handle_t
  563. xtalk_intr_dev_get(xtalk_intr_t xtalk_intr)
  564. {
  565.     return (xtalk_intr->xi_dev);
  566. }
  567. xwidgetnum_t
  568. xtalk_intr_target_get(xtalk_intr_t xtalk_intr)
  569. {
  570.     return (xtalk_intr->xi_target);
  571. }
  572. xtalk_intr_vector_t
  573. xtalk_intr_vector_get(xtalk_intr_t xtalk_intr)
  574. {
  575.     return (xtalk_intr->xi_vector);
  576. }
  577. iopaddr_t
  578. xtalk_intr_addr_get(struct xtalk_intr_s *xtalk_intr)
  579. {
  580.     return (xtalk_intr->xi_addr);
  581. }
  582. void                   *
  583. xtalk_intr_sfarg_get(xtalk_intr_t xtalk_intr)
  584. {
  585.     return (xtalk_intr->xi_sfarg);
  586. }
  587. /****** Generic crosstalk pio interfaces ******/
  588. devfs_handle_t
  589. xtalk_pio_dev_get(xtalk_piomap_t xtalk_piomap)
  590. {
  591.     return (xtalk_piomap->xp_dev);
  592. }
  593. xwidgetnum_t
  594. xtalk_pio_target_get(xtalk_piomap_t xtalk_piomap)
  595. {
  596.     return (xtalk_piomap->xp_target);
  597. }
  598. iopaddr_t
  599. xtalk_pio_xtalk_addr_get(xtalk_piomap_t xtalk_piomap)
  600. {
  601.     return (xtalk_piomap->xp_xtalk_addr);
  602. }
  603. ulong
  604. xtalk_pio_mapsz_get(xtalk_piomap_t xtalk_piomap)
  605. {
  606.     return (xtalk_piomap->xp_mapsz);
  607. }
  608. caddr_t
  609. xtalk_pio_kvaddr_get(xtalk_piomap_t xtalk_piomap)
  610. {
  611.     return (xtalk_piomap->xp_kvaddr);
  612. }
  613. /****** Generic crosstalk dma interfaces ******/
  614. devfs_handle_t
  615. xtalk_dma_dev_get(xtalk_dmamap_t xtalk_dmamap)
  616. {
  617.     return (xtalk_dmamap->xd_dev);
  618. }
  619. xwidgetnum_t
  620. xtalk_dma_target_get(xtalk_dmamap_t xtalk_dmamap)
  621. {
  622.     return (xtalk_dmamap->xd_target);
  623. }
  624. /****** Generic crosstalk widget information interfaces ******/
  625. /* xwidget_info_chk:
  626.  * check to see if this vertex is a widget;
  627.  * if so, return its widget_info (if any).
  628.  * if not, return NULL.
  629.  */
  630. xwidget_info_t
  631. xwidget_info_chk(devfs_handle_t xwidget)
  632. {
  633.     arbitrary_info_t        ainfo = 0;
  634.     hwgraph_info_get_LBL(xwidget, INFO_LBL_XWIDGET, &ainfo);
  635.     return (xwidget_info_t) ainfo;
  636. }
  637. xwidget_info_t
  638. xwidget_info_get(devfs_handle_t xwidget)
  639. {
  640.     xwidget_info_t          widget_info;
  641.     widget_info = (xwidget_info_t)
  642. hwgraph_fastinfo_get(xwidget);
  643. #ifdef LATER
  644.     if ((widget_info != NULL) &&
  645. (widget_info->w_fingerprint != widget_info_fingerprint))
  646. #ifdef SUPPORT_PRINTING_V_FORMAT
  647. PRINT_PANIC("%v bad xwidget_info", xwidget);
  648. #else
  649. PRINT_PANIC("%x bad xwidget_info", xwidget);
  650. #endif
  651. #endif /* LATER */
  652.     return (widget_info);
  653. }
  654. void
  655. xwidget_info_set(devfs_handle_t xwidget, xwidget_info_t widget_info)
  656. {
  657.     if (widget_info != NULL)
  658. widget_info->w_fingerprint = widget_info_fingerprint;
  659.     hwgraph_fastinfo_set(xwidget, (arbitrary_info_t) widget_info);
  660.     /* Also, mark this vertex as an xwidget,
  661.      * and use the widget_info, so xwidget_info_chk
  662.      * can work (and be fairly efficient).
  663.      */
  664.     hwgraph_info_add_LBL(xwidget, INFO_LBL_XWIDGET,
  665.  (arbitrary_info_t) widget_info);
  666. }
  667. devfs_handle_t
  668. xwidget_info_dev_get(xwidget_info_t xwidget_info)
  669. {
  670.     if (xwidget_info == NULL)
  671. panic("null xwidget_info");
  672.     return (xwidget_info->w_vertex);
  673. }
  674. xwidgetnum_t
  675. xwidget_info_id_get(xwidget_info_t xwidget_info)
  676. {
  677.     if (xwidget_info == NULL)
  678. panic("null xwidget_info");
  679.     return (xwidget_info->w_id);
  680. }
  681. devfs_handle_t
  682. xwidget_info_master_get(xwidget_info_t xwidget_info)
  683. {
  684.     if (xwidget_info == NULL)
  685. panic("null xwidget_info");
  686.     return (xwidget_info->w_master);
  687. }
  688. xwidgetnum_t
  689. xwidget_info_masterid_get(xwidget_info_t xwidget_info)
  690. {
  691.     if (xwidget_info == NULL)
  692. panic("null xwidget_info");
  693.     return (xwidget_info->w_masterid);
  694. }
  695. xwidget_part_num_t
  696. xwidget_info_part_num_get(xwidget_info_t xwidget_info)
  697. {
  698.     if (xwidget_info == NULL)
  699. panic("null xwidget_info");
  700.     return (xwidget_info->w_hwid.part_num);
  701. }
  702. xwidget_mfg_num_t
  703. xwidget_info_mfg_num_get(xwidget_info_t xwidget_info)
  704. {
  705.     if (xwidget_info == NULL)
  706. panic("null xwidget_info");
  707.     return (xwidget_info->w_hwid.mfg_num);
  708. }
  709. /* Extract the widget name from the widget information
  710.  * for the xtalk widget.
  711.  */
  712. char *
  713. xwidget_info_name_get(xwidget_info_t xwidget_info)
  714. {
  715.     if (xwidget_info == NULL)
  716. panic("null xwidget info");
  717.     return(xwidget_info->w_name);
  718. }
  719. /****** Generic crosstalk initialization interfaces ******/
  720. /*
  721.  * One-time initialization needed for systems that support crosstalk.
  722.  */
  723. void
  724. xtalk_init(void)
  725. {
  726.     cdl_p                   cp;
  727. #if DEBUG && ATTACH_DEBUG
  728.     printf("xtalk_initn");
  729. #endif
  730.     /* Allocate the registry.
  731.      * We might already have one.
  732.      * If we don't, go get one.
  733.      * MPness: someone might have
  734.      * set one up for us while we
  735.      * were not looking; use an atomic
  736.      * compare-and-swap to commit to
  737.      * using the new registry if and
  738.      * only if nobody else did first.
  739.      * If someone did get there first,
  740.      * toss the one we allocated back
  741.      * into the pool.
  742.      */
  743.     if (xtalk_registry == NULL) {
  744. cp = cdl_new(EDGE_LBL_XIO, "part", "mfgr");
  745. if (!compare_and_swap_ptr((void **) &xtalk_registry, NULL, (void *) cp)) {
  746.     cdl_del(cp);
  747. }
  748.     }
  749.     ASSERT(xtalk_registry != NULL);
  750. }
  751. /*
  752.  * Associate a set of xtalk_provider functions with a vertex.
  753.  */
  754. void
  755. xtalk_provider_register(devfs_handle_t provider, xtalk_provider_t *xtalk_fns)
  756. {
  757.     hwgraph_fastinfo_set(provider, (arbitrary_info_t) xtalk_fns);
  758. }
  759. /*
  760.  * Disassociate a set of xtalk_provider functions with a vertex.
  761.  */
  762. void
  763. xtalk_provider_unregister(devfs_handle_t provider)
  764. {
  765.     hwgraph_fastinfo_set(provider, (arbitrary_info_t)NULL);
  766. }
  767. /*
  768.  * Obtain a pointer to the xtalk_provider functions for a specified Crosstalk
  769.  * provider.
  770.  */
  771. xtalk_provider_t       *
  772. xtalk_provider_fns_get(devfs_handle_t provider)
  773. {
  774.     return ((xtalk_provider_t *) hwgraph_fastinfo_get(provider));
  775. }
  776. /*
  777.  * Announce a driver for a particular crosstalk part.
  778.  * Returns 0 on success or -1 on failure.  Failure occurs if the
  779.  * specified hardware already has a driver.
  780.  */
  781. /*ARGSUSED4 */
  782. int
  783. xwidget_driver_register(xwidget_part_num_t part_num,
  784. xwidget_mfg_num_t mfg_num,
  785. char *driver_prefix,
  786. unsigned flags)
  787. {
  788.     /* a driver's init routine could call
  789.      * xwidget_driver_register before the
  790.      * system calls xtalk_init; so, we
  791.      * make the call here.
  792.      */
  793.     if (xtalk_registry == NULL)
  794. xtalk_init();
  795.     return cdl_add_driver(xtalk_registry,
  796.   part_num, mfg_num,
  797.   driver_prefix, flags, NULL);
  798. }
  799. /*
  800.  * Inform xtalk infrastructure that a driver is no longer available for
  801.  * handling any widgets.
  802.  */
  803. void
  804. xwidget_driver_unregister(char *driver_prefix)
  805. {
  806.     /* before a driver calls unregister,
  807.      * it must have called registger; so we
  808.      * can assume we have a registry here.
  809.      */
  810.     ASSERT(xtalk_registry != NULL);
  811.     cdl_del_driver(xtalk_registry, driver_prefix, NULL);
  812. }
  813. /*
  814.  * Call some function with each vertex that
  815.  * might be one of this driver's attach points.
  816.  */
  817. void
  818. xtalk_iterate(char *driver_prefix,
  819.       xtalk_iter_f *func)
  820. {
  821.     ASSERT(xtalk_registry != NULL);
  822.     cdl_iterate(xtalk_registry, driver_prefix, (cdl_iter_f *)func);
  823. }
  824. /*
  825.  * xwidget_register:
  826.  * Register a xtalk device (xwidget) by doing the following.
  827.  *      -allocate and initialize xwidget_info data
  828.  *      -allocate a hwgraph vertex with name based on widget number (id)
  829.  *      -look up the widget's initialization function and call it,
  830.  *      or remember the vertex for later initialization.
  831.  *
  832.  */
  833. int
  834. xwidget_register(xwidget_hwid_t hwid, /* widget's hardware ID */
  835.  devfs_handle_t  widget, /* widget to initialize */
  836.  xwidgetnum_t  id, /* widget's target id (0..f) */
  837.  devfs_handle_t  master, /* widget's master vertex */
  838.  xwidgetnum_t  targetid, /* master's target id (9/a) */
  839.  async_attach_t aa)
  840. {
  841.     xwidget_info_t          widget_info;
  842.     char     *s,devnm[MAXDEVNAME];
  843.     /* Allocate widget_info and associate it with widget vertex */
  844.     NEW(widget_info);
  845.     /* Initialize widget_info */
  846.     widget_info->w_vertex = widget;
  847.     widget_info->w_id = id;
  848.     widget_info->w_master = master;
  849.     widget_info->w_masterid = targetid;
  850.     widget_info->w_hwid = *hwid; /* structure copy */
  851.     widget_info->w_efunc = 0;
  852.     widget_info->w_einfo = 0;
  853.     /*
  854.      * get the name of this xwidget vertex and keep the info.
  855.      * This is needed during errors and interrupts, but as
  856.      * long as we have it, we can use it elsewhere.
  857.      */
  858.     s = dev_to_name(widget,devnm,MAXDEVNAME);
  859.     widget_info->w_name = kmalloc(strlen(s) + 1, GFP_KERNEL);
  860.     strcpy(widget_info->w_name,s);
  861.     
  862.     xwidget_info_set(widget, widget_info);
  863.     device_master_set(widget, master);
  864.     /* All the driver init routines (including
  865.      * xtalk_init) are called before we get into
  866.      * attaching devices, so we can assume we
  867.      * have a registry here.
  868.      */
  869.     ASSERT(xtalk_registry != NULL);
  870.     /* 
  871.      * Add pointer to async attach info -- tear down will be done when
  872.      * the particular descendant is done with the info.
  873.      */
  874.     if (aa)
  875.     async_attach_add_info(widget, aa);
  876.     return cdl_add_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num,
  877.                           widget, 0);
  878. }
  879. /*
  880.  * xwidget_unregister :
  881.  * Unregister the xtalk device and detach all its hwgraph namespace.
  882.  */
  883. int
  884. xwidget_unregister(devfs_handle_t widget)
  885. {
  886.     xwidget_info_t widget_info;
  887.     xwidget_hwid_t hwid;
  888.     /* Make sure that we have valid widget information initialized */
  889.     if (!(widget_info = xwidget_info_get(widget)))
  890. return(1);
  891.     /* Remove the inventory information associated
  892.      * with the widget.
  893.      */
  894.     hwgraph_inventory_remove(widget, -1, -1, -1, -1, -1);
  895.     
  896.     hwid = &(widget_info->w_hwid);
  897.     cdl_del_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num,
  898.                    widget, 0);
  899.     /* Clean out the xwidget information */
  900.     (void)kfree(widget_info->w_name);
  901.     BZERO((void *)widget_info, sizeof(widget_info));
  902.     DEL(widget_info);
  903.     
  904.     return(0);
  905. }
  906. void
  907. xwidget_error_register(devfs_handle_t xwidget,
  908.        error_handler_f *efunc,
  909.        error_handler_arg_t einfo)
  910. {
  911.     xwidget_info_t          xwidget_info;
  912.     xwidget_info = xwidget_info_get(xwidget);
  913.     ASSERT(xwidget_info != NULL);
  914.     xwidget_info->w_efunc = efunc;
  915.     xwidget_info->w_einfo = einfo;
  916. }
  917. /*
  918.  * Issue a link reset to a widget.
  919.  */
  920. void
  921. xwidget_reset(devfs_handle_t xwidget)
  922. {
  923.     xswitch_reset_link(xwidget);
  924. }
  925. void
  926. xwidget_gfx_reset(devfs_handle_t xwidget)
  927. {
  928.     xwidget_info_t info;
  929.     xswitch_reset_link(xwidget);
  930.     info = xwidget_info_get(xwidget);
  931. #ifdef LATER
  932.     ASSERT_ALWAYS(info != NULL);
  933. #endif
  934.     /*
  935.      * Enable this for other architectures once we add widget_reset to the
  936.      * xtalk provider interface.
  937.      */
  938.     DEV_FUNC(xtalk_provider, widget_reset)
  939. (xwidget_info_master_get(info), xwidget_info_id_get(info));
  940. }
  941. #define ANON_XWIDGET_NAME "No Name" /* Default Widget Name */
  942. /* Get the canonical hwgraph  name of xtalk widget */
  943. char *
  944. xwidget_name_get(devfs_handle_t xwidget_vhdl)
  945. {
  946. xwidget_info_t  info;
  947. /* If we have a bogus widget handle then return
  948.  * a default anonymous widget name.
  949.  */
  950. if (xwidget_vhdl == GRAPH_VERTEX_NONE)
  951.     return(ANON_XWIDGET_NAME);
  952. /* Read the widget name stored in the widget info
  953.  * for the widget setup during widget initialization.
  954.  */
  955. info = xwidget_info_get(xwidget_vhdl);
  956. ASSERT(info != NULL);
  957. return(xwidget_info_name_get(info));
  958. }
  959. /*
  960.  * xtalk_device_shutdown
  961.  * Disable  the specified xtalk widget and clean out all the software
  962.  * state associated with it.
  963.  */
  964. int
  965. xtalk_device_shutdown(devfs_handle_t xbus_vhdl, xwidgetnum_t widget)
  966. {
  967. devfs_handle_t widget_vhdl;
  968. char edge_name[8];
  969. sprintf(edge_name, "%d", widget);
  970. if (hwgraph_traverse(xbus_vhdl, edge_name, &widget_vhdl) 
  971.     != GRAPH_SUCCESS)
  972. return(1);
  973. xwidget_unregister(widget_vhdl);
  974. return(0);
  975. }
  976. /*
  977.  * xtalk_device_inquiry
  978.  * Find out hardware information about the xtalk widget.
  979.  */
  980. int
  981. xtalk_device_inquiry(devfs_handle_t xbus_vhdl, xwidgetnum_t widget)
  982. {
  983. extern void hub_device_inquiry(devfs_handle_t, xwidgetnum_t);
  984. hub_device_inquiry(xbus_vhdl, widget);
  985. return(0);
  986. }