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

Linux/Unix编程

开发平台:

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