1998-12-20  Philip Blundell  <philb@gnu.org>

	* sysdeps/unix/sysv/linux/arm/sysdep.h (INLINE_SYSCALL): Add
	implementation.
	* sysdeps/unix/sysv/linux/arm/syscalls.list: Remove wrappers for
	now-inlined calls.
        
1998-12-22  Philip Blundell  <pb@nexus.co.uk>

	* sysdeps/unix/sysv/linux/arm/ioperm.c: New file.
	Implementation of inb, outb etc for ARM systems.
	* sysdeps/unix/sysv/linux/arm/sys/io.h: Likewise.
	* sysdeps/unix/sysv/linux/arm/Versions: Add appropriate
	entries for the above.
This commit is contained in:
Ulrich Drepper 1998-12-23 13:08:22 +00:00
parent 361d49e6a4
commit edb570bb87
7 changed files with 388 additions and 31 deletions

View File

@ -1,3 +1,18 @@
1998-12-20 Philip Blundell <philb@gnu.org>
* sysdeps/unix/sysv/linux/arm/sysdep.h (INLINE_SYSCALL): Add
implementation.
* sysdeps/unix/sysv/linux/arm/syscalls.list: Remove wrappers for
now-inlined calls.
1998-12-22 Philip Blundell <pb@nexus.co.uk>
* sysdeps/unix/sysv/linux/arm/ioperm.c: New file.
Implementation of inb, outb etc for ARM systems.
* sysdeps/unix/sysv/linux/arm/sys/io.h: Likewise.
* sysdeps/unix/sysv/linux/arm/Versions: Add appropriate
entries for the above.
1998-12-21 Ulrich Drepper <drepper@cygnus.com>
* nss/db-Makefile (shadow.db): Create file with correct protections.

View File

