xtalk.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:28k
- /* $Id$
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1992 - 1997, 2000-2001 Silicon Graphics, Inc. All rights reserved.
- */
- #include <linux/types.h>
- #include <linux/slab.h>
- #include <asm/sn/sgi.h>
- #include <asm/sn/driver.h>
- #include <asm/sn/io.h>
- #include <asm/sn/iograph.h>
- #include <asm/sn/invent.h>
- #include <asm/sn/hcl.h>
- #include <asm/sn/labelcl.h>
- #include <asm/sn/hcl_util.h>
- #include <asm/sn/xtalk/xtalk.h>
- #include <asm/sn/xtalk/xswitch.h>
- #include <asm/sn/xtalk/xwidget.h>
- #include <asm/sn/xtalk/xtalk_private.h>
- /*
- * Implement crosstalk provider operations. The xtalk* layer provides a
- * platform-independent interface for crosstalk devices. This layer
- * switches among the possible implementations of a crosstalk adapter.
- *
- * On platforms with only one possible xtalk provider, macros can be
- * set up at the top that cause the table lookups and indirections to
- * completely disappear.
- */
- #define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))
- #define DEL(ptr) (kfree(ptr))
- char widget_info_fingerprint[] = "widget_info";
- cdl_p xtalk_registry = NULL;
- #define DEV_FUNC(dev,func) hub_##func
- #define CAST_PIOMAP(x) ((hub_piomap_t)(x))
- #define CAST_DMAMAP(x) ((hub_dmamap_t)(x))
- #define CAST_INTR(x) ((hub_intr_t)(x))
- /* =====================================================================
- * Function Table of Contents
- */
- xtalk_piomap_t xtalk_piomap_alloc(devfs_handle_t, device_desc_t, iopaddr_t, size_t, size_t, unsigned);
- void xtalk_piomap_free(xtalk_piomap_t);
- caddr_t xtalk_piomap_addr(xtalk_piomap_t, iopaddr_t, size_t);
- void xtalk_piomap_done(xtalk_piomap_t);
- caddr_t xtalk_piotrans_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, unsigned);
- caddr_t xtalk_pio_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, xtalk_piomap_t *, unsigned);
- void xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *);
- caddr_t xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned);
- static caddr_t null_xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned);
- xtalk_dmamap_t xtalk_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned);
- void xtalk_dmamap_free(xtalk_dmamap_t);
- iopaddr_t xtalk_dmamap_addr(xtalk_dmamap_t, paddr_t, size_t);
- alenlist_t xtalk_dmamap_list(xtalk_dmamap_t, alenlist_t, unsigned);
- void xtalk_dmamap_done(xtalk_dmamap_t);
- iopaddr_t xtalk_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned);
- alenlist_t xtalk_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned);
- void xtalk_dmamap_drain(xtalk_dmamap_t);
- void xtalk_dmaaddr_drain(devfs_handle_t, iopaddr_t, size_t);
- void xtalk_dmalist_drain(devfs_handle_t, alenlist_t);
- xtalk_intr_t xtalk_intr_alloc(devfs_handle_t, device_desc_t, devfs_handle_t);
- xtalk_intr_t xtalk_intr_alloc_nothd(devfs_handle_t, device_desc_t, devfs_handle_t);
- void xtalk_intr_free(xtalk_intr_t);
- int xtalk_intr_connect(xtalk_intr_t, xtalk_intr_setfunc_t, void *);
- void xtalk_intr_disconnect(xtalk_intr_t);
- devfs_handle_t xtalk_intr_cpu_get(xtalk_intr_t);
- int xtalk_error_handler(devfs_handle_t, int, ioerror_mode_t, ioerror_t *);
- int xtalk_error_devenable(devfs_handle_t, int, int);
- void xtalk_provider_startup(devfs_handle_t);
- void xtalk_provider_shutdown(devfs_handle_t);
- devfs_handle_t xtalk_intr_dev_get(xtalk_intr_t);
- xwidgetnum_t xtalk_intr_target_get(xtalk_intr_t);
- xtalk_intr_vector_t xtalk_intr_vector_get(xtalk_intr_t);
- iopaddr_t xtalk_intr_addr_get(struct xtalk_intr_s *);
- void *xtalk_intr_sfarg_get(xtalk_intr_t);
- devfs_handle_t xtalk_pio_dev_get(xtalk_piomap_t);
- xwidgetnum_t xtalk_pio_target_get(xtalk_piomap_t);
- iopaddr_t xtalk_pio_xtalk_addr_get(xtalk_piomap_t);
- ulong xtalk_pio_mapsz_get(xtalk_piomap_t);
- caddr_t xtalk_pio_kvaddr_get(xtalk_piomap_t);
- devfs_handle_t xtalk_dma_dev_get(xtalk_dmamap_t);
- xwidgetnum_t xtalk_dma_target_get(xtalk_dmamap_t);
- xwidget_info_t xwidget_info_chk(devfs_handle_t);
- xwidget_info_t xwidget_info_get(devfs_handle_t);
- void xwidget_info_set(devfs_handle_t, xwidget_info_t);
- devfs_handle_t xwidget_info_dev_get(xwidget_info_t);
- xwidgetnum_t xwidget_info_id_get(xwidget_info_t);
- devfs_handle_t xwidget_info_master_get(xwidget_info_t);
- xwidgetnum_t xwidget_info_masterid_get(xwidget_info_t);
- xwidget_part_num_t xwidget_info_part_num_get(xwidget_info_t);
- xwidget_mfg_num_t xwidget_info_mfg_num_get(xwidget_info_t);
- char *xwidget_info_name_get(xwidget_info_t);
- void xtalk_init(void);
- void xtalk_provider_register(devfs_handle_t, xtalk_provider_t *);
- void xtalk_provider_unregister(devfs_handle_t);
- xtalk_provider_t *xtalk_provider_fns_get(devfs_handle_t);
- int xwidget_driver_register(xwidget_part_num_t,
- xwidget_mfg_num_t,
- char *, unsigned);
- void xwidget_driver_unregister(char *);
- int xwidget_register(xwidget_hwid_t, devfs_handle_t,
- xwidgetnum_t, devfs_handle_t,
- xwidgetnum_t, async_attach_t);
- int xwidget_unregister(devfs_handle_t);
- void xwidget_reset(devfs_handle_t);
- char *xwidget_name_get(devfs_handle_t);
- #if !defined(DEV_FUNC)
- /*
- * There is more than one possible provider
- * for this platform. We need to examine the
- * master vertex of the current vertex for
- * a provider function structure, and indirect
- * through the appropriately named member.
- */
- #define DEV_FUNC(dev,func) xwidget_to_provider_fns(dev)->func
- #define CAST_PIOMAP(x) ((xtalk_piomap_t)(x))
- #define CAST_DMAMAP(x) ((xtalk_dmamap_t)(x))
- #define CAST_INTR(x) ((xtalk_intr_t)(x))
- static xtalk_provider_t *
- xwidget_to_provider_fns(devfs_handle_t xconn)
- {
- xwidget_info_t widget_info;
- xtalk_provider_t *provider_fns;
- widget_info = xwidget_info_get(xconn);
- ASSERT(widget_info != NULL);
- provider_fns = xwidget_info_pops_get(widget_info);
- ASSERT(provider_fns != NULL);
- return (provider_fns);
- }
- #endif
- /*
- * Many functions are not passed their vertex
- * information directly; rather, they must
- * dive through a resource map. These macros
- * are available to coordinate this detail.
- */
- #define PIOMAP_FUNC(map,func) DEV_FUNC(map->xp_dev,func)
- #define DMAMAP_FUNC(map,func) DEV_FUNC(map->xd_dev,func)
- #define INTR_FUNC(intr,func) DEV_FUNC(intr_hdl->xi_dev,func)
- /* =====================================================================
- * PIO MANAGEMENT
- *
- * For mapping system virtual address space to
- * xtalk space on a specified widget
- */
- xtalk_piomap_t
- xtalk_piomap_alloc(devfs_handle_t dev, /* set up mapping for this device */
- device_desc_t dev_desc, /* device descriptor */
- iopaddr_t xtalk_addr, /* map for this xtalk_addr range */
- size_t byte_count,
- size_t byte_count_max, /* maximum size of a mapping */
- unsigned flags)
- { /* defined in sys/pio.h */
- return (xtalk_piomap_t) DEV_FUNC(dev, piomap_alloc)
- (dev, dev_desc, xtalk_addr, byte_count, byte_count_max, flags);
- }
- void
- xtalk_piomap_free(xtalk_piomap_t xtalk_piomap)
- {
- PIOMAP_FUNC(xtalk_piomap, piomap_free)
- (CAST_PIOMAP(xtalk_piomap));
- }
- caddr_t
- xtalk_piomap_addr(xtalk_piomap_t xtalk_piomap, /* mapping resources */
- iopaddr_t xtalk_addr, /* map for this xtalk address */
- size_t byte_count)
- { /* map this many bytes */
- return PIOMAP_FUNC(xtalk_piomap, piomap_addr)
- (CAST_PIOMAP(xtalk_piomap), xtalk_addr, byte_count);
- }
- void
- xtalk_piomap_done(xtalk_piomap_t xtalk_piomap)
- {
- PIOMAP_FUNC(xtalk_piomap, piomap_done)
- (CAST_PIOMAP(xtalk_piomap));
- }
- caddr_t
- xtalk_piotrans_addr(devfs_handle_t dev, /* translate for this device */
- device_desc_t dev_desc, /* device descriptor */
- iopaddr_t xtalk_addr, /* Crosstalk address */
- size_t byte_count, /* map this many bytes */
- unsigned flags)
- { /* (currently unused) */
- return DEV_FUNC(dev, piotrans_addr)
- (dev, dev_desc, xtalk_addr, byte_count, flags);
- }
- caddr_t
- xtalk_pio_addr(devfs_handle_t dev, /* translate for this device */
- device_desc_t dev_desc, /* device descriptor */
- iopaddr_t addr, /* starting address (or offset in window) */
- size_t byte_count, /* map this many bytes */
- xtalk_piomap_t *mapp, /* where to return the map pointer */
- unsigned flags)
- { /* PIO flags */
- xtalk_piomap_t map = 0;
- caddr_t res;
- if (mapp)
- *mapp = 0; /* record "no map used" */
- res = xtalk_piotrans_addr
- (dev, dev_desc, addr, byte_count, flags);
- if (res)
- return res; /* xtalk_piotrans worked */
- map = xtalk_piomap_alloc
- (dev, dev_desc, addr, byte_count, byte_count, flags);
- if (!map)
- return res; /* xtalk_piomap_alloc failed */
- res = xtalk_piomap_addr
- (map, addr, byte_count);
- if (!res) {
- xtalk_piomap_free(map);
- return res; /* xtalk_piomap_addr failed */
- }
- if (mapp)
- *mapp = map; /* pass back map used */
- return res; /* xtalk_piomap_addr succeeded */
- }
- /* =====================================================================
- * EARLY PIOTRANS SUPPORT
- *
- * There are places where drivers (mgras, for instance)
- * need to get PIO translations before the infrastructure
- * is extended to them (setting up textports, for
- * instance). These drivers should call
- * xtalk_early_piotrans_addr with their xtalk ID
- * information, a sequence number (so we can use the second
- * mgras for instance), and the usual piotrans parameters.
- *
- * Machine specific code should provide an implementation
- * of early_piotrans_addr, and present a pointer to this
- * function to xtalk_set_early_piotrans_addr so it can be
- * used by clients without the clients having to know what
- * platform or what xtalk provider is in use.
- */
- static xtalk_early_piotrans_addr_f null_xtalk_early_piotrans_addr;
- xtalk_early_piotrans_addr_f *impl_early_piotrans_addr = null_xtalk_early_piotrans_addr;
- /* xtalk_set_early_piotrans_addr:
- * specify the early_piotrans_addr implementation function.
- */
- void
- xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *impl)
- {
- impl_early_piotrans_addr = impl;
- }
- /* xtalk_early_piotrans_addr:
- * figure out a PIO address for the "nth" crosstalk widget that
- * matches the specified part and mfgr number. Returns NULL if
- * there is no such widget, or if the requested mapping can not
- * be constructed.
- * Limitations on which crosstalk slots (and busses) are
- * checked, and definitions of the ordering of the search across
- * the crosstalk slots, are defined by the platform.
- */
- caddr_t
- xtalk_early_piotrans_addr(xwidget_part_num_t part_num,
- xwidget_mfg_num_t mfg_num,
- int which,
- iopaddr_t xtalk_addr,
- size_t byte_count,
- unsigned flags)
- {
- return impl_early_piotrans_addr
- (part_num, mfg_num, which, xtalk_addr, byte_count, flags);
- }
- /* null_xtalk_early_piotrans_addr:
- * used as the early_piotrans_addr implementation until and
- * unless a real implementation is provided. In DEBUG kernels,
- * we want to know who is calling before the implementation is
- * registered; in non-DEBUG kernels, return NULL representing
- * lack of mapping support.
- */
- /*ARGSUSED */
- static caddr_t
- null_xtalk_early_piotrans_addr(xwidget_part_num_t part_num,
- xwidget_mfg_num_t mfg_num,
- int which,
- iopaddr_t xtalk_addr,
- size_t byte_count,
- unsigned flags)
- {
- #if DEBUG
- PRINT_PANIC("null_xtalk_early_piotrans_addr");
- #endif
- return NULL;
- }
- /* =====================================================================
- * DMA MANAGEMENT
- *
- * For mapping from crosstalk space to system
- * physical space.
- */
- xtalk_dmamap_t
- xtalk_dmamap_alloc(devfs_handle_t dev, /* set up mappings for this device */
- device_desc_t dev_desc, /* device descriptor */
- size_t byte_count_max, /* max size of a mapping */
- unsigned flags)
- { /* defined in dma.h */
- return (xtalk_dmamap_t) DEV_FUNC(dev, dmamap_alloc)
- (dev, dev_desc, byte_count_max, flags);
- }
- void
- xtalk_dmamap_free(xtalk_dmamap_t xtalk_dmamap)
- {
- DMAMAP_FUNC(xtalk_dmamap, dmamap_free)
- (CAST_DMAMAP(xtalk_dmamap));
- }
- iopaddr_t
- xtalk_dmamap_addr(xtalk_dmamap_t xtalk_dmamap, /* use these mapping resources */
- paddr_t paddr, /* map for this address */
- size_t byte_count)
- { /* map this many bytes */
- return DMAMAP_FUNC(xtalk_dmamap, dmamap_addr)
- (CAST_DMAMAP(xtalk_dmamap), paddr, byte_count);
- }
- alenlist_t
- xtalk_dmamap_list(xtalk_dmamap_t xtalk_dmamap, /* use these mapping resources */
- alenlist_t alenlist, /* map this Address/Length List */
- unsigned flags)
- {
- return DMAMAP_FUNC(xtalk_dmamap, dmamap_list)
- (CAST_DMAMAP(xtalk_dmamap), alenlist, flags);
- }
- void
- xtalk_dmamap_done(xtalk_dmamap_t xtalk_dmamap)
- {
- DMAMAP_FUNC(xtalk_dmamap, dmamap_done)
- (CAST_DMAMAP(xtalk_dmamap));
- }
- iopaddr_t
- xtalk_dmatrans_addr(devfs_handle_t dev, /* translate for this device */
- device_desc_t dev_desc, /* device descriptor */
- paddr_t paddr, /* system physical address */
- size_t byte_count, /* length */
- unsigned flags)
- { /* defined in dma.h */
- return DEV_FUNC(dev, dmatrans_addr)
- (dev, dev_desc, paddr, byte_count, flags);
- }
- alenlist_t
- xtalk_dmatrans_list(devfs_handle_t dev, /* translate for this device */
- device_desc_t dev_desc, /* device descriptor */
- alenlist_t palenlist, /* system address/length list */
- unsigned flags)
- { /* defined in dma.h */
- return DEV_FUNC(dev, dmatrans_list)
- (dev, dev_desc, palenlist, flags);
- }
- void
- xtalk_dmamap_drain(xtalk_dmamap_t map)
- {
- DMAMAP_FUNC(map, dmamap_drain)
- (CAST_DMAMAP(map));
- }
- void
- xtalk_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size)
- {
- DEV_FUNC(dev, dmaaddr_drain)
- (dev, addr, size);
- }
- void
- xtalk_dmalist_drain(devfs_handle_t dev, alenlist_t list)
- {
- DEV_FUNC(dev, dmalist_drain)
- (dev, list);
- }
- /* =====================================================================
- * INTERRUPT MANAGEMENT
- *
- * Allow crosstalk devices to establish interrupts
- */
- /*
- * Allocate resources required for an interrupt as specified in intr_desc.
- * Return resource handle in intr_hdl.
- */
- xtalk_intr_t
- xtalk_intr_alloc(devfs_handle_t dev, /* which Crosstalk device */
- device_desc_t dev_desc, /* device descriptor */
- devfs_handle_t owner_dev)
- { /* owner of this interrupt */
- return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc)
- (dev, dev_desc, owner_dev);
- }
- /*
- * Allocate resources required for an interrupt as specified in dev_desc.
- * Unconditionally setup resources to be non-threaded.
- * Return resource handle in intr_hdl.
- */
- xtalk_intr_t
- xtalk_intr_alloc_nothd(devfs_handle_t dev, /* which Crosstalk device */
- device_desc_t dev_desc, /* device descriptor */
- devfs_handle_t owner_dev) /* owner of this interrupt */
- {
- return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc_nothd)
- (dev, dev_desc, owner_dev);
- }
- /*
- * Free resources consumed by intr_alloc.
- */
- void
- xtalk_intr_free(xtalk_intr_t intr_hdl)
- {
- INTR_FUNC(intr_hdl, intr_free)
- (CAST_INTR(intr_hdl));
- }
- /*
- * Associate resources allocated with a previous xtalk_intr_alloc call with the
- * described handler, arg, name, etc.
- *
- * Returns 0 on success, returns <0 on failure.
- */
- int
- xtalk_intr_connect(xtalk_intr_t intr_hdl, /* xtalk intr resource handle */
- xtalk_intr_setfunc_t setfunc, /* func to set intr hw */
- void *setfunc_arg) /* arg to setfunc */
- {
- return INTR_FUNC(intr_hdl, intr_connect)
- (CAST_INTR(intr_hdl), setfunc, setfunc_arg);
- }
- /*
- * Disassociate handler with the specified interrupt.
- */
- void
- xtalk_intr_disconnect(xtalk_intr_t intr_hdl)
- {
- INTR_FUNC(intr_hdl, intr_disconnect)
- (CAST_INTR(intr_hdl));
- }
- /*
- * Return a hwgraph vertex that represents the CPU currently
- * targeted by an interrupt.
- */
- devfs_handle_t
- xtalk_intr_cpu_get(xtalk_intr_t intr_hdl)
- {
- return INTR_FUNC(intr_hdl, intr_cpu_get)
- (CAST_INTR(intr_hdl));
- }
- /* =====================================================================
- * CONFIGURATION MANAGEMENT
- */
- /*
- * Startup a crosstalk provider
- */
- void
- xtalk_provider_startup(devfs_handle_t xtalk_provider)
- {
- DEV_FUNC(xtalk_provider, provider_startup)
- (xtalk_provider);
- }
- /*
- * Shutdown a crosstalk provider
- */
- void
- xtalk_provider_shutdown(devfs_handle_t xtalk_provider)
- {
- DEV_FUNC(xtalk_provider, provider_shutdown)
- (xtalk_provider);
- }
- /*
- * Enable a device on a xtalk widget
- */
- void
- xtalk_widgetdev_enable(devfs_handle_t xconn_vhdl, int devnum)
- {
- DEV_FUNC(xconn_vhdl, widgetdev_enable) (xconn_vhdl, devnum);
- }
- /*
- * Shutdown a device on a xtalk widget
- */
- void
- xtalk_widgetdev_shutdown(devfs_handle_t xconn_vhdl, int devnum)
- {
- DEV_FUNC(xconn_vhdl, widgetdev_shutdown) (xconn_vhdl, devnum);
- }
- int
- xtalk_dma_enabled(devfs_handle_t xconn_vhdl)
- {
- return DEV_FUNC(xconn_vhdl, dma_enabled) (xconn_vhdl);
- }
- /*
- * Generic crosstalk functions, for use with all crosstalk providers
- * and all crosstalk devices.
- */
- /****** Generic crosstalk interrupt interfaces ******/
- devfs_handle_t
- xtalk_intr_dev_get(xtalk_intr_t xtalk_intr)
- {
- return (xtalk_intr->xi_dev);
- }
- xwidgetnum_t
- xtalk_intr_target_get(xtalk_intr_t xtalk_intr)
- {
- return (xtalk_intr->xi_target);
- }
- xtalk_intr_vector_t
- xtalk_intr_vector_get(xtalk_intr_t xtalk_intr)
- {
- return (xtalk_intr->xi_vector);
- }
- iopaddr_t
- xtalk_intr_addr_get(struct xtalk_intr_s *xtalk_intr)
- {
- return (xtalk_intr->xi_addr);
- }
- void *
- xtalk_intr_sfarg_get(xtalk_intr_t xtalk_intr)
- {
- return (xtalk_intr->xi_sfarg);
- }
- /****** Generic crosstalk pio interfaces ******/
- devfs_handle_t
- xtalk_pio_dev_get(xtalk_piomap_t xtalk_piomap)
- {
- return (xtalk_piomap->xp_dev);
- }
- xwidgetnum_t
- xtalk_pio_target_get(xtalk_piomap_t xtalk_piomap)
- {
- return (xtalk_piomap->xp_target);
- }
- iopaddr_t
- xtalk_pio_xtalk_addr_get(xtalk_piomap_t xtalk_piomap)
- {
- return (xtalk_piomap->xp_xtalk_addr);
- }
- ulong
- xtalk_pio_mapsz_get(xtalk_piomap_t xtalk_piomap)
- {
- return (xtalk_piomap->xp_mapsz);
- }
- caddr_t
- xtalk_pio_kvaddr_get(xtalk_piomap_t xtalk_piomap)
- {
- return (xtalk_piomap->xp_kvaddr);
- }
- /****** Generic crosstalk dma interfaces ******/
- devfs_handle_t
- xtalk_dma_dev_get(xtalk_dmamap_t xtalk_dmamap)
- {
- return (xtalk_dmamap->xd_dev);
- }
- xwidgetnum_t
- xtalk_dma_target_get(xtalk_dmamap_t xtalk_dmamap)
- {
- return (xtalk_dmamap->xd_target);
- }
- /****** Generic crosstalk widget information interfaces ******/
- /* xwidget_info_chk:
- * check to see if this vertex is a widget;
- * if so, return its widget_info (if any).
- * if not, return NULL.
- */
- xwidget_info_t
- xwidget_info_chk(devfs_handle_t xwidget)
- {
- arbitrary_info_t ainfo = 0;
- hwgraph_info_get_LBL(xwidget, INFO_LBL_XWIDGET, &ainfo);
- return (xwidget_info_t) ainfo;
- }
- xwidget_info_t
- xwidget_info_get(devfs_handle_t xwidget)
- {
- xwidget_info_t widget_info;
- widget_info = (xwidget_info_t)
- hwgraph_fastinfo_get(xwidget);
- #ifdef LATER
- if ((widget_info != NULL) &&
- (widget_info->w_fingerprint != widget_info_fingerprint))
- #ifdef SUPPORT_PRINTING_V_FORMAT
- PRINT_PANIC("%v bad xwidget_info", xwidget);
- #else
- PRINT_PANIC("%x bad xwidget_info", xwidget);
- #endif
- #endif /* LATER */
- return (widget_info);
- }
- void
- xwidget_info_set(devfs_handle_t xwidget, xwidget_info_t widget_info)
- {
- if (widget_info != NULL)
- widget_info->w_fingerprint = widget_info_fingerprint;
- hwgraph_fastinfo_set(xwidget, (arbitrary_info_t) widget_info);
- /* Also, mark this vertex as an xwidget,
- * and use the widget_info, so xwidget_info_chk
- * can work (and be fairly efficient).
- */
- hwgraph_info_add_LBL(xwidget, INFO_LBL_XWIDGET,
- (arbitrary_info_t) widget_info);
- }
- devfs_handle_t
- xwidget_info_dev_get(xwidget_info_t xwidget_info)
- {
- if (xwidget_info == NULL)
- panic("null xwidget_info");
- return (xwidget_info->w_vertex);
- }
- xwidgetnum_t
- xwidget_info_id_get(xwidget_info_t xwidget_info)
- {
- if (xwidget_info == NULL)
- panic("null xwidget_info");
- return (xwidget_info->w_id);
- }
- devfs_handle_t
- xwidget_info_master_get(xwidget_info_t xwidget_info)
- {
- if (xwidget_info == NULL)
- panic("null xwidget_info");
- return (xwidget_info->w_master);
- }
- xwidgetnum_t
- xwidget_info_masterid_get(xwidget_info_t xwidget_info)
- {
- if (xwidget_info == NULL)
- panic("null xwidget_info");
- return (xwidget_info->w_masterid);
- }
- xwidget_part_num_t
- xwidget_info_part_num_get(xwidget_info_t xwidget_info)
- {
- if (xwidget_info == NULL)
- panic("null xwidget_info");
- return (xwidget_info->w_hwid.part_num);
- }
- xwidget_mfg_num_t
- xwidget_info_mfg_num_get(xwidget_info_t xwidget_info)
- {
- if (xwidget_info == NULL)
- panic("null xwidget_info");
- return (xwidget_info->w_hwid.mfg_num);
- }
- /* Extract the widget name from the widget information
- * for the xtalk widget.
- */
- char *
- xwidget_info_name_get(xwidget_info_t xwidget_info)
- {
- if (xwidget_info == NULL)
- panic("null xwidget info");
- return(xwidget_info->w_name);
- }
- /****** Generic crosstalk initialization interfaces ******/
- /*
- * One-time initialization needed for systems that support crosstalk.
- */
- void
- xtalk_init(void)
- {
- cdl_p cp;
- #if DEBUG && ATTACH_DEBUG
- printf("xtalk_initn");
- #endif
- /* Allocate the registry.
- * We might already have one.
- * If we don't, go get one.
- * MPness: someone might have
- * set one up for us while we
- * were not looking; use an atomic
- * compare-and-swap to commit to
- * using the new registry if and
- * only if nobody else did first.
- * If someone did get there first,
- * toss the one we allocated back
- * into the pool.
- */
- if (xtalk_registry == NULL) {
- cp = cdl_new(EDGE_LBL_XIO, "part", "mfgr");
- if (!compare_and_swap_ptr((void **) &xtalk_registry, NULL, (void *) cp)) {
- cdl_del(cp);
- }
- }
- ASSERT(xtalk_registry != NULL);
- }
- /*
- * Associate a set of xtalk_provider functions with a vertex.
- */
- void
- xtalk_provider_register(devfs_handle_t provider, xtalk_provider_t *xtalk_fns)
- {
- hwgraph_fastinfo_set(provider, (arbitrary_info_t) xtalk_fns);
- }
- /*
- * Disassociate a set of xtalk_provider functions with a vertex.
- */
- void
- xtalk_provider_unregister(devfs_handle_t provider)
- {
- hwgraph_fastinfo_set(provider, (arbitrary_info_t)NULL);
- }
- /*
- * Obtain a pointer to the xtalk_provider functions for a specified Crosstalk
- * provider.
- */
- xtalk_provider_t *
- xtalk_provider_fns_get(devfs_handle_t provider)
- {
- return ((xtalk_provider_t *) hwgraph_fastinfo_get(provider));
- }
- /*
- * Announce a driver for a particular crosstalk part.
- * Returns 0 on success or -1 on failure. Failure occurs if the
- * specified hardware already has a driver.
- */
- /*ARGSUSED4 */
- int
- xwidget_driver_register(xwidget_part_num_t part_num,
- xwidget_mfg_num_t mfg_num,
- char *driver_prefix,
- unsigned flags)
- {
- /* a driver's init routine could call
- * xwidget_driver_register before the
- * system calls xtalk_init; so, we
- * make the call here.
- */
- if (xtalk_registry == NULL)
- xtalk_init();
- return cdl_add_driver(xtalk_registry,
- part_num, mfg_num,
- driver_prefix, flags, NULL);
- }
- /*
- * Inform xtalk infrastructure that a driver is no longer available for
- * handling any widgets.
- */
- void
- xwidget_driver_unregister(char *driver_prefix)
- {
- /* before a driver calls unregister,
- * it must have called registger; so we
- * can assume we have a registry here.
- */
- ASSERT(xtalk_registry != NULL);
- cdl_del_driver(xtalk_registry, driver_prefix, NULL);
- }
- /*
- * Call some function with each vertex that
- * might be one of this driver's attach points.
- */
- void
- xtalk_iterate(char *driver_prefix,
- xtalk_iter_f *func)
- {
- ASSERT(xtalk_registry != NULL);
- cdl_iterate(xtalk_registry, driver_prefix, (cdl_iter_f *)func);
- }
- /*
- * xwidget_register:
- * Register a xtalk device (xwidget) by doing the following.
- * -allocate and initialize xwidget_info data
- * -allocate a hwgraph vertex with name based on widget number (id)
- * -look up the widget's initialization function and call it,
- * or remember the vertex for later initialization.
- *
- */
- int
- xwidget_register(xwidget_hwid_t hwid, /* widget's hardware ID */
- devfs_handle_t widget, /* widget to initialize */
- xwidgetnum_t id, /* widget's target id (0..f) */
- devfs_handle_t master, /* widget's master vertex */
- xwidgetnum_t targetid, /* master's target id (9/a) */
- async_attach_t aa)
- {
- xwidget_info_t widget_info;
- char *s,devnm[MAXDEVNAME];
- /* Allocate widget_info and associate it with widget vertex */
- NEW(widget_info);
- /* Initialize widget_info */
- widget_info->w_vertex = widget;
- widget_info->w_id = id;
- widget_info->w_master = master;
- widget_info->w_masterid = targetid;
- widget_info->w_hwid = *hwid; /* structure copy */
- widget_info->w_efunc = 0;
- widget_info->w_einfo = 0;
- /*
- * get the name of this xwidget vertex and keep the info.
- * This is needed during errors and interupts, but as
- * long as we have it, we can use it elsewhere.
- */
- s = dev_to_name(widget,devnm,MAXDEVNAME);
- widget_info->w_name = kmalloc(strlen(s) + 1, GFP_KERNEL);
- strcpy(widget_info->w_name,s);
-
- xwidget_info_set(widget, widget_info);
- device_master_set(widget, master);
- /* All the driver init routines (including
- * xtalk_init) are called before we get into
- * attaching devices, so we can assume we
- * have a registry here.
- */
- ASSERT(xtalk_registry != NULL);
- /*
- * Add pointer to async attach info -- tear down will be done when
- * the particular descendant is done with the info.
- */
- if (aa)
- async_attach_add_info(widget, aa);
- return cdl_add_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num,
- widget, 0);
- }
- /*
- * xwidget_unregister :
- * Unregister the xtalk device and detach all its hwgraph namespace.
- */
- int
- xwidget_unregister(devfs_handle_t widget)
- {
- xwidget_info_t widget_info;
- xwidget_hwid_t hwid;
- /* Make sure that we have valid widget information initialized */
- if (!(widget_info = xwidget_info_get(widget)))
- return(1);
- /* Remove the inventory information associated
- * with the widget.
- */
- hwgraph_inventory_remove(widget, -1, -1, -1, -1, -1);
-
- hwid = &(widget_info->w_hwid);
- cdl_del_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num,
- widget, 0);
- /* Clean out the xwidget information */
- (void)kfree(widget_info->w_name);
- BZERO((void *)widget_info, sizeof(widget_info));
- DEL(widget_info);
-
- return(0);
- }
- /*
- * Issue a link reset to a widget.
- */
- void
- xwidget_reset(devfs_handle_t xwidget)
- {
- xswitch_reset_link(xwidget);
- }
- void
- xwidget_gfx_reset(devfs_handle_t xwidget)
- {
- xwidget_info_t info;
- xswitch_reset_link(xwidget);
- info = xwidget_info_get(xwidget);
- #ifdef LATER
- ASSERT_ALWAYS(info != NULL);
- #endif
- /*
- * Enable this for other architectures once we add widget_reset to the
- * xtalk provider interface.
- */
- DEV_FUNC(xtalk_provider, widget_reset)
- (xwidget_info_master_get(info), xwidget_info_id_get(info));
- }
- #define ANON_XWIDGET_NAME "No Name" /* Default Widget Name */
- /* Get the canonical hwgraph name of xtalk widget */
- char *
- xwidget_name_get(devfs_handle_t xwidget_vhdl)
- {
- xwidget_info_t info;
- /* If we have a bogus widget handle then return
- * a default anonymous widget name.
- */
- if (xwidget_vhdl == GRAPH_VERTEX_NONE)
- return(ANON_XWIDGET_NAME);
- /* Read the widget name stored in the widget info
- * for the widget setup during widget initialization.
- */
- info = xwidget_info_get(xwidget_vhdl);
- ASSERT(info != NULL);
- return(xwidget_info_name_get(info));
- }
- /*
- * xtalk_device_shutdown
- * Disable the specified xtalk widget and clean out all the software
- * state associated with it.
- */
- int
- xtalk_device_shutdown(devfs_handle_t xbus_vhdl, xwidgetnum_t widget)
- {
- devfs_handle_t widget_vhdl;
- char edge_name[8];
- sprintf(edge_name, "%d", widget);
- if (hwgraph_traverse(xbus_vhdl, edge_name, &widget_vhdl)
- != GRAPH_SUCCESS)
- return(1);
- xwidget_unregister(widget_vhdl);
-
- return(0);
- }