/* Copyright (C) 1992-2025 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 Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library. If not, see
<https://www.gnu.org/licenses/>. */
/* I/O access is restricted to ISA port space (ports 0..65535).
Modern devices hopefully are sane enough not to put any performance
critical registers in i/o space.
On the first call to ioperm, the entire (E)ISA port space is mapped
into the virtual address space at address io.base. mprotect calls
are then used to enable/disable access to ports. Per page, there
are PAGE_SIZE>>IO_SHIFT I/O ports (e.g., 256 ports on a Low Cost Alpha
based system using 8KB pages).
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
sparse address space would work (e.g., the Low Cost Alpha chip has an
I/O address space that's 512MB large!). */
/* Make sure the ldbu/stb asms below are not expaneded to macros. */
#ifndef __alpha_bwx__
asm(".arch ev56");
#endif
#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 <sys/io.h>
#include <sysdep.h>
#include <sys/syscall.h>
#define PATH_ALPHA_SYSTYPE "/etc/alpha_systype"
#define PATH_CPUINFO "/proc/cpuinfo"
#define MAX_PORT 0x10000
#define vip volatile int *
#define vuip volatile unsigned int *
#define vusp volatile unsigned short *
#define vucp volatile unsigned char *
#define JENSEN_IO_BASE (0x300000000UL)
#define JENSEN_SPARSE_MEM (0x200000000UL)
/* 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 (0x1c0000000UL)
#define APECS_SPARSE_MEM (0x200000000UL)
#define APECS_DENSE_MEM (0x300000000UL)
/* The same holds for CIA and PYXIS, except for PYXIS we prefer BWX. */
#define CIA_IO_BASE (0x8580000000UL)
#define CIA_SPARSE_MEM (0x8000000000UL)
#define CIA_DENSE_MEM (0x8600000000UL)
#define PYXIS_IO_BASE (0x8900000000UL)
#define PYXIS_DENSE_MEM (0x8800000000UL)
/* SABLE is EV4, GAMMA is EV5 */
#define T2_IO_BASE (0x3a0000000UL)
#define T2_SPARSE_MEM (0x200000000UL)
#define T2_DENSE_MEM (0x3c0000000UL)
#define GAMMA_IO_BASE (0x83a0000000UL)
#define GAMMA_SPARSE_MEM (0x8200000000UL)
#define GAMMA_DENSE_MEM (0x83c0000000UL)
/* NOTE: these are hardwired to PCI bus 0 addresses!!! */
#define MCPCIA_IO_BASE (0xf980000000UL)
#define MCPCIA_SPARSE_MEM (0xf800000000UL)
#define MCPCIA_DENSE_MEM (0xf900000000UL)
/* Tsunami and Irongate use the same offsets, at least for hose 0. */
#define TSUNAMI_IO_BASE (0x801fc000000UL)
#define TSUNAMI_DENSE_MEM (0x80000000000UL)
/* Polaris has SPARSE space, but we prefer to use only DENSE
because of some idiosyncrasies in actually using SPARSE. */
#define POLARIS_IO_BASE (0xf9fc000000UL)
#define POLARIS_DENSE_MEM (0xf900000000UL)
typedef enum {
IOSYS_UNKNOWN, IOSYS_JENSEN, IOSYS_APECS, IOSYS_CIA, IOSYS_PYXIS, IOSYS_T2,
IOSYS_TSUNAMI, IOSYS_MCPCIA, IOSYS_GAMMA, IOSYS_POLARIS,
IOSYS_CPUDEP, IOSYS_PCIDEP
} iosys_t;
typedef enum {
IOSWIZZLE_JENSEN, IOSWIZZLE_SPARSE