@ -495,7 +495,7 @@ TRANS @c This can probably happen in a GNU system when using NFS. */
#ifdef EDQUOT
/*
TRANS The user's disk quota was exceeded. */
[ERR_REMAP (EDQUOT)] = N_("Disc quota exceeded"),
[ERR_REMAP (EDQUOT)] = N_("Disk quota exceeded"),
#endif
#ifdef ESTALE
/*

View File

@ -0,0 +1,7 @@
libc {
GLIBC_2.1 {
ioperm; iopl;
inb; inw; inl;
outb; outw; outl;
}
}

View File

@ -0,0 +1,271 @@
/* Copyright (C) 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Phil Blundell, based on the Alpha version by
David Mosberger.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* I/O port access on the ARM is something of a fiction. What we do is to
map an appropriate area of /dev/mem into user space so that a program
can blast away at the hardware in such a way as to generate I/O cycles
on the bus. To insulate user code from dependencies on particular
hardware we don't allow calls to inb() and friends to be inlined, but
force them to come through code in here every time. Performance-critical
registers tend to be memory mapped these days so this should be no big
problem. */
#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 <asm/page.h>
#define PATH_ARM_SYSTYPE "/etc/arm_systype"
#define PATH_CPUINFO "/proc/cpuinfo"
#define MAX_PORT 0x10000
static struct {
unsigned long int base;
unsigned long int io_base;
unsigned int shift;
unsigned int initdone; /* since all the above could be 0 */
} io;
#define IO_BASE_FOOTBRIDGE 0x7c000000
#define IO_SHIFT_FOOTBRIDGE 0
static struct platform {
const char *name;
unsigned long int io_base;
unsigned int shift;
} platform[] = {
/* All currently supported platforms are in fact the same. :-) */
{"Chalice-CATS", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE},
{"DEC-EBSA285", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE},
{"Corel-NetWinder", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE},
};
#define IO_ADDR(port) (io.base + ((port) << io.shift))
/*
* Initialize I/O system. To determine what I/O system we're dealing
* with, we first try to read the value of symlink PATH_ARM_SYSTYPE,
* if that fails, we lookup the "system type" field in /proc/cpuinfo.
* If that fails as well, we give up. Other possible options might be
* to look at the ELF auxiliary vector or to add a special system call
* but there is probably no point.
*
* If the value received from PATH_ARM_SYSTYPE begins with a number,
* assume this is a previously unsupported system and the values encode,
* in order, "<io_base>,<port_shift>".
*/
static int
init_iosys (void)
{
char systype[256];
int i, n;
n = readlink (PATH_ARM_SYSTYPE, systype, sizeof (systype) - 1);
if (n > 0)
{
systype[n] = '\0';
if (isdigit (systype[0]))
{
if (sscanf (systype, "%li,%i", &io.io_base, &io.shift) == 2)
{
io.initdone = 1;
return 0;
}
/* else we're likely going to fail with the system match below */
}
}
else
{
FILE * fp;
fp = fopen (PATH_CPUINFO, "r");
if (!fp)
return -1;
while ((n = fscanf (fp, "Hardware\t: %256[^\n]\n", systype))
!= EOF)
{
if (n == 1)
break;
else
fgets (systype, 256, fp);
}
fclose (fp);
if (n == EOF)
{
/* this can happen if the format of /proc/cpuinfo changes... */
fprintf (stderr,
"ioperm: Unable to determine system type.\n"
"\t(May need " PATH_ARM_SYSTYPE " symlink?)\n");
__set_errno (ENODEV);
return -1;
}
}
/* translate systype name into i/o system: */
for (i = 0; i < sizeof (platform) / sizeof (platform[0]); ++i)
{
if (strcmp (platform[i].name, systype) == 0)
{
io.shift = platform[i].shift;
io.io_base = platform[i].io_base;
io.initdone = 1;
return 0;
}
}
/* systype is not a known platform name... */
__set_errno (EINVAL);
return -1;
}
int
_ioperm (unsigned long int from, unsigned long int num, int turn_on)
{
unsigned long int addr, len;
int prot;
if (!io.initdone && init_iosys () < 0)
return -1;
/* this test isn't as silly as it may look like; consider overflows! */
if (from >= MAX_PORT || from + num > MAX_PORT)
{
__set_errno (EINVAL);
return -1;
}
if (turn_on)
{
if (! io.base)
{
int fd;
fd = open ("/dev/mem", O_RDWR);
if (fd < 0)
return -1;
io.base =
(unsigned long int) __mmap (0, MAX_PORT << io.shift, PROT_NONE,
MAP_SHARED, fd, io.io_base);
close (fd);
if ((long) io.base == -1)
return -1;
}
prot = PROT_READ | PROT_WRITE;
}
else
{
if (!io.base)
return 0; /* never was turned on... */
/* turnoff access to relevant pages: */
prot = PROT_NONE;
}
addr = (io.base + (from << io.shift)) & PAGE_MASK;
len = num << io.shift;
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;
}
void
_outb (unsigned char b, unsigned long int port)
{
if (port >= MAX_PORT)
return;
*((volatile unsigned char *)(IO_ADDR (port))) = b;
}
void
_outw (unsigned short b, unsigned long int port)
{
if (port >= MAX_PORT)
return;
*((volatile unsigned short *)(IO_ADDR (port))) = b;
}
void
_outl (unsigned int b, unsigned long int port)
{
if (port >= MAX_PORT)
return;
*((volatile unsigned long *)(IO_ADDR (port))) = b;
}
unsigned int
_inb (unsigned long int port)
{
return *((volatile unsigned char *)(IO_ADDR (port)));
}
unsigned int
_inw (unsigned long int port)
{
return *((volatile unsigned short *)(IO_ADDR (port)));
}
unsigned int
_inl (unsigned long int port)
{
return *((volatile unsigned long *)(IO_ADDR (port)));
}
weak_alias (_ioperm, ioperm);
weak_alias (_iopl, iopl);
weak_alias (_inb, inb);
weak_alias (_inw, inw);
weak_alias (_inl, inl);
weak_alias (_outb, outb);
weak_alias (_outw, outw);
weak_alias (_outl, outl);

View File

@ -0,0 +1,48 @@
/* Copyright (C) 1996, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifndef _SYS_IO_H
#define _SYS_IO_H 1
#include <features.h>
__BEGIN_DECLS
/* If TURN_ON is TRUE, request for permission to do direct i/o on the
port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O
permission off for that range. This call requires root privileges. */
extern int ioperm __P ((unsigned long int __from, unsigned long int __num,
int __turn_on));
/* Set the I/O privilege level to LEVEL. If LEVEL is nonzero,
permission to access any I/O port is granted. This call requires
root privileges. */
extern int iopl __P ((int __level));
/* The functions that actually perform reads and writes. */
extern unsigned char inb (unsigned long port);
extern unsigned short inw (unsigned long port);
extern unsigned long inl (unsigned long port);
extern void outb (unsigned char value, unsigned long port);
extern void outw (unsigned short value, unsigned long port);
extern void outl (unsigned long value, unsigned long port);
__END_DECLS
#endif /* _SYS_IO_H */

