1/* $NetBSD: sys_machdep.c,v 1.20 2011/02/24 04:28:44 joerg Exp $ */
2
3/*-
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University.
34 * All rights reserved.
35 *
36 * Author: Chris G. Demetriou
37 *
38 * Permission to use, copy, modify and distribute this software and
39 * its documentation is hereby granted, provided that both the copyright
40 * notice and this permission notice appear in all copies of the
41 * software, derivative works or modified versions, and any portions
42 * thereof, and that both notices appear in supporting documentation.
43 *
44 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
45 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
46 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
47 *
48 * Carnegie Mellon requests users of this software to return to
49 *
50 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
51 *  School of Computer Science
52 *  Carnegie Mellon University
53 *  Pittsburgh PA 15213-3890
54 *
55 * any improvements or extensions that they make and grant Carnegie the
56 * rights to redistribute these changes.
57 */
58
59#include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
60
61__KERNEL_RCSID(0, "$NetBSD: sys_machdep.c,v 1.20 2011/02/24 04:28:44 joerg Exp $");
62
63#include <sys/param.h>
64#include <sys/systm.h>
65#include <sys/device.h>
66#include <sys/proc.h>
67#include <sys/cpu.h>
68
69#include <sys/mount.h>
70#include <sys/syscallargs.h>
71
72#include <machine/fpu.h>
73#include <machine/sysarch.h>
74
75#include <dev/pci/pcivar.h>
76
77u_int	alpha_bus_window_count[ALPHA_BUS_TYPE_MAX + 1];
78
79int	(*alpha_bus_get_window)(int, int,
80	    struct alpha_bus_space_translation *);
81
82struct alpha_pci_chipset *alpha_pci_chipset;
83
84int
85sys_sysarch(struct lwp *l, const struct sys_sysarch_args *uap, register_t *retval)
86{
87	/* {
88		syscallarg(int) op;
89		syscallarg(void *) parms;
90	} */
91	int error = 0;
92
93	switch(SCARG(uap, op)) {
94	case ALPHA_FPGETMASK:
95		*retval = FP_C_TO_NETBSD_MASK(l->l_md.md_flags);
96		break;
97	case ALPHA_FPGETSTICKY:
98		*retval = FP_C_TO_NETBSD_FLAG(l->l_md.md_flags);
99		break;
100	case ALPHA_FPSETMASK:
101	case ALPHA_FPSETSTICKY:
102	    {
103		fp_except m;
104		uint64_t md_flags;
105		struct alpha_fp_except_args args;
106
107		error = copyin(SCARG(uap, parms), &args, sizeof args);
108		if (error)
109			return error;
110		m = args.mask;
111		md_flags = l->l_md.md_flags;
112		switch (SCARG(uap, op)) {
113		case ALPHA_FPSETMASK:
114			*retval = FP_C_TO_NETBSD_MASK(md_flags);
115			md_flags = SET_FP_C_MASK(md_flags, m);
116			break;
117		case ALPHA_FPSETSTICKY:
118			*retval = FP_C_TO_NETBSD_FLAG(md_flags);
119			md_flags = SET_FP_C_FLAG(md_flags, m);
120			break;
121		}
122		alpha_write_fp_c(l, md_flags);
123		break;
124	    }
125	case ALPHA_GET_FP_C:
126	    {
127		struct alpha_fp_c_args args;
128
129		args.fp_c = alpha_read_fp_c(l);
130		error = copyout(&args, SCARG(uap, parms), sizeof args);
131		break;
132	    }
133	case ALPHA_SET_FP_C:
134	    {
135		struct alpha_fp_c_args args;
136
137		error = copyin(SCARG(uap, parms), &args, sizeof args);
138		if (error)
139			return (error);
140		if ((args.fp_c >> 63) != 0)
141			args.fp_c |= IEEE_INHERIT;
142		alpha_write_fp_c(l, args.fp_c);
143		break;
144	    }
145	case ALPHA_BUS_GET_WINDOW_COUNT:
146	    {
147		struct alpha_bus_get_window_count_args args;
148
149		error = copyin(SCARG(uap, parms), &args, sizeof(args));
150		if (error)
151			return (error);
152
153		if (args.type > ALPHA_BUS_TYPE_MAX)
154			return (EINVAL);
155
156		if (alpha_bus_window_count[args.type] == 0)
157			return (EOPNOTSUPP);
158
159		args.count = alpha_bus_window_count[args.type];
160		error = copyout(&args, SCARG(uap, parms), sizeof(args));
161		break;
162	    }
163
164	case ALPHA_BUS_GET_WINDOW:
165	    {
166		struct alpha_bus_space_translation abst;
167		struct alpha_bus_get_window_args args;
168
169		error = copyin(SCARG(uap, parms), &args, sizeof(args));
170		if (error)
171			return (error);
172
173		if (args.type > ALPHA_BUS_TYPE_MAX)
174			return (EINVAL);
175
176		if (alpha_bus_window_count[args.type] == 0)
177			return (EOPNOTSUPP);
178
179		if (args.window >= alpha_bus_window_count[args.type])
180			return (EINVAL);
181
182		error = (*alpha_bus_get_window)(args.type, args.window,
183		    &abst);
184		if (error)
185			return (error);
186
187		error = copyout(&abst, args.translation, sizeof(abst));
188		break;
189	    }
190
191	case ALPHA_PCI_CONF_READWRITE:
192	    {
193		struct alpha_pci_conf_readwrite_args args;
194		pcitag_t tag;
195
196		error = copyin(SCARG(uap, parms), &args, sizeof(args));
197		if (error)
198			return (error);
199
200		if (alpha_pci_chipset == NULL)
201			return (EOPNOTSUPP);
202
203		if (args.bus > 0xff)		/* XXX MAGIC NUMBER */
204			return (EINVAL);
205		if (args.device > pci_bus_maxdevs(alpha_pci_chipset, args.bus))
206			return (EINVAL);
207		if (args.function > 7)		/* XXX MAGIC NUMBER */
208			return (EINVAL);
209		if (args.reg > 0xff)		/* XXX MAGIC NUMBER */
210			return (EINVAL);
211
212		tag = pci_make_tag(alpha_pci_chipset, args.bus, args.device,
213		    args.function);
214
215		if (args.write)
216			pci_conf_write(alpha_pci_chipset, tag, args.reg,
217			    args.val);
218		else {
219			args.val = pci_conf_read(alpha_pci_chipset, tag,
220			    args.reg);
221			error = copyout(&args, SCARG(uap, parms), sizeof(args));
222		}
223		break;
224	    }
225
226	default:
227		error = EINVAL;
228		break;
229	}
230
231	return (error);
232}
233
234int
235cpu_lwp_setprivate(lwp_t *l, void *addr)
236{
237	struct pcb *pcb;
238
239	pcb = lwp_getpcb(l);
240	pcb->pcb_hw.apcb_unique = (unsigned long)addr;
241	if (l == curlwp)
242		alpha_pal_wrunique(pcb->pcb_hw.apcb_unique);
243	return 0;
244}
245