📄 xtalk.c
字号:
/* $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 Silicon Graphics, Inc. * Copyright (C) 2000 by Colin Ngam */#include <linux/types.h>#include <linux/config.h>#include <linux/slab.h>#include <asm/sn/sgi.h>#include <asm/sn/iobus.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;#include <asm/sn/agent.h>#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);void xtalk_intr_free(xtalk_intr_t);int xtalk_intr_connect(xtalk_intr_t, intr_func_t, intr_arg_t, xtalk_intr_setfunc_t, void *, 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_error_register(devfs_handle_t, error_handler_f *, error_handler_arg_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_txtalk_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);}voidxtalk_piomap_free(xtalk_piomap_t xtalk_piomap){ PIOMAP_FUNC(xtalk_piomap, piomap_free) (CAST_PIOMAP(xtalk_piomap));}caddr_txtalk_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);}voidxtalk_piomap_done(xtalk_piomap_t xtalk_piomap){ PIOMAP_FUNC(xtalk_piomap, piomap_done) (CAST_PIOMAP(xtalk_piomap));}caddr_txtalk_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_txtalk_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. */voidxtalk_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_txtalk_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_tnull_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 cmn_err(CE_PANIC, "null_xtalk_early_piotrans_addr");#endif return NULL;}/* ===================================================================== * DMA MANAGEMENT * * For mapping from crosstalk space to system * physical space. */xtalk_dmamap_txtalk_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);}voidxtalk_dmamap_free(xtalk_dmamap_t xtalk_dmamap){ DMAMAP_FUNC(xtalk_dmamap, dmamap_free) (CAST_DMAMAP(xtalk_dmamap));}iopaddr_txtalk_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_txtalk_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);}voidxtalk_dmamap_done(xtalk_dmamap_t xtalk_dmamap){ DMAMAP_FUNC(xtalk_dmamap, dmamap_done) (CAST_DMAMAP(xtalk_dmamap));}iopaddr_t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -