Wed May 22 00:40:50 1996 David Mosberger-Tang <davidm@azstarnet.com>
authorRoland McGrath <roland@gnu.org>
Thu, 23 May 1996 05:32:27 +0000 (05:32 +0000)
committerRoland McGrath <roland@gnu.org>
Thu, 23 May 1996 05:32:27 +0000 (05:32 +0000)
* sysdeps/unix/sysv/linux/alpha/ioperm.c: Modify to support
  dynamic recognition of platform type.
(_bus_base): New function.

sysdeps/unix/sysv/linux/alpha/ioperm.c

index 306c86b..b9630a8 100644 (file)
@@ -35,31 +35,35 @@ I/O address space that's 512MB large!).  */
 #include <errno.h>
 #include <fcntl.h>
 #include <stdio.h>
-#include <unistd.h>
+#include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include <sys/types.h>
 #include <sys/mman.h>
 
-#include <asm/io.h>
 #include <asm/page.h>
 #include <asm/system.h>
 
-#undef inb
-#undef inw
-#undef inl
-#undef outb
-#undef outw
-#undef outl
-
-#define PATH_CPUINFO   "/proc/cpuinfo"
+#define PATH_ALPHA_SYSTYPE     "/etc/alpha_systype"
+#define PATH_CPUINFO           "/proc/cpuinfo"
 
 #define MAX_PORT       0x10000
 #define vuip           volatile unsigned int *
 
-#define JENSEN_IO_BASE         (IDENT_ADDR + 0x0300000000UL)
-#define APECS_IO_BASE          (IDENT_ADDR + 0x01c0000000UL)
-#define ALCOR_IO_BASE          (IDENT_ADDR + 0x8580000000UL)
+#define JENSEN_IO_BASE         (0xfffffc0300000000UL)
+#define JENSEN_MEM             (0xfffffc0200000000UL)  /* sparse!! */
+
+/*
+ * 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_DENSE_MEM                (0xfffffc0300000000UL)
+
+#define ALCOR_IO_BASE          (0xfffffc8580000000UL)
+#define ALCOR_DENSE_MEM                (0xfffffc8600000000UL)
+
 
 enum {
   IOSYS_JENSEN = 0, IOSYS_APECS = 1, IOSYS_ALCOR = 2
@@ -78,58 +82,75 @@ struct ioswtch {
 static struct platform {
   const char   *name;
   int          io_sys;
+  unsigned long        bus_memory_base;
 } platform[] = {
-  {"Alcor",            IOSYS_ALCOR},
-  {"Avanti",           IOSYS_APECS},
-  {"Cabriolet",                IOSYS_APECS},
-  {"EB64+",            IOSYS_APECS},
-  {"EB66",             IOSYS_APECS},
-  {"EB66P",            IOSYS_APECS},
-  {"Jensen",           IOSYS_JENSEN},
-  {"Mustang",          IOSYS_APECS},
-  {"Noname",           IOSYS_APECS},
+  {"Alcor",    IOSYS_ALCOR,    ALCOR_DENSE_MEM},
+  {"Avanti",   IOSYS_APECS,    APECS_DENSE_MEM},
+  {"Cabriolet",        IOSYS_APECS,    APECS_DENSE_MEM},
+  {"EB164",    IOSYS_ALCOR,    ALCOR_DENSE_MEM},
+  {"EB64+",    IOSYS_APECS,    APECS_DENSE_MEM},
+  {"EB66",     IOSYS_APECS,    APECS_DENSE_MEM},       /* LCA same as APECS */
+  {"EB66P",    IOSYS_APECS,    APECS_DENSE_MEM},       /* LCA same as APECS */
+  {"Jensen",   IOSYS_JENSEN,   JENSEN_MEM},
+  {"Mustang",  IOSYS_APECS,    APECS_DENSE_MEM},
+  {"Noname",   IOSYS_APECS,    APECS_DENSE_MEM},       /* LCA same as APECS */
 };
 
 
 static struct {
-  struct hae           hae;
+  struct hae {
+    unsigned long      cache;
+    unsigned long *    reg;
+  } hae;
   unsigned long                base;
   struct ioswtch *     swp;
   int                  sys;
 } io;
 