View File

@ -13,33 +13,3 @@ s_setreuid setreuid setreuid 2 __syscall_setreuid
s_setuid setuid setuid 1 __syscall_setuid
syscall - syscall 5 syscall
vm86 - vm86 1 __vm86 vm86
# System calls with wrappers.
rt_sigaction - rt_sigaction 4 __syscall_rt_sigaction
rt_sigpending - rt_sigpending 2 __syscall_rt_sigpending
rt_sigprocmask - rt_sigprocmask 4 __syscall_rt_sigprocmask
rt_sigqueueinfo - rt_sigqueueinfo 3 __syscall_rt_sigqueueinfo
rt_sigsuspend - rt_sigsuspend 2 __syscall_rt_sigsuspend
rt_sigtimedwait - rt_sigtimedwait 4 __syscall_rt_sigtimedwait
s_getcwd getcwd getcwd 2 __syscall_getcwd
s_getdents getdents getdents 3 __syscall_getdents
s_getpriority getpriority getpriority 2 __syscall_getpriority
s_getresgid getresgid getresgid 3 __syscall_getresgid
s_getresuid getresuid getresuid 3 __syscall_getresuid
s_poll poll poll 3 __syscall_poll
s_pread64 pread64 pread 5 __syscall_pread
s_ptrace ptrace ptrace 4 __syscall_ptrace
s_pwrite64 pwrite64 pwrite 5 __syscall_pwrite
s_reboot reboot reboot 3 __syscall_reboot
s_sigaction sigaction sigaction 3 __syscall_sigaction
s_sigpending sigpending sigpending 1 __syscall_sigpending
s_sigprocmask sigprocmask sigprocmask 3 __syscall_sigprocmask
s_sigsuspend sigsuspend sigsuspend 3 __syscall_sigsuspend
s_sysctl sysctl _sysctl 1 __syscall__sysctl
s_ustat ustat ustat 2 __syscall_ustat
sys_fstat fxstat fstat 2 __syscall_fstat
sys_lstat lxstat lstat 2 __syscall_lstat
sys_mknod xmknod mknod 3 __syscall_mknod
sys_readv readv readv 3 __syscall_readv
sys_stat xstat stat 2 __syscall_stat
sys_writev writev writev 3 __syscall_writev

View File

@ -104,6 +104,52 @@
#define UNDOARGS_4 /* nothing */
#define UNDOARGS_5 ldr r4, [sp];
#else /* not __ASSEMBLER__ */
/* Define a macro which expands into the inline wrapper code for a system
call. */
#undef INLINE_SYSCALL
#define INLINE_SYSCALL(name, nr, args...) \
({ unsigned int _sys_result; \
{ \
register int _a1 asm ("a1"); \
LOAD_ARGS_##nr (args) \
asm volatile ("swi %1" \
: "=r" (_a1) \
: "i" (SYS_ify(name)) ASM_ARGS_##nr \
: "a1"); \
_sys_result = _a1; \
} \
if (_sys_result >= (unsigned int) -4095) \
{ \
__set_errno (-_sys_result); \
_sys_result = (unsigned int) -1; \
} \
(int) _sys_result; })
#define LOAD_ARGS_0()
#define ASM_ARGS_0
#define LOAD_ARGS_1(a1) \
_a1 = (int) (a1); \
LOAD_ARGS_0 ()
#define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1)
#define LOAD_ARGS_2(a1, a2) \
register int _a2 asm ("a2") = (int) (a2); \
LOAD_ARGS_1 (a1)
#define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2)
#define LOAD_ARGS_3(a1, a2, a3) \
register int _a3 asm ("a3") = (int) (a3); \
LOAD_ARGS_2 (a1, a2)
#define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3)
#define LOAD_ARGS_4(a1, a2, a3, a4) \
register int _a4 asm ("a4") = (int) (a4); \
LOAD_ARGS_3 (a1, a2, a3)
#define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4)
#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \
register int _v1 asm ("v1") = (int) (a5); \
LOAD_ARGS_4 (a1, a2, a3, a4)
#define ASM_ARGS_5 ASM_ARGS_4, "r" (_v1)
#endif /* __ASSEMBLER__ */
#endif /* linux/arm/sysdep.h */