#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.22 2021/02/28 21:34:34 tnn Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/proc.h>
#include <sys/cpu.h>
#include <sys/mount.h>
#include <sys/syscallargs.h>
#include <machine/fpu.h>
#include <machine/sysarch.h>
#include <dev/pci/pcivar.h>
u_int alpha_bus_window_count[ALPHA_BUS_TYPE_MAX + 1];
int (*alpha_bus_get_window)(int, int,
struct alpha_bus_space_translation *);
struct alpha_pci_chipset *alpha_pci_chipset;
int
sys_sysarch(struct lwp *l, const struct sys_sysarch_args *uap, register_t *retval)
{
int error = 0;
switch(SCARG(uap, op)) {
case ALPHA_FPGETMASK:
*retval = FP_C_TO_NETBSD_MASK(l->l_md.md_flags);
break;
case ALPHA_FPGETSTICKY:
*retval = FP_C_TO_NETBSD_FLAG(l->l_md.md_flags);
break;
case ALPHA_FPSETMASK:
case ALPHA_FPSETSTICKY:
{
fp_except m;
uint64_t md_flags;
struct alpha_fp_except_args args;
error = copyin(SCARG(uap, parms), &args, sizeof args);
if (error)
return error;
m = args.mask;
md_flags = l->l_md.md_flags;
switch (SCARG(uap, op)) {
case ALPHA_FPSETMASK:
*retval = FP_C_TO_NETBSD_MASK(md_flags);
md_flags = SET_FP_C_MASK(md_flags, m);
break;
case ALPHA_FPSETSTICKY:
*retval = FP_C_TO_NETBSD_FLAG(md_flags);
md_flags = SET_FP_C_FLAG(md_flags, m);
break;
}
alpha_write_fp_c(l, md_flags);
break;
}
case ALPHA_GET_FP_C:
{
struct alpha_fp_c_args args;
args.fp_c = alpha_read_fp_c(l);
error = copyout(&args, SCARG(uap, parms), sizeof args);
break;
}
case ALPHA_SET_FP_C:
{
struct alpha_fp_c_args args;
error = copyin(SCARG(uap, parms), &args, sizeof args);
if (error)
return (error);
if ((args.fp_c >> 63) != 0)
args.fp_c |= IEEE_INHERIT;
alpha_write_fp_c(l, args.fp_c);
break;
}
case ALPHA_BUS_GET_WINDOW_COUNT:
{
struct alpha_bus_get_window_count_args args;
error = copyin(SCARG(uap, parms), &args, sizeof(args));
if (error)
return (error);
if (args.type > ALPHA_BUS_TYPE_MAX)
return (EINVAL);
if (alpha_bus_window_count[args.type] == 0)
return (EOPNOTSUPP);
args.count = alpha_bus_window_count[args.type];
error = copyout(&args, SCARG(uap, parms), sizeof(args));
break;
}
case ALPHA_BUS_GET_WINDOW:
{
struct alpha_bus_space_translation abst;
struct alpha_bus_get_window_args args;
error = copyin(SCARG(uap, parms), &args, sizeof(args));
if (error)
return (error);
if (args.type > ALPHA_BUS_TYPE_MAX)
return (EINVAL);
if (alpha_bus_window_count[args.type] == 0)
return (EOPNOTSUPP);
if (args.window >= alpha_bus_window_count[args.type])
return (EINVAL);
error = (*alpha_bus_get_window)(args.type, args.window,
&abst);
if (error)
return (error);
error = copyout(&abst, args.translation, sizeof(abst));
break;
}
#if NPCI > 0
case ALPHA_PCI_CONF_READWRITE:
{
struct alpha_pci_conf_readwrite_args args;
pcitag_t tag;
error = copyin(SCARG(uap, parms), &args, sizeof(args));
if (error)
return (error);
if (alpha_pci_chipset == NULL)
return (EOPNOTSUPP);
if (args.bus > 0xff)
return (EINVAL);
if (args.device > pci_bus_maxdevs(alpha_pci_chipset, args.bus))
return (EINVAL);
if (args.function > 7)
return (EINVAL);
if (args.reg > 0xff)
return (EINVAL);
tag = pci_make_tag(alpha_pci_chipset, args.bus, args.device,
args.function);
if (args.write)
pci_conf_write(alpha_pci_chipset, tag, args.reg,
args.val);
else {
args.val = pci_conf_read(alpha_pci_chipset, tag,
args.reg);
error = copyout(&args, SCARG(uap, parms), sizeof(args));
}
break;
}
#endif
default:
error = EINVAL;
break;
}
return (error);
}
int
cpu_lwp_setprivate(lwp_t *l, void *addr)
{
struct pcb *pcb;
pcb = lwp_getpcb(l);
pcb->pcb_hw.apcb_unique = (unsigned long)addr;
if (l == curlwp)
alpha_pal_wrunique(pcb->pcb_hw.apcb_unique);
return 0;
}