+static unsigned long bus_memory_base = -1;
+
+extern void __sethae (unsigned long);  /* we can't use asm/io.h */
+
 
 static inline unsigned long
 port_to_cpu_addr (unsigned long port, int iosys, int size)
 {
-  if (iosys == IOSYS_JENSEN) {
-    return (port << 7) + ((size - 1) << 4) + io.base;
-  } else {
-    return (port << 5) + ((size - 1) << 3) + io.base;
-  }
+  if (iosys == IOSYS_JENSEN)
+    {
+      return (port << 7) + ((size - 1) << 4) + io.base;
+    }
+  else
+    {
+      return (port << 5) + ((size - 1) << 3) + io.base;
+    }
 }
 
 
 static inline void
 inline_sethae (unsigned long addr, int iosys)
 {
-  if (iosys == IOSYS_JENSEN) {
-    /* hae on the Jensen is bits 31:25 shifted right */
-    addr >>= 25;
-    if (addr != io.hae.cache) {
-       __sethae (addr);
-       io.hae.cache = addr;
+  if (iosys == IOSYS_JENSEN)
+    {
+      /* hae on the Jensen is bits 31:25 shifted right */
+      addr >>= 25;
+      if (addr != io.hae.cache)
+       {
+         __sethae (addr);
+         io.hae.cache = addr;
+       }
     }
-  } else {
-    unsigned long msb;
-
-    /* no need to set hae if msb is 0: */
-    msb = addr & 0xf8000000;
-    if (msb && msb != io.hae.cache) {
-       __sethae (msb);
-       io.hae.cache = msb;
+  else
+    {
+      unsigned long msb;
+
+      /* no need to set hae if msb is 0: */
+      msb = addr & 0xf8000000;
+      if (msb && msb != io.hae.cache)
+       {
+         __sethae (msb);
+         io.hae.cache = msb;
+       }
     }
-  }
 }
 
 
@@ -263,22 +284,56 @@ struct ioswtch ioswtch[] = {
 };
 
 
+/*
+ * 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.
+ */
 static int
 init_iosys (void)
 {
-  char name[256], value[256];
-  FILE * fp;
-  int i;
+  char systype[256];
+  int i, n;
 
-  fp = fopen (PATH_CPUINFO, "r");
-  if (!fp)
-    return -1;
+  n = readlink(PATH_ALPHA_SYSTYPE, systype, sizeof(systype) - 1);
+  if (n > 0)
+    {
+      systype[n] = '\0';
+    }
+  else
+    {
+      char name[256];
+      FILE * fp;
+
+      fp = fopen (PATH_CPUINFO, "r");
+      if (!fp)
+       return -1;
+      while ((n = fscanf (fp, "%256[^:]: %256[^\n]\n", name, systype)) != EOF)
+       {
+         if (n == 2 && strncmp (name, "system type", 11) == 0) {
+           break;
+         }
+       }
+      fclose(fp);
+
+      if (n == EOF)
+       {
+         /* 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");
+         errno = ENODEV;
+         return -1;
+       }
+    }
 
-  while (fscanf (fp, "%256[^:]: %256[^\n]\n", name, value) == 2) {
-    if (strncmp (name, "system type", 11) == 0) {
-      for (i = 0; i < sizeof (platform) / sizeof (platform[0]); ++i) {
-       if (strcmp (platform[i].name, value) == 0) {
-         fclose (fp);
+  /* translate systype name into i/o system: */
+  for (i = 0; i < sizeof (platform) / sizeof (platform[0]); ++i)
+    {
+      if (strcmp (platform[i].name, systype) == 0)
+       {
+         bus_memory_base = platform[i].bus_memory_base;
          io.sys = platform[i].io_sys;
          if (io.sys == IOSYS_JENSEN)
            io.swp = &ioswtch[0];
@@ -286,11 +341,10 @@ init_iosys (void)
            io.swp = &ioswtch[1];
          return 0;
        }
-      }
     }
-  }
-  fclose (fp);
-  errno = ENODEV;
+
+  /* systype is not a know platform name... */
+  errno = EINVAL;
   return -1;
 }
 
@@ -305,49 +359,55 @@ _ioperm (unsigned long from, unsigned long num, int turn_on)
     return -1;
 
   /* this test isn't as silly as it may look like; consider overflows! */
-  if (from >= MAX_PORT || from + num > MAX_PORT) {
-    errno = EINVAL;
-    return -1;
-  }
+  if (from >= MAX_PORT || from + num > MAX_PORT)
+    {
+      errno = EINVAL;
+      return -1;
+    }
 
-  if (turn_on) {
-    if (!io.base) {
-      unsigned long base;
-      int fd;
-
-      io.hae.reg   = 0;                /* not used in user-level */
-      io.hae.cache = 0;
-      __sethae (io.hae.cache); /* synchronize with hw */
-
-      fd = open ("/dev/mem", O_RDWR);
-      if (fd < 0)
-       return fd;
-
-      switch (io.sys) {
-      case IOSYS_JENSEN:       base = JENSEN_IO_BASE; break;
-      case IOSYS_APECS:                base = APECS_IO_BASE; break;
-      case IOSYS_ALCOR:                base = ALCOR_IO_BASE; break;
-      default:
-       errno = ENODEV;
-       return -1;
-      }
-      addr  = port_to_cpu_addr (from, io.sys, 1);
-      addr &= PAGE_MASK;
-      len = port_to_cpu_addr (MAX_PORT, io.sys, 1) - addr;
-      io.base =
-         (unsigned long) __mmap (0, len, PROT_NONE, MAP_SHARED, fd, base);
-      close (fd);
-      if ((long) io.base == -1)
-       return -1;
+  if (turn_on)
+    {
+      if (!io.base)
+       {
+         unsigned long base;
+         int fd;
+
+         io.hae.reg   = 0;             /* not used in user-level */
+         io.hae.cache = 0;
+         __sethae (io.hae.cache);      /* synchronize with hw */
+
+         fd = open ("/dev/mem", O_RDWR);
+         if (fd < 0)
+           return fd;
+
+         switch (io.sys)
+           {
+           case IOSYS_JENSEN:  base = JENSEN_IO_BASE; break;
+           case IOSYS_APECS:   base = APECS_IO_BASE; break;
+           case IOSYS_ALCOR:   base = ALCOR_IO_BASE; break;
+           default:
+             errno = ENODEV;
+             return -1;
+           }
+         addr  = port_to_cpu_addr (from, io.sys, 1);
+         addr &= PAGE_MASK;
+         len = port_to_cpu_addr (MAX_PORT, io.sys, 1) - addr;
+         io.base =
+           (unsigned long) __mmap (0, len, PROT_NONE, MAP_SHARED, fd, base);
+         close (fd);
+         if ((long) io.base == -1)
+           return -1;
+       }
+      prot = PROT_READ | PROT_WRITE;
     }
-    prot = PROT_READ | PROT_WRITE;
-  } else {
-    if (!io.base)
-      return 0;        /* never was turned on... */
+  else
+    {
+      if (!io.base)
+       return 0;       /* never was turned on... */
 
-    /* turnoff access to relevant pages: */
-    prot = PROT_NONE;
-  }
+      /* turnoff access to relevant pages: */
+      prot = PROT_NONE;
+    }
   addr  = port_to_cpu_addr (from, io.sys, 1);
   addr &= PAGE_MASK;
   len = port_to_cpu_addr (from + num, io.sys, 1) - addr;
@@ -358,13 +418,15 @@ _ioperm (unsigned long from, unsigned long num, int turn_on)
 int
 _iopl (unsigned int level)
 {
-    if (level > 3) {
+    if (level > 3)
+      {
        errno = EINVAL;
        return -1;
-    }
-    if (level) {
+      }
+    if (level)
+      {
        return _ioperm (0, MAX_PORT, 1);
-    }
+      }
     return 0;
 }
 
@@ -430,6 +492,14 @@ _inl (unsigned long port)
 }
 
 
+unsigned long
+_bus_base(void)
+{
+  if (!io.swp && init_iosys () < 0)
+    return -1;
+  return bus_memory_base;
+}
+
 weak_alias (_sethae, sethae);
 weak_alias (_ioperm, ioperm);
 weak_alias (_iopl, iopl);
@@ -439,3 +509,4 @@ weak_alias (_inl, inl);
 weak_alias (_outb, outb);
 weak_alias (_outw, outw);
 weak_alias (_outl, outl);
+weak_alias (_bus_base, bus_base);