⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pciba.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $Id: pciba.c,v 1.1.1.1 2004/02/04 12:55:33 laputa Exp $ * * 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 <linux/module.h>#include <asm/sn/sgi.h>#include <asm/sn/addrs.h>#include <asm/sn/arch.h>#include <asm/sn/iograph.h>#include <asm/sn/invent.h>#include <asm/sn/hcl.h>#include <asm/sn/labelcl.h>#include <asm/sn/xtalk/xwidget.h>#include <asm/sn/pci/bridge.h>#include <asm/sn/pci/pciio.h>#include <asm/sn/pci/pcibr.h>#include <asm/sn/pci/pcibr_private.h>#include <asm/sn/pci/pci_defs.h>#include <asm/sn/prio.h>#include <asm/sn/ioerror_handling.h>#include <asm/sn/xtalk/xbow.h>#include <asm/sn/ioc3.h>#include <asm/sn/eeprom.h>#include <asm/sn/sn1/bedrock.h>#include <asm/sn/sn_private.h>#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)#include <asm/sn/sn1/hubio.h>#include <asm/sn/sn1/hubio_next.h>#endif#define copyin(_a, _b, _c)	copy_from_user(_b, _a, _c)#ifndef	DEBUG_PCIBA#define	DEBUG_PCIBA		0#endif/* v_mapphys does not percolate page offset back. */#define	PCIBA_ALIGN_CHECK	1#include <asm/sn/pci/pciba.h>/* grab an unused space code for "User DMA" space */#ifndef	PCIBA_SPACE_UDMA#define	PCIBA_SPACE_UDMA	(14)#endif#if DEBUG_REFCTextern int		hwgraph_vertex_refct(vertex_hdl_t);#endifextern int		pci_user_dma_max_pages;#define NEW(ptr)	(ptr = kmem_zalloc(sizeof (*(ptr)), KM_SLEEP))#define DEL(ptr)	(kfree(ptr))/* Oops -- no standard "pci address" type! */typedef uint64_t        pciaddr_t;/* ================================================================ *            driver types */typedef struct pciba_slot_s *pciba_slot_t;typedef struct pciba_comm_s *pciba_comm_t;typedef struct pciba_soft_s *pciba_soft_t;typedef struct pciba_map_s *pciba_map_t, **pciba_map_h;typedef struct pciba_dma_s *pciba_dma_t, **pciba_dma_h;typedef struct pciba_bus_s *pciba_bus_t;#define	TRACKED_SPACES	16struct pciba_comm_s {    devfs_handle_t	    conn;    pciba_bus_t             bus;    int			    refct;    pciba_soft_t	    soft[TRACKED_SPACES][2];    struct semaphore        lock;    pciba_dma_t             dmap;};/* pciba_soft: device_info() for all openables */struct pciba_soft_s {    pciba_comm_t	    comm;    devfs_handle_t          vhdl;    int			    refct;    pciio_space_t           space;    size_t                  size;    pciio_space_t           iomem;    pciaddr_t               base;    unsigned		    flags;};#define	pciba_soft_get(v)	(pciba_soft_t)hwgraph_fastinfo_get(v)#define	pciba_soft_set(v,i)	hwgraph_fastinfo_set(v,(arbitrary_info_t)(i))#define	pciba_soft_lock(soft)	down(&soft->comm->lock)#define	pciba_soft_unlock(soft)	up(&soft->comm->lock)/* pciba_map: data describing a mapping. * (ie. a user mmap request) */struct pciba_map_s {    pciba_map_t             next;#ifdef LATER    uthread_t              *uthread;#endif    __psunsigned_t          handle;    uvaddr_t                uvaddr;    size_t                  size;    pciio_piomap_t          map;    pciio_space_t           space;    pciaddr_t               base;    unsigned		    flags;};/* pciba_dma: data describing a DMA mapping. */struct pciba_dma_s {    pciba_dma_t             next;    iopaddr_t               paddr;	/* starting phys addr */    caddr_t                 kaddr;	/* starting kern addr */    pciio_dmamap_t          map;	/* mapping resources (ugh!) */    pciaddr_t               daddr;	/* starting pci addr */    size_t                  pages;	/* size of block in pages */    size_t                  bytes;	/* size of block in bytes */    __psunsigned_t          handle;	/* mapping handle */};/* pciba_bus: common bus info for all openables * descended from the same master vertex. */struct pciba_bus_s {    struct semaphore        lock;    pciba_map_t             maps;	/* stack of mappings */    int			    refct;};#define	pciba_bus_lock(bus)	down(&bus->lock)#define	pciba_bus_unlock(bus)	up(&bus->lock)typedef union ioctl_arg_buffer_u {    char                    data[IOCPARM_MASK + 1];    uint8_t                 uc;    uint16_t                us;    uint32_t                ui;    uint64_t                ud;    caddr_t                 ca;#if ULI    struct uliargs          uli;    struct uliargs32	    uli32;#endif} ioctl_arg_buffer_t;/* ================================================================ *            driver variables */char                   *pciba_mversion = "mload version 7.0";int                     pciba_devflag = 0x1 |                                        0x200 |                                        0x400;/* this counts the reasons why we can not * currently unload this driver. */atomic_t                pciba_prevent_unload = ATOMIC_INIT(0);#if DEBUG_PCIBAstatic struct reg_values space_v[] ={    {PCIIO_SPACE_NONE, "none"},    {PCIIO_SPACE_ROM, "ROM"},    {PCIIO_SPACE_IO, "I/O"},    {PCIIO_SPACE_MEM, "MEM"},    {PCIIO_SPACE_MEM32, "MEM(32)"},    {PCIIO_SPACE_MEM64, "MEM(64)"},    {PCIIO_SPACE_CFG, "CFG"},    {PCIIO_SPACE_WIN(0), "WIN(0)"},    {PCIIO_SPACE_WIN(1), "WIN(1)"},    {PCIIO_SPACE_WIN(2), "WIN(2)"},    {PCIIO_SPACE_WIN(3), "WIN(3)"},    {PCIIO_SPACE_WIN(4), "WIN(4)"},    {PCIIO_SPACE_WIN(5), "WIN(5)"},    {PCIBA_SPACE_UDMA, "UDMA"},    {PCIIO_SPACE_BAD, "BAD"},    {0}};static struct reg_desc  space_desc[] ={    {0xFF, 0, "space", 0, space_v},    {0}};#endifchar                    pciba_edge_lbl_base[] = "base";char                    pciba_edge_lbl_cfg[] = "config";char                    pciba_edge_lbl_dma[] = "dma";char                    pciba_edge_lbl_intr[] = "intr";char                    pciba_edge_lbl_io[] = "io";char                    pciba_edge_lbl_mem[] = "mem";char                    pciba_edge_lbl_rom[] = "rom";char                   *pciba_edge_lbl_win[6] ={"0", "1", "2", "3", "4", "5"};#define	PCIBA_EDGE_LBL_BASE	pciba_edge_lbl_base#define	PCIBA_EDGE_LBL_CFG	pciba_edge_lbl_cfg#define	PCIBA_EDGE_LBL_DMA	pciba_edge_lbl_dma#define	PCIBA_EDGE_LBL_INTR	pciba_edge_lbl_intr#define	PCIBA_EDGE_LBL_IO	pciba_edge_lbl_io#define	PCIBA_EDGE_LBL_MEM	pciba_edge_lbl_mem#define	PCIBA_EDGE_LBL_ROM	pciba_edge_lbl_rom#define	PCIBA_EDGE_LBL_WIN(n)	pciba_edge_lbl_win[n]#define	PCIBA_EDGE_LBL_FLIP	pciba_edge_lbl_flipstatic char             pciba_info_lbl_bus[] = "pciba_bus";#define	PCIBA_INFO_LBL_BUS	pciba_info_lbl_busstruct file_operations pciba_fops = {	owner:	THIS_MODULE,	llseek: NULL,	read: NULL,	write: NULL,	readdir: NULL,	poll: NULL,	ioctl: NULL,	mmap: NULL,	open: NULL,	flush: NULL,	release: NULL,	fsync: NULL,	fasync: NULL,	lock: NULL,	readv: NULL,	writev: NULL};	/* ================================================================ *            function table of contents */void                    pciba_init(void);int                     pciba_attach(devfs_handle_t);static void		pciba_sub_attach(pciba_comm_t,					 pciio_space_t, pciio_space_t, pciaddr_t,					 devfs_handle_t, devfs_handle_t, char *);static pciba_bus_t      pciba_find_bus(devfs_handle_t, int);#ifdef LATERstatic void             pciba_map_push(pciba_bus_t, pciba_map_t);static pciba_map_t      pciba_map_pop_hdl(pciba_bus_t, __psunsigned_t);static void             pciba_sub_detach(devfs_handle_t, char *);static pciio_iter_f     pciba_unload_me;#endifint                     pciba_unload(void);int                     pciba_unreg(void);int                     pciba_detach(devfs_handle_t);int                     pciba_open(dev_t *, int, int, struct cred *);int                     pciba_close(dev_t);int                     pciba_read(dev_t, cred_t *);int                     pciba_write(dev_t, cred_t *);int                     pciba_ioctl(dev_t, int, void *, int, cred_t *, int *);int                     pciba_map(dev_t, vhandl_t *, off_t, size_t, uint32_t);int                     pciba_unmap(dev_t, vhandl_t *);#if ULIvoid                    pciba_clearuli(struct uli *);static intr_func_f      pciba_intr;#endif /* Undef as it gets implemented *//* ================================================================ *            driver load, register, and setup */voidpciba_init(void){	/*	 * What do we need to do here?	 */#if DEBUG_PCIBA    printk("pciba_init()\n");#endif}#ifdef LATER#if HWG_PERF_CHECK && IP30 && !DEBUGvoidpciba_timeout(void *arg1, void *arg2){    struct semaphore       *semap = (sema_t *) arg1;    unsigned long          *cvalp = (unsigned long *) arg2;    if (cvalp)	cvalp[0] = RAW_COUNT();    if (semap)	up(semap);}volatile unsigned long  cNval[1];struct semaphore        tsema;voidpciba_timeout_test(void){    unsigned long           c0val, cval;    toid_t                  tid;    extern void             hwg_hprint(unsigned long, char *);    sema_init(&tsema, 0);    cNval[0] = 0;    c0val = RAW_COUNT();    tid = timeout((void (*)()) pciba_timeout, (void *) 0, 1, (void *) cNval);    DELAY(1000000);    cval = cNval[0];    if (cval == 0) {	untimeout(tid);	PRINT_ALERT("pciba: one-tick timeout did not happen in a second\n");	return;    }    cval = cval - c0val;    hwg_hprint(cval, "timeout(1)");    cNval[0] = 0;    c0val = RAW_COUNT();    tid = timeout((void (*)()) pciba_timeout, (void *) &tsema, 2, (void *) cNval);    /* FIXME : this probably needs to be down_interruptible() */    if (down(&tsema) < 0) {	/* wait for the pciba_timeout */	untimeout(tid);	PRINT_WARNING("pciba: timeout(2) time check aborted\n");	return;    }    cval = cNval[0];    if (cval == 0) {	untimeout(tid);	PRINT_WARNING("pciba: timeout(2) time not logged\n");	return;    }    cval = cval - c0val;    hwg_hprint(cval, "timeout(2)");    cNval[0] = 0;    c0val = RAW_COUNT();    tid = timeout((void (*)()) pciba_timeout, (void *) &tsema, HZ, (void *) cNval);    /* FIXME : this probably needs to be down_interruptible() */    if (down(&tsema) < 0) {	/* wait for the pciba_timeout */	untimeout(tid);	PRINT_WARNING("pciba: timeout(HZ) time check aborted\n");	return;    }    cval = cNval[0];    if (cval == 0) {	untimeout(tid);	PRINT_WARNING("pciba: timeout(HZ) time not logged\n");	return;    }    cval = cval - c0val;    hwg_hprint(cval, "timeout(HZ)");    printk("verifying untimeout() cancells ...\n");    cNval[0] = 0;    tid = timeout((void (*)()) pciba_timeout, (void *) 0, 2, (void *) cNval);    untimeout(tid);    DELAY(1000000);    cval = cNval[0];    if (cval != 0) {	PRINT_ALERT("pciba: unable to cancel two-tick timeout\n");	cval -= c0val;	hwg_hprint(cval, "CANCELLED timeout(2)");    }}#endifintpciba_reg(void){#if DEBUG_PCIBA    printk("pciba_reg()\n");#endif    pciio_driver_register(-1, -1, "pciba_", 0);#if HWG_PERF_CHECK && IP30 && !DEBUG    printk("%s %d\n", __FUNCTION__, __LINE__);pciba_timeout_test();#endif#if DEBUG_REFCT    {	char	       *cname = "pciba";	char	       *dname = "ptv";	char           *cpath0 = "node/xtalk/15";	char           *uname0 = "0";	char           *cpath1 = "node/xtalk/13";	char           *uname1 = "1";	devfs_handle_t conn;	devfs_handle_t conv;	devfs_handle_t vhdl;	int		ret;	printk("pciba refct tests:\n");#define	SHOWREF(vhdl,func)	printk("ref=%d\t%s\t(%d) %v\n", hwgraph_vertex_refct(vhdl), #func, vhdl, vhdl);	if (GRAPH_SUCCESS != (ret = hwgraph_path_add(hwgraph_root, cname, &conv)))	    printk("\tunable to create conv (ret=%d)\n", ret);	else {						SHOWREF(conv, hwgraph_path_add);	    if (GRAPH_SUCCESS != (ret = hwgraph_traverse(hwgraph_root, cpath0, &conn)))		printk("\tunable to find %s (ret=%d)\n", cpath0, ret);	    else {					SHOWREF(conn, hwgraph_traverse);		if (GRAPH_SUCCESS != (ret = hwgraph_char_device_add(conn, dname, "pciba_", &vhdl)))		    printk("unable to create %v/%s (ret=%d)\n", conn, dname, ret);		else {					SHOWREF(vhdl, hwgraph_char_device_add);		    hwgraph_chmod(vhdl, 0666);		SHOWREF(vhdl, hwgraph_chmod);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -