From c069bb98d20c31e40a2e7e8341d5884b42b50f78 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Mar 2000 20:23:05 +0000 Subject: * sysdeps/unix/sysv/linux/alpha/Makefile (sysdep_routines): Kill sethae. * sysdeps/unix/sysv/linux/alpha/Versions: Add pciconfig_iobase. * sysdeps/unix/sysv/linux/alpha/ioperm.c (all address constants): Use physical addresses not KSEG addresses. (io_system): Add PYXIS. (io): Remove hae.reg, sys, hae_shift. (stb_mb, stw_mb, stl_mb, __sethae): New. (inline_outb, inline_outw, inline_outl): Don't set hae. (inline_inb, inline_inw, inline_inl): Likewise. (dense_sethae): New null function. (struct cpuinfo_data): New. (process_cpuinfo): Use local and stack variables, not static. Move readlink check here from init_iosys. (init_iosys): Use __pciconfig_iobase first. Know SX and LX as PYXIS. (_iopl): Simplify. (_hae_shift): Calculate it here. * sysdeps/unix/sysv/linux/alpha/syscalls.list: Remove sethae, add pciconfig_iobase. 2000-03-20 Richard Henderson * sysdeps/unix/sysv/linux/alpha/Makefile (sysdep_routines): Kill sethae. * sysdeps/unix/sysv/linux/alpha/Versions: Add pciconfig_iobase. * sysdeps/unix/sysv/linux/alpha/ioperm.c (all address constants): Use physical addresses not KSEG addresses. (io_system): Add PYXIS. (io): Remove hae.reg, sys, hae_shift. (stb_mb, stw_mb, stl_mb, __sethae): New. (inline_outb, inline_outw, inline_outl): Don't set hae. (inline_inb, inline_inw, inline_inl): Likewise. (dense_sethae): New null function. (struct cpuinfo_data): New. (process_cpuinfo): Use local and stack variables, not static. Move readlink check here from init_iosys. (init_iosys): Use __pciconfig_iobase first. Know SX and LX as PYXIS. (_iopl): Simplify. (_hae_shift): Calculate it here. * sysdeps/unix/sysv/linux/alpha/syscalls.list: Remove sethae, add pciconfig_iobase. --- sysdeps/unix/sysv/linux/alpha/ioperm.c | 521 +++++++++++++++++++-------------- 1 file changed, 297 insertions(+), 224 deletions(-) (limited to 'sysdeps/unix/sysv/linux/alpha/ioperm.c') diff --git a/sysdeps/unix/sysv/linux/alpha/ioperm.c b/sysdeps/unix/sysv/linux/alpha/ioperm.c index 65bab818d9..310930bc21 100644 --- a/sysdeps/unix/sysv/linux/alpha/ioperm.c +++ b/sysdeps/unix/sysv/linux/alpha/ioperm.c @@ -21,11 +21,11 @@ Modern devices hopefully are sane enough not to put any performance critical registers in i/o space. - On the first call to ioperm() or _sethae(), 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). + 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 @@ -42,57 +42,62 @@ #include #include +#include -#include -#include +#include +#include #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 (0xfffffc0300000000UL) -#define JENSEN_SPARSE_MEM (0xfffffc0200000000UL) +#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 (0xfffffc01c0000000UL) -#define APECS_SPARSE_MEM (0xfffffc0200000000UL) -#define APECS_DENSE_MEM (0xfffffc0300000000UL) +#define APECS_IO_BASE (0x1c0000000UL) +#define APECS_SPARSE_MEM (0x200000000UL) +#define APECS_DENSE_MEM (0x300000000UL) -/* The same holds for CIA and PYXIS. */ -#define CIA_IO_BASE (0xfffffc8580000000UL) -#define CIA_SPARSE_MEM (0xfffffc8000000000UL) -#define CIA_DENSE_MEM (0xfffffc8600000000UL) +/* 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) -/* SABLE is EV4, GAMMA is EV5 */ -#define T2_IO_BASE (0xfffffc03a0000000UL) -#define T2_SPARSE_MEM (0xfffffc0200000000UL) -#define T2_DENSE_MEM (0xfffffc03c0000000UL) +#define PYXIS_IO_BASE (0x8900000000UL) +#define PYXIS_DENSE_MEM (0x8800000000UL) -#define GAMMA_IO_BASE (0xfffffc83a0000000UL) -#define GAMMA_SPARSE_MEM (0xfffffc8200000000UL) -#define GAMMA_DENSE_MEM (0xfffffc83c0000000UL) +/* SABLE is EV4, GAMMA is EV5 */ +#define T2_IO_BASE (0x3a0000000UL) +#define T2_SPARSE_MEM (0x200000000UL) +#define T2_DENSE_MEM (0x3c0000000UL) -/* these are for the RAWHIDE family */ -#define MCPCIA_IO_BASE (0xfffffcf980000000UL) -#define MCPCIA_SPARSE_MEM (0xfffffcf800000000UL) -#define MCPCIA_DENSE_MEM (0xfffffcf900000000UL) +#define GAMMA_IO_BASE (0x83a0000000UL) +#define GAMMA_SPARSE_MEM (0x8200000000UL) +#define GAMMA_DENSE_MEM (0x83c0000000UL) -/* Tsunami has no SPARSE space */ /* NOTE: these are hardwired to PCI bus 0 addresses!!! */ -/* Also, these are PHYSICAL, as/so there's no KSEG translation */ -#define TSUNAMI_IO_BASE (0x00000801fc000000UL + 0xfffffc0000000000UL) -#define TSUNAMI_DENSE_MEM (0x0000080000000000UL + 0xfffffc0000000000UL) +#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 (0xfffffcf9fc000000UL) -#define POLARIS_DENSE_MEM (0xfffffcf900000000UL) +/* 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_T2, + 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; @@ -102,22 +107,22 @@ typedef enum { } ioswizzle_t; static struct io_system { - int hae_shift; 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, 0}, -/* JENSEN */ {7, 0, JENSEN_SPARSE_MEM, JENSEN_IO_BASE}, -/* APECS */ {5, APECS_DENSE_MEM, APECS_SPARSE_MEM, APECS_IO_BASE}, -/* CIA */ {5, CIA_DENSE_MEM, CIA_SPARSE_MEM, CIA_IO_BASE}, -/* T2 */ {5, T2_DENSE_MEM, T2_SPARSE_MEM, T2_IO_BASE}, -/* TSUNAMI */ {0, TSUNAMI_DENSE_MEM, 0, TSUNAMI_IO_BASE}, -/* MCPCIA */ {5, MCPCIA_DENSE_MEM, MCPCIA_SPARSE_MEM, MCPCIA_IO_BASE}, -/* GAMMA */ {5, GAMMA_DENSE_MEM, GAMMA_SPARSE_MEM, GAMMA_IO_BASE}, -/* POLARIS */ {0, POLARIS_DENSE_MEM, 0, POLARIS_IO_BASE}, -/* CPUDEP */ {0, 0, 0, 0}, /* for platforms dependent on CPU type */ -/* PCIDEP */ {0, 0, 0, 0}, /* for platforms dependent on core logic */ +/* 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 { @@ -126,23 +131,23 @@ static struct platform { } platform[] = { {"Alcor", IOSYS_CIA}, {"Avanti", IOSYS_APECS}, - {"XL", 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}, - {"Noritake", IOSYS_CPUDEP}, - {"Noname", IOSYS_APECS}, - {"Sable", IOSYS_CPUDEP}, - {"Miata", IOSYS_CIA}, - {"Tsunami", IOSYS_TSUNAMI}, {"Nautilus", IOSYS_TSUNAMI}, + {"Noname", IOSYS_APECS}, + {"Noritake", IOSYS_CPUDEP}, {"Rawhide", IOSYS_MCPCIA}, - {"Ruffian", IOSYS_CIA}, + {"Ruffian", IOSYS_PYXIS}, + {"Sable", IOSYS_CPUDEP}, {"Takara", IOSYS_CIA}, + {"Tsunami", IOSYS_TSUNAMI}, + {"XL", IOSYS_APECS}, }; struct ioswtch { @@ -156,31 +161,58 @@ struct ioswtch { }; static struct { - struct hae { - unsigned long int cache; - unsigned long int * reg; - } hae; + 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; - iosys_t sys; ioswizzle_t swiz; - int hae_shift; } io; -extern void __sethae (unsigned long int); /* we can't use asm/io.h */ +static inline void +stb_mb(unsigned char val, unsigned long addr) +{ + __asm__("stb %1,%0; mb" : "=m"(*(vucp)addr) : "r"(val)); +} + +static inline void +stw_mb(unsigned short val, unsigned long addr) +{ + __asm__("stw %1,%0; mb" : "=m"(*(vusp)addr) : "r"(val)); +} + +static inline void +stl_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 int port_to_cpu_addr (unsigned long int port, ioswizzle_t ioswiz, int size) { if (ioswiz == IOSWIZZLE_SPARSE) - return (port << 5) + ((size - 1) << 3) + io.base; + return io.base + (port << 5) + ((size - 1) << 3); else if (ioswiz == IOSWIZZLE_DENSE) return port + io.base; else - return (port << 7) + ((size - 1) << 5) + io.base; + return io.base + (port << 7) + ((size - 1) << 5); } static inline void @@ -192,20 +224,20 @@ inline_sethae (unsigned long int addr, ioswizzle_t ioswiz) /* no need to set hae if msb is 0: */ msb = addr & 0xf8000000; - if (msb && msb != io.hae.cache) + if (msb && msb != io.hae_cache) { + io.hae_cache = msb; __sethae (msb); - io.hae.cache = msb; } } - else + else if (ioswiz == IOSWIZZLE_JENSEN) { - /* hae on the Jensen is bits 31:25 shifted right */ + /* HAE on the Jensen is bits 31:25 shifted right. */ addr >>= 25; - if (addr != io.hae.cache) + if (addr != io.hae_cache) { + io.hae_cache = addr; __sethae (addr); - io.hae.cache = addr; } } } @@ -216,23 +248,19 @@ inline_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); - inline_sethae (0, ioswiz); asm ("insbl %2,%1,%0" : "=r" (w) : "ri" (port & 0x3), "r" (b)); - *(vuip)addr = w; - mb (); + stl_mb(w, addr); } static inline void inline_outw (unsigned short int b, unsigned long int port, ioswizzle_t ioswiz) { - unsigned int w; + unsigned long w; unsigned long int addr = port_to_cpu_addr (port, ioswiz, 2); - inline_sethae (0, ioswiz); asm ("inswl %2,%1,%0" : "=r" (w) : "ri" (port & 0x3), "r" (b)); - *(vuip)addr = w; - mb (); + stl_mb(w, addr); } @@ -241,19 +269,17 @@ inline_outl (unsigned int b, unsigned long int port, ioswizzle_t ioswiz) { unsigned long int addr = port_to_cpu_addr (port, ioswiz, 4); - inline_sethae (0, ioswiz); - *(vuip)addr = b; - mb (); + stl_mb(b, addr); } static inline unsigned int inline_inb (unsigned long int port, ioswizzle_t ioswiz) { - unsigned long int result, addr = port_to_cpu_addr (port, ioswiz, 1); + unsigned long int addr = port_to_cpu_addr (port, ioswiz, 1); + int result; - inline_sethae (0, ioswiz); - result = *(vuip) addr; + result = *(vip) addr; result >>= (port & 3) * 8; return 0xffUL & result; } @@ -262,10 +288,10 @@ inline_inb (unsigned long int port, ioswizzle_t ioswiz) static inline unsigned int inline_inw (unsigned long int port, ioswizzle_t ioswiz) { - unsigned long int result, addr = port_to_cpu_addr (port, ioswiz, 2); + unsigned long int addr = port_to_cpu_addr (port, ioswiz, 2); + int result; - inline_sethae (0, ioswiz); - result = *(vuip) addr; + result = *(vip) addr; result >>= (port & 3) * 8; return 0xffffUL & result; } @@ -276,7 +302,6 @@ inline_inl (unsigned long int port, ioswizzle_t ioswiz) { unsigned long int addr = port_to_cpu_addr (port, ioswiz, 4); - inline_sethae (0, ioswiz); return *(vuip) addr; } @@ -303,45 +328,41 @@ static inline void inline_bwx_outb (unsigned char b, unsigned long int port) { unsigned long int addr = dense_port_to_cpu_addr (port); - - __asm__ __volatile__ ("stb %1,%0" : : "m"(*(unsigned char *)addr), "r"(b)); - mb (); + stb_mb (b, addr); } static inline void inline_bwx_outw (unsigned short int b, unsigned long int port) { unsigned long int addr = dense_port_to_cpu_addr (port); - - __asm__ __volatile__ ("stw %1,%0" : : "m"(*(unsigned short *)addr), "r"(b)); - mb (); + stw_mb (b, addr); } static inline void inline_bwx_outl (unsigned int b, unsigned long int port) { unsigned long int addr = dense_port_to_cpu_addr (port); - - *(vuip)addr = b; - mb (); + stl_mb (b, addr); } static inline unsigned int inline_bwx_inb (unsigned long int port) { - unsigned long int r, addr = dense_port_to_cpu_addr (port); + unsigned long int addr = dense_port_to_cpu_addr (port); + unsigned char r; - __asm__ __volatile__ ("ldbu %0,%1" : "=r"(r) : "m"(*(unsigned char *)addr)); - return 0xffUL & r; + __asm__ ("ldbu %0,%1" : "=r"(r) : "m"(*(vucp)addr)); + return r; } static inline unsigned int inline_bwx_inw (unsigned long int port) { - unsigned long int r, addr = dense_port_to_cpu_addr (port); + unsigned long int addr = dense_port_to_cpu_addr (port); + unsigned short r; - __asm__ __volatile__ ("ldwu %0,%1" : "=r"(r) : "m"(*(unsigned short *)addr)); - return 0xffffUL & r; + __asm__ ("ldwu %0,%1" : "=r"(r) : "m"(*(vusp)addr)); + return r; } static inline unsigned int @@ -411,6 +432,7 @@ 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) @@ -431,7 +453,7 @@ static struct ioswtch ioswtch[] = { sparse_inb, sparse_inw, sparse_inl }, { - NULL, + dense_sethae, dense_outb, dense_outw, dense_outl, dense_inb, dense_inw, dense_inl } @@ -439,171 +461,216 @@ static struct ioswtch ioswtch[] = { #undef DEBUG_IOPERM -/* routine to process the /proc/cpuinfo information into the fields */ -/* that are required for correctly determining the platform parameters */ +/* Routine to process the /proc/cpuinfo information into the fields + that are required for correctly determining the platform parameters. */ -char systype[256]; /* system type field */ -char sysvari[256]; /* system variation field */ -char cpumodel[256]; /* cpu model field */ -int got_type, got_vari, got_model; +struct cpuinfo_data +{ + char systype[256]; /* system type field */ + char sysvari[256]; /* system variation field */ + char cpumodel[256]; /* cpu model field */ +}; -static int -process_cpuinfo(void) +static inline int +process_cpuinfo(struct cpuinfo_data *data) { + int got_type, got_vari, got_model; char dummy[256]; FILE * fp; + int n; + + data->systype[0] = 0; + data->sysvari[0] = 0; + data->cpumodel[0] = 0; + + /* If there's an /etc/alpha_systype link, we're intending to override + whatever's in /proc/cpuinfo. */ + n = __readlink (PATH_ALPHA_SYSTYPE, data->systype, 256 - 1); + if (n > 0) + { + data->systype[n] = '\0'; + return 1; + } fp = fopen (PATH_CPUINFO, "r"); if (!fp) return 0; got_type = got_vari = got_model = 0; - systype[0] = sysvari[0] = cpumodel[0] = 0; while (1) { - if (fgets (dummy, 256, fp) == NULL) break; - /* fprintf(stderr, "read: %s", dummy); */ + if (fgets (dummy, 256, fp) == NULL) + break; if (!got_type && - sscanf (dummy, "system type : %256[^\n]\n", systype) == 1) + sscanf (dummy, "system type : %256[^\n]\n", data->systype) == 1) got_type = 1; if (!got_vari && - sscanf (dummy, "system variation : %256[^\n]\n", sysvari) == 1) + sscanf (dummy, "system variation : %256[^\n]\n", data->sysvari) == 1) got_vari = 1; if (!got_model && - sscanf (dummy, "cpu model : %256[^\n]\n", cpumodel) == 1) + sscanf (dummy, "cpu model : %256[^\n]\n", data->cpumodel) == 1) got_model = 1; } fclose (fp); #ifdef DEBUG_IOPERM - fprintf(stderr, "system type: %s\n", systype); - fprintf(stderr, "system vari: %s\n", sysvari); - fprintf(stderr, "cpu model: %s\n", cpumodel); + fprintf(stderr, "system type: `%s'\n", data->systype); + fprintf(stderr, "system vari: `%s'\n", data->sysvari); + fprintf(stderr, "cpu model: `%s'\n", data->cpumodel); #endif - return got_type+got_vari+got_model; + return got_type + got_vari + got_model; } + + /* - * Initialize I/O system. To determine what I/O system we're dealing - * with, we first try to read the value of symlink PATH_ALPHA_SYSTYPE, - * if that fails, we lookup the "system type" field in /proc/cpuinfo. - * If that fails as well, we give up. - * - * If the value received from PATH_ALPHA_SYSTYPE begins with a number, - * assume this is a previously unsupported system and the values encode, - * in order, ",,,". + * Initialize I/O system. */ static int init_iosys (void) { - int i, n; + long addr; + int i, olderrno = errno; + struct cpuinfo_data data; - n = readlink (PATH_ALPHA_SYSTYPE, systype, sizeof (systype) - 1); - if (n > 0) + /* First try the pciconfig_iobase syscall added to 2.2.15 and 2.3.99. */ + + addr = __pciconfig_iobase (IOBASE_DENSE_MEM, 0, 0); + if (addr != -1) { - systype[n] = '\0'; - if (isdigit (systype[0])) + ioswizzle_t io_swiz; + + if (addr == 0) + { + /* Only Jensen doesn't have dense mem space. */ + io.sparse_bus_memory_base + = io_system[IOSYS_JENSEN].sparse_bus_mem_base; + io.io_base = io_system[IOSYS_JENSEN].bus_io_base; + io_swiz = IOSWIZZLE_JENSEN; + } + else { - if (sscanf (systype, "%li,%i,%li,%li", &io.io_base, &io.hae_shift, - &io.bus_memory_base, &io.sparse_bus_memory_base) == 4) + io.bus_memory_base = addr; + + addr = __pciconfig_iobase (IOBASE_DENSE_IO, 0, 0); + if (addr != 0) + { + /* The X server uses _bus_base_sparse == 0 to know that + BWX access are supported to dense mem space. This is + true of every system that supports dense io space, so + never fill in io.sparse_bus_memory_base in this case. */ + io_swiz = IOSWIZZLE_DENSE; + io.io_base = addr; + } + else { - io.sys = IOSYS_UNKNOWN; - io.swiz = IOSWIZZLE_SPARSE; - io.swp = &ioswtch[IOSWIZZLE_SPARSE]; - return 0; + io.sparse_bus_memory_base + = __pciconfig_iobase (IOBASE_SPARSE_MEM, 0, 0); + io.io_base = __pciconfig_iobase (IOBASE_SPARSE_IO, 0, 0); + io_swiz = IOSWIZZLE_SPARSE; } - /* else we're likely going to fail with the system match below */ } + + io.swiz = io_swiz; + io.swp = &ioswtch[io_swiz]; + + return 0; } - else - { - n = process_cpuinfo(); - if (!n) - { - /* this can happen if the format of /proc/cpuinfo changes... */ - fprintf (stderr, - "ioperm.init_iosys(): Unable to determine system type.\n" - "\t(May need " PATH_ALPHA_SYSTYPE " symlink?)\n"); - __set_errno (ENODEV); - return -1; - } + /* Second, collect the contents of /etc/alpha_systype or /proc/cpuinfo. */ + + if (process_cpuinfo(&data) == 0) + { + /* This can happen if the format of /proc/cpuinfo changes. */ + fprintf (stderr, + "ioperm.init_iosys: Unable to determine system type.\n" + "\t(May need " PATH_ALPHA_SYSTYPE " symlink?)\n"); + __set_errno (ENODEV); + return -1; } - /* translate systype name into i/o system: */ + /* Translate systype name into i/o system. */ for (i = 0; i < sizeof (platform) / sizeof (platform[0]); ++i) { - if (strcmp (platform[i].name, systype) == 0) + if (strcmp (platform[i].name, data.systype) == 0) { - io.sys = platform[i].io_sys; - /* some platforms can have either EV4 or EV5 CPUs */ - if (io.sys == IOSYS_CPUDEP) /* SABLE or MIKASA or NORITAKE so far */ + iosys_t io_sys = platform[i].io_sys; + + /* Some platforms can have either EV4 or EV5 CPUs. */ + if (io_sys == IOSYS_CPUDEP) { + /* SABLE or MIKASA or NORITAKE so far. */ if (strcmp (platform[i].name, "Sable") == 0) { - if (strncmp (cpumodel, "EV4", 3) == 0) - io.sys = IOSYS_T2; - else if (strncmp (cpumodel, "EV5", 3) == 0) - io.sys = IOSYS_GAMMA; + if (strncmp (data.cpumodel, "EV4", 3) == 0) + io_sys = IOSYS_T2; + else if (strncmp (data.cpumodel, "EV5", 3) == 0) + io_sys = IOSYS_GAMMA; } else - { /* this covers MIKASA/NORITAKE */ - if (strncmp (cpumodel, "EV4", 3) == 0) - io.sys = IOSYS_APECS; - else if (strncmp (cpumodel, "EV5", 3) == 0) - io.sys = IOSYS_CIA; + { + /* This covers MIKASA/NORITAKE. */ + if (strncmp (data.cpumodel, "EV4", 3) == 0) + io_sys = IOSYS_APECS; + else if (strncmp (data.cpumodel, "EV5", 3) == 0) + io_sys = IOSYS_CIA; } - if (io.sys == IOSYS_CPUDEP) + if (io_sys == IOSYS_CPUDEP) { /* This can happen if the format of /proc/cpuinfo changes.*/ - fprintf (stderr, "ioperm.init_iosys(): Unable to determine" + fprintf (stderr, "ioperm.init_iosys: Unable to determine" " CPU model.\n"); __set_errno (ENODEV); return -1; } } - /* some platforms can have different core logic chipsets */ - if (io.sys == IOSYS_PCIDEP) /* EB164 so far */ + /* Some platforms can have different core logic chipsets */ + if (io_sys == IOSYS_PCIDEP) { - if (strcmp (systype, "EB164") == 0) + /* EB164 so far */ + if (strcmp (data.systype, "EB164") == 0) { - if (strncmp (sysvari, "RX164", 5) == 0) - io.sys = IOSYS_POLARIS; + if (strncmp (data.sysvari, "RX164", 5) == 0) + io_sys = IOSYS_POLARIS; + else if (strncmp (data.sysvari, "LX164", 5) == 0 + || strncmp (data.sysvari, "SX164", 5) == 0) + io_sys = IOSYS_PYXIS; else - io.sys = IOSYS_CIA; + io_sys = IOSYS_CIA; } - if (io.sys == IOSYS_PCIDEP) + if (io_sys == IOSYS_PCIDEP) { /* This can happen if the format of /proc/cpuinfo changes.*/ - fprintf (stderr, "ioperm.init_iosys(): Unable to determine" + fprintf (stderr, "ioperm.init_iosys: Unable to determine" " core logic chipset.\n"); __set_errno (ENODEV); return -1; } } - io.hae_shift = io_system[io.sys].hae_shift; - io.bus_memory_base = io_system[io.sys].bus_memory_base; - io.sparse_bus_memory_base = io_system[io.sys].sparse_bus_mem_base; - io.io_base = io_system[io.sys].bus_io_base; + io.bus_memory_base = io_system[io_sys].bus_memory_base; + io.sparse_bus_memory_base = io_system[io_sys].sparse_bus_mem_base; + io.io_base = io_system[io_sys].bus_io_base; - if (io.sys == IOSYS_JENSEN) + if (io_sys == IOSYS_JENSEN) io.swiz = IOSWIZZLE_JENSEN; - else if (io.sys == IOSYS_TSUNAMI || io.sys == IOSYS_POLARIS) + else if (io_sys == IOSYS_TSUNAMI + || io_sys == IOSYS_POLARIS + || io_sys == IOSYS_PYXIS) io.swiz = IOSWIZZLE_DENSE; else io.swiz = IOSWIZZLE_SPARSE; io.swp = &ioswtch[io.swiz]; + + __set_errno (olderrno); return 0; } } - /* systype is not a know platform name... */ - __set_errno (EINVAL); -#ifdef DEBUG_IOPERM - fprintf(stderr, "init_iosys: platform not recognized\n"); -#endif + __set_errno (ENODEV); + fprintf(stderr, "ioperm.init_iosys: Platform not recognized.\n" + "\t(May need " PATH_ALPHA_SYSTYPE " symlink?)\n"); return -1; } @@ -611,17 +678,18 @@ init_iosys (void) int _ioperm (unsigned long int from, unsigned long int num, int turn_on) { - unsigned long int addr, len; - int prot, err; + unsigned long int addr, len, pagesize = __getpagesize(); + int prot; - if (!io.swp && init_iosys() < 0) { + if (!io.swp && init_iosys() < 0) + { #ifdef DEBUG_IOPERM - fprintf(stderr, "ioperm: init_iosys() failed\n"); + fprintf(stderr, "ioperm: init_iosys() failed (%m)\n"); #endif - return -1; - } + return -1; + } - /* this test isn't as silly as it may look like; consider overflows! */ + /* This test isn't as silly as it may look like; consider overflows! */ if (from >= MAX_PORT || from + num > MAX_PORT) { __set_errno (EINVAL); @@ -632,7 +700,7 @@ _ioperm (unsigned long int from, unsigned long int num, int turn_on) } #ifdef DEBUG_IOPERM - fprintf(stderr, "ioperm: turn_on %d io.base %ld\n", turn_on, io.base); + fprintf(stderr, "ioperm: turn_on %d io.base %ld\n", turn_on, io.base); #endif if (turn_on) @@ -641,25 +709,28 @@ _ioperm (unsigned long int from, unsigned long int num, int turn_on) { int fd; - io.hae.reg = 0; /* not used in user-level */ - io.hae.cache = 0; + io.hae_cache = 0; if (io.swiz != IOSWIZZLE_DENSE) - __sethae (io.hae.cache); /* synchronize with hw */ + { + /* Synchronize with hw. */ + __sethae (0); + } - fd = open ("/dev/mem", O_RDWR); - if (fd < 0) { + fd = __open ("/dev/mem", O_RDWR); + if (fd < 0) + { #ifdef DEBUG_IOPERM - fprintf(stderr, "ioperm: /dev/mem open failed\n"); + fprintf(stderr, "ioperm: /dev/mem open failed (%m)\n"); #endif - return -1; - } + return -1; + } addr = port_to_cpu_addr (0, io.swiz, 1); len = port_to_cpu_addr (MAX_PORT, io.swiz, 1) - addr; io.base = (unsigned long int) __mmap (0, len, PROT_NONE, MAP_SHARED, fd, io.io_base); - close (fd); + __close (fd); #ifdef DEBUG_IOPERM fprintf(stderr, "ioperm: mmap of len 0x%lx returned 0x%lx\n", len, io.base); @@ -678,29 +749,27 @@ _ioperm (unsigned long int from, unsigned long int num, int turn_on) prot = PROT_NONE; } addr = port_to_cpu_addr (from, io.swiz, 1); - addr &= PAGE_MASK; + addr &= ~(pagesize - 1); len = port_to_cpu_addr (from + num, io.swiz, 1) - addr; - err = mprotect ((void *) addr, len, prot); -#ifdef DEBUG_IOPERM - fprintf(stderr, "ioperm: mprotect returned %d\n", err); -#endif - return err; + return __mprotect ((void *) addr, len, prot); } int -_iopl (unsigned int level) -{ - if (level > 3) - { - __set_errno (EINVAL); - return -1; - } - if (level) - { - return _ioperm (0, MAX_PORT, 1); - } - return 0; +_iopl (int level) +{ + switch (level) + { + case 0: + return 0; + + case 1: case 2: case 3: + return _ioperm (0, MAX_PORT, 1); + + default: + __set_errno (EINVAL); + return -1; + } } @@ -786,7 +855,11 @@ _hae_shift(void) { if (!io.swp && init_iosys () < 0) return -1; - return io.hae_shift; + if (io.swiz == IOSWIZZLE_JENSEN) + return 7; + if (io.swiz == IOSWIZZLE_SPARSE) + return 5; + return 0; } weak_alias (_sethae, sethae); -- cgit 1.4.1