aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--sysdeps/unix/sysv/linux/arm/ioperm.c63
-rw-r--r--sysdeps/unix/sysv/linux/sparc/bits/fcntl.h6
3 files changed, 47 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index 2ed81d65e4..371cc8ab88 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2000-01-02 Philip Blundell <philb@gnu.org>
+
+ * sysdeps/unix/sysv/linux/arm/ioperm.c: Use sysctl by preference
+ to obtain port mapping information. Avoid use of mprotect.
+
2000-01-04 Ulrich Drepper <drepper@cygnus.com>
* sysdeps/unix/sysv/linux/sparc/bits/fcntl.h (O_LARGEFILE): Add
diff --git a/sysdeps/unix/sysv/linux/arm/ioperm.c b/sysdeps/unix/sysv/linux/arm/ioperm.c
index 260226d9f3..f4c9322823 100644
--- a/sysdeps/unix/sysv/linux/arm/ioperm.c
+++ b/sysdeps/unix/sysv/linux/arm/ioperm.c
@@ -27,6 +27,12 @@
registers tend to be memory mapped these days so this should be no big
problem. */
+/* Once upon a time this file used mprotect to enable and disable
+ access to particular areas of I/O space. Unfortunately the
+ mprotect syscall also has the side effect of enabling caching for
+ the area affected (this is a kernel limitation). So we now just
+ enable all the ports all of the time. */
+
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
@@ -39,6 +45,7 @@
#include <sys/mman.h>
#include <asm/page.h>
+#include <sys/sysctl.h>
#define PATH_ARM_SYSTYPE "/etc/arm_systype"
#define PATH_CPUINFO "/proc/cpuinfo"
@@ -69,16 +76,22 @@ static struct platform {
#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.
+ * Initialize I/O system. There are several ways to get the information
+ * we need. Each is tried in turn until one succeeds.
+ *
+ * 1. Sysctl (CTL_BUS, BUS_ISA, ISA_*). This is the preferred method
+ * but not all kernels support it.
+ *
+ * 2. Read the value (not the contents) of symlink PATH_ARM_SYSTYPE.
+ * - If it matches one of the entries in the table above, use the
+ * corresponding values.
+ * - If it begins with a number, assume this is a previously
+ * unsupported system and the values encode, in order,
+ * "<io_base>,<port_shift>".
*
- * 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>".
+ * 3. Lookup the "system type" field in /proc/cpuinfo. Again, if it
+ * matches an entry in the platform[] table, use the corresponding
+ * values.
*/
static int
@@ -86,6 +99,16 @@ init_iosys (void)
{
char systype[256];
int i, n;
+ static int iobase_name[] = { CTL_BUS, BUS_ISA, BUS_ISA_PORT_BASE };
+ static int ioshift_name[] = { CTL_BUS, BUS_ISA, BUS_ISA_PORT_SHIFT };
+ size_t len = sizeof(io.base);
+
+ if (! sysctl (iobase_name, 3, &io.io_base, &len, NULL, 0)
+ && ! sysctl (ioshift_name, 3, &io.shift, &len, NULL, 0))
+ {
+ io.initdone = 1;
+ return 0;
+ }
n = readlink (PATH_ARM_SYSTYPE, systype, sizeof (systype) - 1);
if (n > 0)
@@ -106,7 +129,7 @@ init_iosys (void)
FILE * fp;
fp = fopen (PATH_CPUINFO, "r");
- if (!fp)
+ if (! fp)
return -1;
while ((n = fscanf (fp, "Hardware\t: %256[^\n]\n", systype))
!= EOF)
@@ -149,10 +172,7 @@ init_iosys (void)
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)
+ if (! io.initdone && init_iosys () < 0)
return -1;
/* this test isn't as silly as it may look like; consider overflows! */
@@ -173,25 +193,16 @@ _ioperm (unsigned long int from, unsigned long int num, int turn_on)
return -1;
io.base =
- (unsigned long int) __mmap (0, MAX_PORT << io.shift, PROT_NONE,
+ (unsigned long int) __mmap (0, MAX_PORT << io.shift,
+ PROT_READ | PROT_WRITE,
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);
+ return 0;
}
diff --git a/sysdeps/unix/sysv/linux/sparc/bits/fcntl.h b/sysdeps/unix/sysv/linux/sparc/bits/fcntl.h
index 4dd8f3d182..53f0d507e2 100644
--- a/sysdeps/unix/sysv/linux/sparc/bits/fcntl.h
+++ b/sysdeps/unix/sysv/linux/sparc/bits/fcntl.h
@@ -44,7 +44,11 @@
#endif
#ifdef __USE_LARGEFILE64
-# define O_LARGEFILE 0x40000
+# if __WORDSIZE == 64
+# define O_LARGEFILE 0
+# else
+# define O_LARGEFILE 0x40000
+# endif
#endif
/* For now Linux has no synchronisity options for data and read