about summary refs log tree commit diff
path: root/sysdeps/unix/sysv/linux/alpha
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/alpha')
-rw-r--r--sysdeps/unix/sysv/linux/alpha/Dist3
-rw-r--r--sysdeps/unix/sysv/linux/alpha/Makefile2
-rw-r--r--sysdeps/unix/sysv/linux/alpha/init-first.h39
-rw-r--r--sysdeps/unix/sysv/linux/alpha/ioperm.c47
-rw-r--r--sysdeps/unix/sysv/linux/alpha/sys/io.h59
5 files changed, 119 insertions, 31 deletions
diff --git a/sysdeps/unix/sysv/linux/alpha/Dist b/sysdeps/unix/sysv/linux/alpha/Dist
index 79ac03ff90..d898d041a2 100644
--- a/sysdeps/unix/sysv/linux/alpha/Dist
+++ b/sysdeps/unix/sysv/linux/alpha/Dist
@@ -1,5 +1,6 @@
-alpha/ptrace.halpha/regdef.h
+alpha/ptrace.h alpha/regdef.h
 ieee_get_fp_control.S ieee_set_fp_control.S
 ioperm.c
 init-first.h
 clone.S
+sys/io.h
diff --git a/sysdeps/unix/sysv/linux/alpha/Makefile b/sysdeps/unix/sysv/linux/alpha/Makefile
index 3908b5703c..fa433e9d8b 100644
--- a/sysdeps/unix/sysv/linux/alpha/Makefile
+++ b/sysdeps/unix/sysv/linux/alpha/Makefile
@@ -1,5 +1,5 @@
 ifeq ($(subdir), misc)
-sysdep_headers += alpha/ptrace.h alpha/regdef.h
+sysdep_headers += alpha/ptrace.h alpha/regdef.h sys/io.h
 
 sysdep_routines += ieee_get_fp_control ieee_set_fp_control \
 		   sethae ioperm osf_sigprocmask fstatfs statfs llseek
diff --git a/sysdeps/unix/sysv/linux/alpha/init-first.h b/sysdeps/unix/sysv/linux/alpha/init-first.h
index c27c589a28..ffbcaf1521 100644
--- a/sysdeps/unix/sysv/linux/alpha/init-first.h
+++ b/sysdeps/unix/sysv/linux/alpha/init-first.h
@@ -1,12 +1,29 @@
-/* This fragment is invoked in the stack context of program start.
-   Its job is to set up a pointer to argc as an argument, pass
-   control to `INIT', and, if necessary, clean up after the call
-   to leave the stack in the same condition it was found in.  */
+/* The job of this fragment it to find argc and friends for INIT.
+   This is done in one of two ways: either in the stack context
+   of program start, or having dlopen pass them in.  */
 
-#define SYSDEP_CALL_INIT(NAME, INIT)	\
-    asm(".globl " #NAME "\n"		\
-	#NAME ":\n\t"			\
-	"ldgp $29, 0($27)\n\t"		\
-	".prologue 1\n\t"		\
-	"mov $30, $16\n\t"		\
-	"br $31, " #INIT "..ng");
+#define SYSDEP_CALL_INIT(NAME, INIT)		\
+    asm(".weak _dl_starting_up\n\t"		\
+        ".globl " #NAME "\n\t"			\
+	".ent " #NAME "\n"			\
+	#NAME ":\n\t"				\
+	"ldgp	$29, 0($27)\n\t"		\
+	".prologue 1\n\t"			\
+	".set at\n\t"				\
+	/* Are we a dynamic libc being loaded into a static program?  */ \
+	"lda	$0, _dl_starting_up\n\t"	\
+	"beq	$0, 1f\n\t"			\
+	"ldl	$0, 0($0)\n"			\
+	"cmpeq	$31, $0, $0\n"			\
+	"1:\t"					\
+	"stl	$0, __libc_multiple_libcs\n\t"	\
+	/* If so, argc et al are in a0-a2 already.  Otherwise, load them.  */ \
+	"bne	$0, 2f\n\t"			\
+	"ldl	$16, 0($30)\n\t"		\
+	"lda	$17, 8($30)\n\t"		\
+	"s8addq	$16, $17, $18\n\t"		\
+	"addq	$18, 8, $18\n"			\
+	"2:\t"					\
+	"br $31, " #INIT "..ng\n\t"		\
+	".set noat\n\t"				\
+	".end " #NAME);
diff --git a/sysdeps/unix/sysv/linux/alpha/ioperm.c b/sysdeps/unix/sysv/linux/alpha/ioperm.c
index a91608ff24..731059e600 100644
--- a/sysdeps/unix/sysv/linux/alpha/ioperm.c
+++ b/sysdeps/unix/sysv/linux/alpha/ioperm.c
@@ -84,20 +84,21 @@ struct ioswtch {
 static struct platform {
   const char	*name;
   int		io_sys;
+  int		hae_shift;
   unsigned long	bus_memory_base;
   unsigned long	sparse_bus_memory_base;
 } platform[] = {
-  {"Alcor",	IOSYS_CIA,	CIA_DENSE_MEM,		CIA_SPARSE_MEM},
-  {"Avanti",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
-  {"Cabriolet",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
-  {"EB164",	IOSYS_CIA,	CIA_DENSE_MEM,		CIA_SPARSE_MEM},
-  {"EB64+",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
-  {"EB66",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
-  {"EB66P",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
-  {"Jensen",	IOSYS_JENSEN,	0,			JENSEN_SPARSE_MEM},
-  {"Mikasa",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
-  {"Mustang",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
-  {"Noname",	IOSYS_APECS,	APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"Alcor",	IOSYS_CIA,	5, CIA_DENSE_MEM,	CIA_SPARSE_MEM},
+  {"Avanti",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"Cabriolet",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"EB164",	IOSYS_CIA,	5, CIA_DENSE_MEM,	CIA_SPARSE_MEM},
+  {"EB64+",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"EB66",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"EB66P",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"Jensen",	IOSYS_JENSEN,	7, 0,			JENSEN_SPARSE_MEM},
+  {"Mikasa",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"Mustang",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
+  {"Noname",	IOSYS_APECS,	5, APECS_DENSE_MEM,	APECS_SPARSE_MEM},
 };
 
 
@@ -109,11 +110,11 @@ static struct {
   unsigned long		base;
   struct ioswtch *	swp;
   int			sys;
+  int			hae_shift;
+  unsigned long		bus_memory_base;
+  unsigned long		sparse_bus_memory_base;
 } io;
 
-static unsigned long bus_memory_base = -1;
-static unsigned long sparse_bus_memory_base = -1;
-
 extern void __sethae (unsigned long);	/* we can't use asm/io.h */
 
 
@@ -335,8 +336,9 @@ init_iosys (void)
     {
       if (strcmp (platform[i].name, systype) == 0)
 	{
-	  bus_memory_base = platform[i].bus_memory_base;
-	  sparse_bus_memory_base = platform[i].sparse_bus_memory_base;
+	  io.hae_shift = platform[i].hae_shift;
+	  io.bus_memory_base = platform[i].bus_memory_base;
+	  io.sparse_bus_memory_base = platform[i].sparse_bus_memory_base;
 	  io.sys = platform[i].io_sys;
 	  if (io.sys == IOSYS_JENSEN)
 	    io.swp = &ioswtch[0];
@@ -500,7 +502,7 @@ _bus_base(void)
 {
   if (!io.swp && init_iosys () < 0)
     return -1;
-  return bus_memory_base;
+  return io.bus_memory_base;
 }
 
 unsigned long
@@ -508,7 +510,15 @@ _bus_base_sparse(void)
 {
   if (!io.swp && init_iosys () < 0)
     return -1;
-  return sparse_bus_memory_base;
+  return io.sparse_bus_memory_base;
+}
+
+int
+_hae_shift(void)
+{
+  if (!io.swp && init_iosys () < 0)
+    return -1;
+  return io.hae_shift;
 }
 
 weak_alias (_sethae, sethae);
@@ -522,3 +532,4 @@ weak_alias (_outw, outw);
 weak_alias (_outl, outl);
 weak_alias (_bus_base, bus_base);
 weak_alias (_bus_base_sparse, bus_base_sparse);
+weak_alias (_hae_shift, hae_shift);
diff --git a/sysdeps/unix/sysv/linux/alpha/sys/io.h b/sysdeps/unix/sysv/linux/alpha/sys/io.h
new file mode 100644
index 0000000000..a88073573c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/alpha/sys/io.h
@@ -0,0 +1,59 @@
+/* Copyright (C) 1996 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., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef	_SYS_IO_H
+
+#define	_SYS_IO_H	1
+#include <features.h>
+
+__BEGIN_DECLS
+
+/* Get constants from kernel header files. */
+#include <asm/io.h>
+
+/* 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.
+
+   Portability note: not all Linux platforms support this call.  Most
+   platforms based on the PC I/O architecture probably will, however.
+   E.g., Linux/Alpha for Alpha PCs supports this.  */
+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>3, permission to
+   access any I/O port is granted.  This call requires root
+   privileges. */
+extern int iopl __P ((int __level));
+
+/* Return the physical address of the DENSE I/O memory or NULL if none
+   is available (e.g. on a jensen).  */
+extern unsigned long _bus_base __P ((void)) __attribute__ ((const));
+extern unsigned long bus_base __P ((void)) __attribute__ ((const));
+
+/* Return the physical address of the SPARSE I/O memory.  */
+extern unsigned long _bus_base_sparse __P ((void)) __attribute__ ((const));
+extern unsigned long bus_base_sparse __P ((void)) __attribute__ ((const));
+
+/* Return the HAE shift used by the SPARSE I/O memory.  */
+extern int _hae_shift __P ((void)) __attribute__ ((const));
+extern int hae_shift __P ((void)) __attribute__ ((const));
+
+__END_DECLS
+
+#endif /* _SYS_IO_H */