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

📄 ioperm.c

📁 Glibc 2.3.2源代码(解压后有100多M)
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) 1992, 1996-1999, 2000 Free Software Foundation, Inc.   This file is part of the GNU C Library.   Contributed by David Mosberger.   The GNU C Library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public   License as published by the Free Software Foundation; either   version 2.1 of the License, or (at your option) any later version.   The GNU C Library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library; if not, write to the Free   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA   02111-1307 USA.  *//* I/O access is restricted to ISA port space (ports 0..65535).   Modern devices hopefully are sane enough not to put any performance   critical registers in i/o space.   On the first call to ioperm, the entire (E)ISA port space is mapped   into the virtual address space at address io.base.  mprotect calls   are then used to enable/disable access to ports.  Per page, there   are PAGE_SIZE>>IO_SHIFT I/O ports (e.g., 256 ports on a Low Cost Alpha   based system using 8KB pages).   Keep in mind that this code should be able to run in a 32bit address   space.  It is therefore unreasonable to expect mmap'ing the entire   sparse address space would work (e.g., the Low Cost Alpha chip has an   I/O address space that's 512MB large!).  */#include <errno.h>#include <fcntl.h>#include <stdio.h>#include <ctype.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/mman.h>#include <sys/io.h>#include <sysdep.h>#include <sys/syscall.h>#define PATH_ALPHA_SYSTYPE	"/etc/alpha_systype"#define PATH_CPUINFO		"/proc/cpuinfo"#define MAX_PORT	0x10000#define vip		volatile int *#define vuip		volatile unsigned int *#define vusp		volatile unsigned short *#define vucp		volatile unsigned char *#define JENSEN_IO_BASE		(0x300000000UL)#define JENSEN_SPARSE_MEM	(0x200000000UL)/* With respect to the I/O architecture, APECS and LCA are identical,   so the following defines apply to LCA as well.  */#define APECS_IO_BASE		(0x1c0000000UL)#define APECS_SPARSE_MEM	(0x200000000UL)#define APECS_DENSE_MEM		(0x300000000UL)/* The same holds for CIA and PYXIS, except for PYXIS we prefer BWX.  */#define CIA_IO_BASE		(0x8580000000UL)#define CIA_SPARSE_MEM		(0x8000000000UL)#define CIA_DENSE_MEM		(0x8600000000UL)#define PYXIS_IO_BASE		(0x8900000000UL)#define PYXIS_DENSE_MEM		(0x8800000000UL)/* SABLE is EV4, GAMMA is EV5 */#define T2_IO_BASE		(0x3a0000000UL)#define T2_SPARSE_MEM		(0x200000000UL)#define T2_DENSE_MEM		(0x3c0000000UL)#define GAMMA_IO_BASE		(0x83a0000000UL)#define GAMMA_SPARSE_MEM	(0x8200000000UL)#define GAMMA_DENSE_MEM		(0x83c0000000UL)/* NOTE: these are hardwired to PCI bus 0 addresses!!! */#define MCPCIA_IO_BASE		(0xf980000000UL)#define MCPCIA_SPARSE_MEM	(0xf800000000UL)#define MCPCIA_DENSE_MEM	(0xf900000000UL)/* Tsunami and Irongate use the same offsets, at least for hose 0.  */#define TSUNAMI_IO_BASE		(0x801fc000000UL)#define TSUNAMI_DENSE_MEM	(0x80000000000UL)/* Polaris has SPARSE space, but we prefer to use only DENSE   because of some idiosyncracies in actually using SPARSE.  */#define POLARIS_IO_BASE		(0xf9fc000000UL)#define POLARIS_DENSE_MEM	(0xf900000000UL)typedef enum {  IOSYS_UNKNOWN, IOSYS_JENSEN, IOSYS_APECS, IOSYS_CIA, IOSYS_PYXIS, IOSYS_T2,  IOSYS_TSUNAMI, IOSYS_MCPCIA, IOSYS_GAMMA, IOSYS_POLARIS,  IOSYS_CPUDEP, IOSYS_PCIDEP} iosys_t;typedef enum {  IOSWIZZLE_JENSEN, IOSWIZZLE_SPARSE, IOSWIZZLE_DENSE} ioswizzle_t;static struct io_system {  unsigned long	int bus_memory_base;  unsigned long	int sparse_bus_mem_base;  unsigned long	int bus_io_base;} io_system[] = { /* NOTE! must match iosys_t enumeration *//* UNKNOWN */	{0, 0, 0},/* JENSEN */	{0, JENSEN_SPARSE_MEM, JENSEN_IO_BASE},/* APECS */	{APECS_DENSE_MEM, APECS_SPARSE_MEM, APECS_IO_BASE},/* CIA */	{CIA_DENSE_MEM, CIA_SPARSE_MEM, CIA_IO_BASE},/* PYXIS */	{PYXIS_DENSE_MEM, 0, PYXIS_IO_BASE},/* T2 */	{T2_DENSE_MEM, T2_SPARSE_MEM, T2_IO_BASE},/* TSUNAMI */	{TSUNAMI_DENSE_MEM, 0, TSUNAMI_IO_BASE},/* MCPCIA */	{MCPCIA_DENSE_MEM, MCPCIA_SPARSE_MEM, MCPCIA_IO_BASE},/* GAMMA */	{GAMMA_DENSE_MEM, GAMMA_SPARSE_MEM, GAMMA_IO_BASE},/* POLARIS */	{POLARIS_DENSE_MEM, 0, POLARIS_IO_BASE},/* CPUDEP */	{0, 0, 0}, /* for platforms dependent on CPU type *//* PCIDEP */	{0, 0, 0}, /* for platforms dependent on core logic */};static struct platform {  const char	   *name;  iosys_t	    io_sys;} platform[] = {  {"Alcor",	IOSYS_CIA},  {"Avanti",	IOSYS_APECS},  {"Cabriolet",	IOSYS_APECS},  {"EB164",	IOSYS_PCIDEP},  {"EB64+",	IOSYS_APECS},  {"EB66",	IOSYS_APECS},  {"EB66P",	IOSYS_APECS},  {"Jensen",	IOSYS_JENSEN},  {"Miata",	IOSYS_PYXIS},  {"Mikasa",	IOSYS_CPUDEP},  {"Nautilus",	IOSYS_TSUNAMI},  {"Noname",	IOSYS_APECS},  {"Noritake",	IOSYS_CPUDEP},  {"Rawhide",	IOSYS_MCPCIA},  {"Ruffian",	IOSYS_PYXIS},  {"Sable",	IOSYS_CPUDEP},  {"Takara",	IOSYS_CIA},  {"Tsunami",	IOSYS_TSUNAMI},  {"XL",	IOSYS_APECS},};struct ioswtch {  void		(*sethae)(unsigned long int addr);  void		(*outb)(unsigned char b, unsigned long int port);  void		(*outw)(unsigned short b, unsigned long int port);  void		(*outl)(unsigned int b, unsigned long int port);  unsigned int	(*inb)(unsigned long int port);  unsigned int	(*inw)(unsigned long int port);  unsigned int	(*inl)(unsigned long int port);};static struct {  unsigned long int hae_cache;  unsigned long int	base;  struct ioswtch *	swp;  unsigned long int	bus_memory_base;  unsigned long int	sparse_bus_memory_base;  unsigned long int	io_base;  ioswizzle_t		swiz;} io;static inline voidstb_mb(unsigned char val, unsigned long addr){  __asm__("stb %1,%0; mb" : "=m"(*(vucp)addr) : "r"(val));}static inline voidstw_mb(unsigned short val, unsigned long addr){  __asm__("stw %1,%0; mb" : "=m"(*(vusp)addr) : "r"(val));}static inline voidstl_mb(unsigned int val, unsigned long addr){  __asm__("stl %1,%0; mb" : "=m"(*(vip)addr) : "r"(val));}/* No need to examine error -- sethae never fails.  */static inline void__sethae(unsigned long value){  register unsigned long r16 __asm__("$16") = value;  register unsigned long r0 __asm__("$0") = __NR_sethae;  __asm__ __volatile__ ("callsys"			: "=r"(r0)			: "0"(r0), "r" (r16)			: inline_syscall_clobbers, "$19");}extern long __pciconfig_iobase(enum __pciconfig_iobase_which __which,			       unsigned long int __bus,			       unsigned long int __dfn);static inline unsigned long intport_to_cpu_addr (unsigned long int port, ioswizzle_t ioswiz, int size){  if (ioswiz == IOSWIZZLE_SPARSE)    return io.base + (port << 5) + ((size - 1) << 3);  else if (ioswiz == IOSWIZZLE_DENSE)    return port + io.base;  else    return io.base + (port << 7) + ((size - 1) << 5);}static inline voidinline_sethae (unsigned long int addr, ioswizzle_t ioswiz){  if (ioswiz == IOSWIZZLE_SPARSE)    {      unsigned long int msb;      /* no need to set hae if msb is 0: */      msb = addr & 0xf8000000;      if (msb && msb != io.hae_cache)	{	  io.hae_cache = msb;	  __sethae (msb);	}    }  else if (ioswiz == IOSWIZZLE_JENSEN)    {      /* HAE on the Jensen is bits 31:25 shifted right.  */      addr >>= 25;      if (addr != io.hae_cache)	{	  io.hae_cache = addr;	  __sethae (addr);	}    }}static inline voidinline_outb (unsigned char b, unsigned long int port, ioswizzle_t ioswiz){  unsigned int w;  unsigned long int addr = port_to_cpu_addr (port, ioswiz, 1);  asm ("insbl %2,%1,%0" : "=r" (w) : "ri" (port & 0x3), "r" (b));  stl_mb(w, addr);}static inline voidinline_outw (unsigned short int b, unsigned long int port, ioswizzle_t ioswiz){  unsigned long w;  unsigned long int addr = port_to_cpu_addr (port, ioswiz, 2);  asm ("inswl %2,%1,%0" : "=r" (w) : "ri" (port & 0x3), "r" (b));  stl_mb(w, addr);}static inline voidinline_outl (unsigned int b, unsigned long int port, ioswizzle_t ioswiz){  unsigned long int addr = port_to_cpu_addr (port, ioswiz, 4);  stl_mb(b, addr);}static inline unsigned intinline_inb (unsigned long int port, ioswizzle_t ioswiz){  unsigned long int addr = port_to_cpu_addr (port, ioswiz, 1);  int result;  result = *(vip) addr;  result >>= (port & 3) * 8;  return 0xffUL & result;}static inline unsigned intinline_inw (unsigned long int port, ioswizzle_t ioswiz){  unsigned long int addr = port_to_cpu_addr (port, ioswiz, 2);  int result;  result = *(vip) addr;  result >>= (port & 3) * 8;  return 0xffffUL & result;}static inline unsigned intinline_inl (unsigned long int port, ioswizzle_t ioswiz){  unsigned long int addr = port_to_cpu_addr (port, ioswiz, 4);  return *(vuip) addr;}/* * Now define the inline functions for CPUs supporting byte/word insns, * and whose core logic supports I/O space accesses utilizing them. * * These routines could be used by MIATA, for example, because it has * and EV56 plus PYXIS, but it currently uses SPARSE anyway. This is * also true of RX164 which used POLARIS, but we will choose to use * these routines in that case instead of SPARSE. * * These routines are necessary for TSUNAMI/TYPHOON based platforms, * which will have (at least) EV6. */static inline unsigned long intdense_port_to_cpu_addr (unsigned long int port){  return port + io.base;}static inline voidinline_bwx_outb (unsigned char b, unsigned long int port){  unsigned long int addr = dense_port_to_cpu_addr (port);  stb_mb (b, addr);}static inline voidinline_bwx_outw (unsigned short int b, unsigned long int port){  unsigned long int addr = dense_port_to_cpu_addr (port);  stw_mb (b, addr);}static inline voidinline_bwx_outl (unsigned int b, unsigned long int port){  unsigned long int addr = dense_port_to_cpu_addr (port);  stl_mb (b, addr);}static inline unsigned intinline_bwx_inb (unsigned long int port){  unsigned long int addr = dense_port_to_cpu_addr (port);  unsigned char r;  __asm__ ("ldbu %0,%1" : "=r"(r) : "m"(*(vucp)addr));  return r;}static inline unsigned intinline_bwx_inw (unsigned long int port){  unsigned long int addr = dense_port_to_cpu_addr (port);  unsigned short r;  __asm__ ("ldwu %0,%1" : "=r"(r) : "m"(*(vusp)addr));  return r;}static inline unsigned intinline_bwx_inl (unsigned long int port){  unsigned long int addr = dense_port_to_cpu_addr (port);  return *(vuip) addr;}/* macros to define routines with appropriate names and functions *//* these do either SPARSE or JENSEN swizzle */#define DCL_SETHAE(name, ioswiz)                        \static void                                             \name##_sethae (unsigned long int addr)                  \{                                                       \  inline_sethae (addr, IOSWIZZLE_##ioswiz);             \}#define DCL_OUT(name, func, type, ioswiz)		\static void						\name##_##func (unsigned type b, unsigned long int addr)	\{							\  inline_##func (b, addr, IOSWIZZLE_##ioswiz);		\}#define DCL_IN(name, func, ioswiz)			\static unsigned int					\name##_##func (unsigned long int addr)			\{							\  return inline_##func (addr, IOSWIZZLE_##ioswiz);	\}/* these do DENSE, so no swizzle is needed */#define DCL_OUT_BWX(name, func, type)			\static void						\name##_##func (unsigned type b, unsigned long int addr)	\{							\  inline_bwx_##func (b, addr);				\}#define DCL_IN_BWX(name, func)				\static unsigned int					\name##_##func (unsigned long int addr)			\{							\  return inline_bwx_##func (addr);			\}/* now declare/define the necessary routines */DCL_SETHAE(jensen, JENSEN)DCL_OUT(jensen, outb, char,  JENSEN)DCL_OUT(jensen, outw, short int, JENSEN)DCL_OUT(jensen, outl, int,   JENSEN)DCL_IN(jensen, inb, JENSEN)DCL_IN(jensen, inw, JENSEN)DCL_IN(jensen, inl, JENSEN)DCL_SETHAE(sparse, SPARSE)DCL_OUT(sparse, outb, char,  SPARSE)DCL_OUT(sparse, outw, short int, SPARSE)DCL_OUT(sparse, outl, int,   SPARSE)DCL_IN(sparse, inb, SPARSE)DCL_IN(sparse, inw, SPARSE)DCL_IN(sparse, inl, SPARSE)DCL_SETHAE(dense, DENSE)DCL_OUT_BWX(dense, outb, char)DCL_OUT_BWX(dense, outw, short int)DCL_OUT_BWX(dense, outl, int)DCL_IN_BWX(dense, inb)DCL_IN_BWX(dense, inw)

⌨️ 快捷键说明

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