* 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.
This commit is contained in:
Richard Henderson 2000-03-20 20:23:05 +00:00
parent 59e14c2112
commit 194b9b3b26
5 changed files with 320 additions and 228 deletions

View File

@ -6,7 +6,7 @@ ifeq ($(subdir),misc)
sysdep_headers += alpha/ptrace.h alpha/regdef.h sys/io.h sysdep_headers += alpha/ptrace.h alpha/regdef.h sys/io.h
sysdep_routines += ieee_get_fp_control ieee_set_fp_control \ sysdep_routines += ieee_get_fp_control ieee_set_fp_control \
sethae ioperm osf_sigprocmask llseek adjtimex ioperm osf_sigprocmask llseek adjtimex
# Support old timeval32 entry points # Support old timeval32 entry points
sysdep_routines += osf_select osf_gettimeofday osf_settimeofday \ sysdep_routines += osf_select osf_gettimeofday osf_settimeofday \

View File

@ -46,4 +46,7 @@ libc {
# w* # w*
wait4; wait4;
} }
GLIBC_2.1.3 {
pciconfig_iobase;
}
} }

View File

@ -21,11 +21,11 @@
Modern devices hopefully are sane enough not to put any performance Modern devices hopefully are sane enough not to put any performance
critical registers in i/o space. critical registers in i/o space.
On the first call to ioperm() or _sethae(), the entire (E)ISA port On the first call to ioperm, the entire (E)ISA port space is mapped
space is mapped into the virtual address space at address io.base. into the virtual address space at address io.base. mprotect calls
mprotect() calls are then used to enable/disable access to ports. Per are then used to enable/disable access to ports. Per page, there
page, there are PAGE_SIZE>>IO_SHIFT I/O ports (e.g., 256 ports on a are PAGE_SIZE>>IO_SHIFT I/O ports (e.g., 256 ports on a Low Cost Alpha
Low Cost Alpha based system using 8KB pages). based system using 8KB pages).
Keep in mind that this code should be able to run in a 32bit address 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 space. It is therefore unreasonable to expect mmap'ing the entire
@ -42,57 +42,62 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/io.h>
#include <asm/page.h> #include <sysdep.h>
#include <asm/system.h> #include <sys/syscall.h>
#define PATH_ALPHA_SYSTYPE "/etc/alpha_systype" #define PATH_ALPHA_SYSTYPE "/etc/alpha_systype"
#define PATH_CPUINFO "/proc/cpuinfo" #define PATH_CPUINFO "/proc/cpuinfo"
#define MAX_PORT 0x10000 #define MAX_PORT 0x10000
#define vip volatile int *
#define vuip volatile unsigned int * #define vuip volatile unsigned int *
#define vusp volatile unsigned short *
#define vucp volatile unsigned char *
#define JENSEN_IO_BASE (0xfffffc0300000000UL) #define JENSEN_IO_BASE (0x300000000UL)
#define JENSEN_SPARSE_MEM (0xfffffc0200000000UL) #define JENSEN_SPARSE_MEM (0x200000000UL)
/* With respect to the I/O architecture, APECS and LCA are identical, /* With respect to the I/O architecture, APECS and LCA are identical,
so the following defines apply to LCA as well. */ so the following defines apply to LCA as well. */
#define APECS_IO_BASE (0xfffffc01c0000000UL) #define APECS_IO_BASE (0x1c0000000UL)
#define APECS_SPARSE_MEM (0xfffffc0200000000UL) #define APECS_SPARSE_MEM (0x200000000UL)
#define APECS_DENSE_MEM (0xfffffc0300000000UL) #define APECS_DENSE_MEM (0x300000000UL)
/* The same holds for CIA and PYXIS. */ /* The same holds for CIA and PYXIS, except for PYXIS we prefer BWX. */
#define CIA_IO_BASE (0xfffffc8580000000UL) #define CIA_IO_BASE (0x8580000000UL)
#define CIA_SPARSE_MEM (0xfffffc8000000000UL) #define CIA_SPARSE_MEM (0x8000000000UL)
#define CIA_DENSE_MEM (0xfffffc8600000000UL) #define CIA_DENSE_MEM (0x8600000000UL)
#define PYXIS_IO_BASE (0x8900000000UL)
#define PYXIS_DENSE_MEM (0x8800000000UL)
/* SABLE is EV4, GAMMA is EV5 */ /* SABLE is EV4, GAMMA is EV5 */
#define T2_IO_BASE (0xfffffc03a0000000UL) #define T2_IO_BASE (0x3a0000000UL)
#define T2_SPARSE_MEM (0xfffffc0200000000UL) #define T2_SPARSE_MEM (0x200000000UL)
#define T2_DENSE_MEM (0xfffffc03c0000000UL) #define T2_DENSE_MEM (0x3c0000000UL)
#define GAMMA_IO_BASE (0xfffffc83a0000000UL) #define GAMMA_IO_BASE (0x83a0000000UL)
#define GAMMA_SPARSE_MEM (0xfffffc8200000000UL) #define GAMMA_SPARSE_MEM (0x8200000000UL)
#define GAMMA_DENSE_MEM (0xfffffc83c0000000UL) #define GAMMA_DENSE_MEM (0x83c0000000UL)
/* these are for the RAWHIDE family */
#define MCPCIA_IO_BASE (0xfffffcf980000000UL)
#define MCPCIA_SPARSE_MEM (0xfffffcf800000000UL)
#define MCPCIA_DENSE_MEM (0xfffffcf900000000UL)
/* Tsunami has no SPARSE space */
/* NOTE: these are hardwired to PCI bus 0 addresses!!! */ /* NOTE: these are hardwired to PCI bus 0 addresses!!! */
/* Also, these are PHYSICAL, as/so there's no KSEG translation */ #define MCPCIA_IO_BASE (0xf980000000UL)
#define TSUNAMI_IO_BASE (0x00000801fc000000UL + 0xfffffc0000000000UL) #define MCPCIA_SPARSE_MEM (0xf800000000UL)
#define TSUNAMI_DENSE_MEM (0x0000080000000000UL + 0xfffffc0000000000UL) #define MCPCIA_DENSE_MEM (0xf900000000UL)
/* Polaris has SPARSE space, but we prefer to use only DENSE */ /* Tsunami and Irongate use the same offsets, at least for hose 0. */
/* because of some idiosyncracies in actually using SPARSE */ #define TSUNAMI_IO_BASE (0x801fc000000UL)
#define POLARIS_IO_BASE (0xfffffcf9fc000000UL) #define TSUNAMI_DENSE_MEM (0x80000000000UL)
#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 { 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_TSUNAMI, IOSYS_MCPCIA, IOSYS_GAMMA, IOSYS_POLARIS,
IOSYS_CPUDEP, IOSYS_PCIDEP IOSYS_CPUDEP, IOSYS_PCIDEP
} iosys_t; } iosys_t;
@ -102,22 +107,22 @@ typedef enum {
} ioswizzle_t; } ioswizzle_t;
static struct io_system { static struct io_system {
int hae_shift;
unsigned long int bus_memory_base; unsigned long int bus_memory_base;
unsigned long int sparse_bus_mem_base; unsigned long int sparse_bus_mem_base;
unsigned long int bus_io_base; unsigned long int bus_io_base;
} io_system[] = { /* NOTE! must match iosys_t enumeration */ } io_system[] = { /* NOTE! must match iosys_t enumeration */
/* UNKNOWN */ {0, 0, 0, 0}, /* UNKNOWN */ {0, 0, 0},
/* JENSEN */ {7, 0, JENSEN_SPARSE_MEM, JENSEN_IO_BASE}, /* JENSEN */ {0, JENSEN_SPARSE_MEM, JENSEN_IO_BASE},
/* APECS */ {5, APECS_DENSE_MEM, APECS_SPARSE_MEM, APECS_IO_BASE}, /* APECS */ {APECS_DENSE_MEM, APECS_SPARSE_MEM, APECS_IO_BASE},
/* CIA */ {5, CIA_DENSE_MEM, CIA_SPARSE_MEM, CIA_IO_BASE}, /* CIA */ {CIA_DENSE_MEM, CIA_SPARSE_MEM, CIA_IO_BASE},
/* T2 */ {5, T2_DENSE_MEM, T2_SPARSE_MEM, T2_IO_BASE}, /* PYXIS */ {PYXIS_DENSE_MEM, 0, PYXIS_IO_BASE},
/* TSUNAMI */ {0, TSUNAMI_DENSE_MEM, 0, TSUNAMI_IO_BASE}, /* T2 */ {T2_DENSE_MEM, T2_SPARSE_MEM, T2_IO_BASE},
/* MCPCIA */ {5, MCPCIA_DENSE_MEM, MCPCIA_SPARSE_MEM, MCPCIA_IO_BASE}, /* TSUNAMI */ {TSUNAMI_DENSE_MEM, 0, TSUNAMI_IO_BASE},
/* GAMMA */ {5, GAMMA_DENSE_MEM, GAMMA_SPARSE_MEM, GAMMA_IO_BASE}, /* MCPCIA */ {MCPCIA_DENSE_MEM, MCPCIA_SPARSE_MEM, MCPCIA_IO_BASE},
/* POLARIS */ {0, POLARIS_DENSE_MEM, 0, POLARIS_IO_BASE}, /* GAMMA */ {GAMMA_DENSE_MEM, GAMMA_SPARSE_MEM, GAMMA_IO_BASE},
/* CPUDEP */ {0, 0, 0, 0}, /* for platforms dependent on CPU type */ /* POLARIS */ {POLARIS_DENSE_MEM, 0, POLARIS_IO_BASE},
/* PCIDEP */ {0, 0, 0, 0}, /* for platforms dependent on core logic */ /* CPUDEP */ {0, 0, 0}, /* for platforms dependent on CPU type */
/* PCIDEP */ {0, 0, 0}, /* for platforms dependent on core logic */
}; };
static struct platform { static struct platform {
@ -126,23 +131,23 @@ static struct platform {
} platform[] = { } platform[] = {
{"Alcor", IOSYS_CIA}, {"Alcor", IOSYS_CIA},
{"Avanti", IOSYS_APECS}, {"Avanti", IOSYS_APECS},
{"XL", IOSYS_APECS},
{"Cabriolet", IOSYS_APECS}, {"Cabriolet", IOSYS_APECS},
{"EB164", IOSYS_PCIDEP}, {"EB164", IOSYS_PCIDEP},
{"EB64+", IOSYS_APECS}, {"EB64+", IOSYS_APECS},
{"EB66", IOSYS_APECS}, {"EB66", IOSYS_APECS},
{"EB66P", IOSYS_APECS}, {"EB66P", IOSYS_APECS},
{"Jensen", IOSYS_JENSEN}, {"Jensen", IOSYS_JENSEN},
{"Miata", IOSYS_PYXIS},
{"Mikasa", IOSYS_CPUDEP}, {"Mikasa", IOSYS_CPUDEP},
{"Noritake", IOSYS_CPUDEP},
{"Noname", IOSYS_APECS},
{"Sable", IOSYS_CPUDEP},
{"Miata", IOSYS_CIA},
{"Tsunami", IOSYS_TSUNAMI},
{"Nautilus", IOSYS_TSUNAMI}, {"Nautilus", IOSYS_TSUNAMI},
{"Noname", IOSYS_APECS},
{"Noritake", IOSYS_CPUDEP},
{"Rawhide", IOSYS_MCPCIA}, {"Rawhide", IOSYS_MCPCIA},
{"Ruffian", IOSYS_CIA}, {"Ruffian", IOSYS_PYXIS},
{"Sable", IOSYS_CPUDEP},
{"Takara", IOSYS_CIA}, {"Takara", IOSYS_CIA},
{"Tsunami", IOSYS_TSUNAMI},
{"XL", IOSYS_APECS},
}; };
struct ioswtch { struct ioswtch {
@ -156,31 +161,58 @@ struct ioswtch {
}; };
static struct { static struct {
struct hae { unsigned long int hae_cache;
unsigned long int cache;
unsigned long int * reg;
} hae;
unsigned long int base; unsigned long int base;
struct ioswtch * swp; struct ioswtch * swp;
unsigned long int bus_memory_base; unsigned long int bus_memory_base;
unsigned long int sparse_bus_memory_base; unsigned long int sparse_bus_memory_base;
unsigned long int io_base; unsigned long int io_base;
iosys_t sys;
ioswizzle_t swiz; ioswizzle_t swiz;
int hae_shift;
} io; } 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 static inline unsigned long int
port_to_cpu_addr (unsigned long int port, ioswizzle_t ioswiz, int size) port_to_cpu_addr (unsigned long int port, ioswizzle_t ioswiz, int size)
{ {
if (ioswiz == IOSWIZZLE_SPARSE) 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) else if (ioswiz == IOSWIZZLE_DENSE)
return port + io.base; return port + io.base;
else else
return (port << 7) + ((size - 1) << 5) + io.base; return io.base + (port << 7) + ((size - 1) << 5);
} }
static inline void 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: */ /* no need to set hae if msb is 0: */
msb = addr & 0xf8000000; msb = addr & 0xf8000000;
if (msb && msb != io.hae.cache) if (msb && msb != io.hae_cache)
{ {
io.hae_cache = msb;
__sethae (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; addr >>= 25;
if (addr != io.hae.cache) if (addr != io.hae_cache)
{ {
io.hae_cache = addr;
__sethae (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 int w;
unsigned long int addr = port_to_cpu_addr (port, ioswiz, 1); 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)); asm ("insbl %2,%1,%0" : "=r" (w) : "ri" (port & 0x3), "r" (b));
*(vuip)addr = w; stl_mb(w, addr);
mb ();
} }
static inline void static inline void
inline_outw (unsigned short int b, unsigned long int port, ioswizzle_t ioswiz) 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); 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)); asm ("inswl %2,%1,%0" : "=r" (w) : "ri" (port & 0x3), "r" (b));
*(vuip)addr = w; stl_mb(w, addr);
mb ();
} }
@ -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); unsigned long int addr = port_to_cpu_addr (port, ioswiz, 4);
inline_sethae (0, ioswiz); stl_mb(b, addr);
*(vuip)addr = b;
mb ();
} }
static inline unsigned int static inline unsigned int
inline_inb (unsigned long int port, ioswizzle_t ioswiz) 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 = *(vip) addr;
result = *(vuip) addr;
result >>= (port & 3) * 8; result >>= (port & 3) * 8;
return 0xffUL & result; return 0xffUL & result;
} }
@ -262,10 +288,10 @@ inline_inb (unsigned long int port, ioswizzle_t ioswiz)
static inline unsigned int static inline unsigned int
inline_inw (unsigned long int port, ioswizzle_t ioswiz) 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 = *(vip) addr;
result = *(vuip) addr;
result >>= (port & 3) * 8; result >>= (port & 3) * 8;
return 0xffffUL & result; 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); unsigned long int addr = port_to_cpu_addr (port, ioswiz, 4);
inline_sethae (0, ioswiz);
return *(vuip) addr; return *(vuip) addr;
} }
@ -303,45 +328,41 @@ static inline void
inline_bwx_outb (unsigned char b, unsigned long int port) inline_bwx_outb (unsigned char b, unsigned long int port)
{ {
unsigned long int addr = dense_port_to_cpu_addr (port); unsigned long int addr = dense_port_to_cpu_addr (port);
stb_mb (b, addr);
__asm__ __volatile__ ("stb %1,%0" : : "m"(*(unsigned char *)addr), "r"(b));
mb ();
} }
static inline void static inline void
inline_bwx_outw (unsigned short int b, unsigned long int port) inline_bwx_outw (unsigned short int b, unsigned long int port)
{ {
unsigned long int addr = dense_port_to_cpu_addr (port); unsigned long int addr = dense_port_to_cpu_addr (port);
stw_mb (b, addr);
__asm__ __volatile__ ("stw %1,%0" : : "m"(*(unsigned short *)addr), "r"(b));
mb ();
} }
static inline void static inline void
inline_bwx_outl (unsigned int b, unsigned long int port) inline_bwx_outl (unsigned int b, unsigned long int port)
{ {
unsigned long int addr = dense_port_to_cpu_addr (port); unsigned long int addr = dense_port_to_cpu_addr (port);
stl_mb (b, addr);
*(vuip)addr = b;
mb ();
} }
static inline unsigned int static inline unsigned int
inline_bwx_inb (unsigned long int port) 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)); __asm__ ("ldbu %0,%1" : "=r"(r) : "m"(*(vucp)addr));
return 0xffUL & r; return r;
} }
static inline unsigned int static inline unsigned int
inline_bwx_inw (unsigned long int port) 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)); __asm__ ("ldwu %0,%1" : "=r"(r) : "m"(*(vusp)addr));
return 0xffffUL & r; return r;
} }
static inline unsigned int static inline unsigned int
@ -411,6 +432,7 @@ DCL_IN(sparse, inb, SPARSE)
DCL_IN(sparse, inw, SPARSE) DCL_IN(sparse, inw, SPARSE)
DCL_IN(sparse, inl, SPARSE) DCL_IN(sparse, inl, SPARSE)
DCL_SETHAE(dense, DENSE)
DCL_OUT_BWX(dense, outb, char) DCL_OUT_BWX(dense, outb, char)
DCL_OUT_BWX(dense, outw, short int) DCL_OUT_BWX(dense, outw, short int)
DCL_OUT_BWX(dense, outl, int) DCL_OUT_BWX(dense, outl, int)
@ -431,7 +453,7 @@ static struct ioswtch ioswtch[] = {
sparse_inb, sparse_inw, sparse_inl sparse_inb, sparse_inw, sparse_inl
}, },
{ {
NULL, dense_sethae,
dense_outb, dense_outw, dense_outl, dense_outb, dense_outw, dense_outl,
dense_inb, dense_inw, dense_inl dense_inb, dense_inw, dense_inl
} }
@ -439,171 +461,216 @@ static struct ioswtch ioswtch[] = {
#undef DEBUG_IOPERM #undef DEBUG_IOPERM
/* routine to process the /proc/cpuinfo information into the fields */ /* Routine to process the /proc/cpuinfo information into the fields
/* that are required for correctly determining the platform parameters */ that are required for correctly determining the platform parameters. */
struct cpuinfo_data
{
char systype[256]; /* system type field */ char systype[256]; /* system type field */
char sysvari[256]; /* system variation field */ char sysvari[256]; /* system variation field */
char cpumodel[256]; /* cpu model field */ char cpumodel[256]; /* cpu model field */
int got_type, got_vari, got_model; };
static int static inline int
process_cpuinfo(void) process_cpuinfo(struct cpuinfo_data *data)
{ {
int got_type, got_vari, got_model;
char dummy[256]; char dummy[256];
FILE * fp; 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"); fp = fopen (PATH_CPUINFO, "r");
if (!fp) if (!fp)
return 0; return 0;
got_type = got_vari = got_model = 0; got_type = got_vari = got_model = 0;
systype[0] = sysvari[0] = cpumodel[0] = 0;
while (1) while (1)
{ {
if (fgets (dummy, 256, fp) == NULL) break; if (fgets (dummy, 256, fp) == NULL)
/* fprintf(stderr, "read: %s", dummy); */ break;
if (!got_type && 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; got_type = 1;
if (!got_vari && 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; got_vari = 1;
if (!got_model && 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; got_model = 1;
} }
fclose (fp); fclose (fp);
#ifdef DEBUG_IOPERM #ifdef DEBUG_IOPERM
fprintf(stderr, "system type: %s\n", systype); fprintf(stderr, "system type: `%s'\n", data->systype);
fprintf(stderr, "system vari: %s\n", sysvari); fprintf(stderr, "system vari: `%s'\n", data->sysvari);
fprintf(stderr, "cpu model: %s\n", cpumodel); fprintf(stderr, "cpu model: `%s'\n", data->cpumodel);
#endif #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 * Initialize I/O system.
* 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, "<io_base>,<hae_shift>,<dense_base>,<sparse_base>".
*/ */
static int static int
init_iosys (void) 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); /* First try the pciconfig_iobase syscall added to 2.2.15 and 2.3.99. */
if (n > 0)
addr = __pciconfig_iobase (IOBASE_DENSE_MEM, 0, 0);
if (addr != -1)
{ {
systype[n] = '\0'; ioswizzle_t io_swiz;
if (isdigit (systype[0]))
if (addr == 0)
{ {
if (sscanf (systype, "%li,%i,%li,%li", &io.io_base, &io.hae_shift, /* Only Jensen doesn't have dense mem space. */
&io.bus_memory_base, &io.sparse_bus_memory_base) == 4) io.sparse_bus_memory_base
{ = io_system[IOSYS_JENSEN].sparse_bus_mem_base;
io.sys = IOSYS_UNKNOWN; io.io_base = io_system[IOSYS_JENSEN].bus_io_base;
io.swiz = IOSWIZZLE_SPARSE; io_swiz = IOSWIZZLE_JENSEN;
io.swp = &ioswtch[IOSWIZZLE_SPARSE];
return 0;
}
/* else we're likely going to fail with the system match below */
}
} }
else else
{ {
n = process_cpuinfo(); io.bus_memory_base = addr;
if (!n) addr = __pciconfig_iobase (IOBASE_DENSE_IO, 0, 0);
if (addr != 0)
{ {
/* this can happen if the format of /proc/cpuinfo changes... */ /* 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.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;
}
}
io.swiz = io_swiz;
io.swp = &ioswtch[io_swiz];
return 0;
}
/* 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, fprintf (stderr,
"ioperm.init_iosys(): Unable to determine system type.\n" "ioperm.init_iosys: Unable to determine system type.\n"
"\t(May need " PATH_ALPHA_SYSTYPE " symlink?)\n"); "\t(May need " PATH_ALPHA_SYSTYPE " symlink?)\n");
__set_errno (ENODEV); __set_errno (ENODEV);
return -1; 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) 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; 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 */ /* 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 (strcmp (platform[i].name, "Sable") == 0)
{ {
if (strncmp (cpumodel, "EV4", 3) == 0) if (strncmp (data.cpumodel, "EV4", 3) == 0)
io.sys = IOSYS_T2; io_sys = IOSYS_T2;
else if (strncmp (cpumodel, "EV5", 3) == 0) else if (strncmp (data.cpumodel, "EV5", 3) == 0)
io.sys = IOSYS_GAMMA; io_sys = IOSYS_GAMMA;
} }
else else
{ /* this covers MIKASA/NORITAKE */ {
if (strncmp (cpumodel, "EV4", 3) == 0) /* This covers MIKASA/NORITAKE. */
io.sys = IOSYS_APECS; if (strncmp (data.cpumodel, "EV4", 3) == 0)
else if (strncmp (cpumodel, "EV5", 3) == 0) io_sys = IOSYS_APECS;
io.sys = IOSYS_CIA; 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.*/ /* 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"); " CPU model.\n");
__set_errno (ENODEV); __set_errno (ENODEV);
return -1; return -1;
} }
} }
/* some platforms can have different core logic chipsets */ /* Some platforms can have different core logic chipsets */
if (io.sys == IOSYS_PCIDEP) /* EB164 so far */ 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) if (strncmp (data.sysvari, "RX164", 5) == 0)
io.sys = IOSYS_POLARIS; io_sys = IOSYS_POLARIS;
else if (strncmp (data.sysvari, "LX164", 5) == 0
|| strncmp (data.sysvari, "SX164", 5) == 0)
io_sys = IOSYS_PYXIS;
else 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.*/ /* 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"); " core logic chipset.\n");
__set_errno (ENODEV); __set_errno (ENODEV);
return -1; return -1;
} }
} }
io.hae_shift = io_system[io.sys].hae_shift; io.bus_memory_base = io_system[io_sys].bus_memory_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.sparse_bus_memory_base = io_system[io.sys].sparse_bus_mem_base; io.io_base = io_system[io_sys].bus_io_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; 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; io.swiz = IOSWIZZLE_DENSE;
else else
io.swiz = IOSWIZZLE_SPARSE; io.swiz = IOSWIZZLE_SPARSE;
io.swp = &ioswtch[io.swiz]; io.swp = &ioswtch[io.swiz];
__set_errno (olderrno);
return 0; return 0;
} }
} }
/* systype is not a know platform name... */ __set_errno (ENODEV);
__set_errno (EINVAL); fprintf(stderr, "ioperm.init_iosys: Platform not recognized.\n"
#ifdef DEBUG_IOPERM "\t(May need " PATH_ALPHA_SYSTYPE " symlink?)\n");
fprintf(stderr, "init_iosys: platform not recognized\n");
#endif
return -1; return -1;
} }
@ -611,17 +678,18 @@ init_iosys (void)
int int
_ioperm (unsigned long int from, unsigned long int num, int turn_on) _ioperm (unsigned long int from, unsigned long int num, int turn_on)
{ {
unsigned long int addr, len; unsigned long int addr, len, pagesize = __getpagesize();
int prot, err; int prot;
if (!io.swp && init_iosys() < 0) { if (!io.swp && init_iosys() < 0)
{
#ifdef DEBUG_IOPERM #ifdef DEBUG_IOPERM
fprintf(stderr, "ioperm: init_iosys() failed\n"); fprintf(stderr, "ioperm: init_iosys() failed (%m)\n");
#endif #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) if (from >= MAX_PORT || from + num > MAX_PORT)
{ {
__set_errno (EINVAL); __set_errno (EINVAL);
@ -641,15 +709,18 @@ _ioperm (unsigned long int from, unsigned long int num, int turn_on)
{ {
int fd; int fd;
io.hae.reg = 0; /* not used in user-level */ io.hae_cache = 0;
io.hae.cache = 0;
if (io.swiz != IOSWIZZLE_DENSE) if (io.swiz != IOSWIZZLE_DENSE)
__sethae (io.hae.cache); /* synchronize with hw */ {
/* Synchronize with hw. */
__sethae (0);
}
fd = open ("/dev/mem", O_RDWR); fd = __open ("/dev/mem", O_RDWR);
if (fd < 0) { if (fd < 0)
{
#ifdef DEBUG_IOPERM #ifdef DEBUG_IOPERM
fprintf(stderr, "ioperm: /dev/mem open failed\n"); fprintf(stderr, "ioperm: /dev/mem open failed (%m)\n");
#endif #endif
return -1; return -1;
} }
@ -659,7 +730,7 @@ _ioperm (unsigned long int from, unsigned long int num, int turn_on)
io.base = io.base =
(unsigned long int) __mmap (0, len, PROT_NONE, MAP_SHARED, (unsigned long int) __mmap (0, len, PROT_NONE, MAP_SHARED,
fd, io.io_base); fd, io.io_base);
close (fd); __close (fd);
#ifdef DEBUG_IOPERM #ifdef DEBUG_IOPERM
fprintf(stderr, "ioperm: mmap of len 0x%lx returned 0x%lx\n", fprintf(stderr, "ioperm: mmap of len 0x%lx returned 0x%lx\n",
len, io.base); len, io.base);
@ -678,29 +749,27 @@ _ioperm (unsigned long int from, unsigned long int num, int turn_on)
prot = PROT_NONE; prot = PROT_NONE;
} }
addr = port_to_cpu_addr (from, io.swiz, 1); 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; len = port_to_cpu_addr (from + num, io.swiz, 1) - addr;
err = mprotect ((void *) addr, len, prot); return __mprotect ((void *) addr, len, prot);
#ifdef DEBUG_IOPERM
fprintf(stderr, "ioperm: mprotect returned %d\n", err);
#endif
return err;
} }
int int
_iopl (unsigned int level) _iopl (int level)
{ {
if (level > 3) switch (level)
{ {
case 0:
return 0;
case 1: case 2: case 3:
return _ioperm (0, MAX_PORT, 1);
default:
__set_errno (EINVAL); __set_errno (EINVAL);
return -1; return -1;
} }
if (level)
{
return _ioperm (0, MAX_PORT, 1);
}
return 0;
} }
@ -786,7 +855,11 @@ _hae_shift(void)
{ {
if (!io.swp && init_iosys () < 0) if (!io.swp && init_iosys () < 0)
return -1; 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); weak_alias (_sethae, sethae);

View File

@ -51,6 +51,24 @@ extern unsigned long bus_base_sparse (void) __THROW __attribute__ ((const));
extern int _hae_shift (void) __THROW __attribute__ ((const)); extern int _hae_shift (void) __THROW __attribute__ ((const));
extern int hae_shift (void) __THROW __attribute__ ((const)); extern int hae_shift (void) __THROW __attribute__ ((const));
/* Previous three are deprecated in favour of the following, which
knows about multiple PCI "hoses". Provide the PCI bus and dfn
numbers just as to pciconfig_read/write. */
enum __pciconfig_iobase_which
{
IOBASE_HOSE = 0, /* Return hose index. */
IOBASE_SPARSE_MEM = 1, /* Return physical memory addresses. */
IOBASE_DENSE_MEM = 2,
IOBASE_SPARSE_IO = 3,
IOBASE_DENSE_IO = 4
};
extern long pciconfig_iobase(enum __pciconfig_iobase_which __which,
unsigned long int __bus,
unsigned long int __dfn)
__THROW __attribute__ ((const));
/* Access PCI space protected from machine checks. */ /* Access PCI space protected from machine checks. */
extern int pciconfig_read (unsigned long int __bus, extern int pciconfig_read (unsigned long int __bus,
unsigned long int __dfn, unsigned long int __dfn,

View File

@ -1,8 +1,5 @@
# File name Caller Syscall name # args Strong name Weak names # File name Caller Syscall name # args Strong name Weak names
# used to implement inb()/outb() etc.
sethae - sethae 1 __sethae
oldmsgctl EXTRA msgctl 3 __old_msgctl msgctl@GLIBC_2.0 oldmsgctl EXTRA msgctl 3 __old_msgctl msgctl@GLIBC_2.0
msgget - msgget 2 __msgget msgget msgget - msgget 2 __msgget msgget
msgrcv - msgrcv 5 __msgrcv msgrcv msgrcv - msgrcv 5 __msgrcv msgrcv
@ -63,6 +60,7 @@ getresgid - getresgid 3 getresgid
# access pci space protected from machine checks: # access pci space protected from machine checks:
pciconfig_read EXTRA pciconfig_read 5 pciconfig_read pciconfig_read EXTRA pciconfig_read 5 pciconfig_read
pciconfig_write EXTRA pciconfig_write 5 pciconfig_write pciconfig_write EXTRA pciconfig_write 5 pciconfig_write
pciconfig_iobase EXTRA pciconfig_iobase 3 __pciconfig_iobase pciconfig_iobase
# Wrapper for adjtimex. # Wrapper for adjtimex.
adjtimex - syscall_adjtimex 1 __syscall_adjtimex syscall_adjtimex adjtimex - syscall_adjtimex 1 __syscall_adjtimex syscall_adjtimex