184121Sdfr/*-
284121Sdfr * Copyright (c) 2001 Doug Rabson
384121Sdfr * All rights reserved.
484121Sdfr *
584121Sdfr * Redistribution and use in source and binary forms, with or without
684121Sdfr * modification, are permitted provided that the following conditions
784121Sdfr * are met:
884121Sdfr * 1. Redistributions of source code must retain the above copyright
984121Sdfr *    notice, this list of conditions and the following disclaimer.
1084121Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1184121Sdfr *    notice, this list of conditions and the following disclaimer in the
1284121Sdfr *    documentation and/or other materials provided with the distribution.
1384121Sdfr *
1484121Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1584121Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1684121Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1784121Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1884121Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1984121Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2084121Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2184121Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2284121Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2384121Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2484121Sdfr * SUCH DAMAGE.
2584121Sdfr */
2684121Sdfr
27135453Smarcel#include <sys/cdefs.h>
28135453Smarcel__FBSDID("$FreeBSD$");
29135453Smarcel
3084121Sdfr#include <sys/param.h>
3184121Sdfr#include <sys/systm.h>
32205234Smarcel#include <sys/bus.h>
3395245Smarcel#include <sys/kernel.h>
3495245Smarcel#include <sys/malloc.h>
3595245Smarcel#include <vm/vm.h>
3695245Smarcel#include <vm/vm_kern.h>
37135453Smarcel#include <machine/efi.h>
38205234Smarcel#include <machine/intr.h>
3996061Smarcel#include <machine/md_var.h>
4084121Sdfr#include <machine/sal.h>
4185656Smarcel#include <machine/smp.h>
4284121Sdfr
43205234Smarcelint ia64_ipi_wakeup;
4496442Smarcel
4584121Sdfrstatic struct ia64_fdesc sal_fdesc;
4684121Sdfrstatic sal_entry_t	fake_sal;
4784121Sdfr
4884121Sdfrextern u_int64_t	ia64_pal_entry;
4984121Sdfrsal_entry_t		*ia64_sal_entry = fake_sal;
5084121Sdfr
51135453Smarcelstatic struct uuid sal_table = EFI_TABLE_SAL;
52135453Smarcelstatic struct sal_system_table *sal_systbl;
53135453Smarcel
5484121Sdfrstatic struct ia64_sal_result
5584121Sdfrfake_sal(u_int64_t a1, u_int64_t a2, u_int64_t a3, u_int64_t a4,
5684121Sdfr	 u_int64_t a5, u_int64_t a6, u_int64_t a7, u_int64_t a8)
5784121Sdfr{
5884121Sdfr	struct ia64_sal_result res;
5984121Sdfr	res.sal_status = -3;
6084121Sdfr	res.sal_result[0] = 0;
6184121Sdfr	res.sal_result[1] = 0;
6284121Sdfr	res.sal_result[2] = 0;
6384121Sdfr	return res;
6484121Sdfr}
6584121Sdfr
6684121Sdfrvoid
67135453Smarcelia64_sal_init(void)
6884121Sdfr{
6984121Sdfr	static int sizes[6] = {
7084121Sdfr		48, 32, 16, 32, 16, 16
7184121Sdfr	};
7284121Sdfr	u_int8_t *p;
73205234Smarcel	int error, i;
7484121Sdfr
75135453Smarcel	sal_systbl = efi_get_table(&sal_table);
76135453Smarcel	if (sal_systbl == NULL)
77135453Smarcel		return;
78135453Smarcel
79183299Sobrien	if (bcmp(sal_systbl->sal_signature, SAL_SIGNATURE, 4)) {
8084121Sdfr		printf("Bad signature for SAL System Table\n");
8184121Sdfr		return;
8284121Sdfr	}
8384121Sdfr
84135453Smarcel	p = (u_int8_t *) (sal_systbl + 1);
85135453Smarcel	for (i = 0; i < sal_systbl->sal_entry_count; i++) {
8685211Smarcel		switch (*p) {
8785211Smarcel		case 0: {
8884121Sdfr			struct sal_entrypoint_descriptor *dp;
8985211Smarcel
9085211Smarcel			dp = (struct sal_entrypoint_descriptor*)p;
9184121Sdfr			ia64_pal_entry = IA64_PHYS_TO_RR7(dp->sale_pal_proc);
9284121Sdfr			if (bootverbose)
9384121Sdfr				printf("PAL Proc at 0x%lx\n", ia64_pal_entry);
9484121Sdfr			sal_fdesc.func = IA64_PHYS_TO_RR7(dp->sale_sal_proc);
9584121Sdfr			sal_fdesc.gp = IA64_PHYS_TO_RR7(dp->sale_sal_gp);
9684121Sdfr			if (bootverbose)
9784121Sdfr				printf("SAL Proc at 0x%lx, GP at 0x%lx\n",
9885211Smarcel				    sal_fdesc.func, sal_fdesc.gp);
9984121Sdfr			ia64_sal_entry = (sal_entry_t *) &sal_fdesc;
10085211Smarcel			break;
10184121Sdfr		}
10285211Smarcel		case 5: {
10385211Smarcel			struct sal_ap_wakeup_descriptor *dp;
10485211Smarcel
10585211Smarcel			dp = (struct sal_ap_wakeup_descriptor*)p;
10696442Smarcel			if (dp->sale_mechanism != 0) {
10796442Smarcel				printf("SAL: unsupported AP wake-up mechanism "
10896442Smarcel				    "(%d)\n", dp->sale_mechanism);
10996442Smarcel				break;
11096442Smarcel			}
11196442Smarcel
112205234Smarcel			/* Reserve the XIV so that we won't use it. */
113205234Smarcel			error = ia64_xiv_reserve(dp->sale_vector,
114205234Smarcel			    IA64_XIV_PLAT, NULL);
115205234Smarcel			if (error) {
116205234Smarcel				printf("SAL: invalid AP wake-up XIV (%#lx)\n",
117205234Smarcel				    dp->sale_vector);
11896442Smarcel				break;
11996442Smarcel			}
12096442Smarcel
121205234Smarcel			ia64_ipi_wakeup = dp->sale_vector;
12285211Smarcel			if (bootverbose)
123205234Smarcel				printf("SAL: AP wake-up XIV: %#x\n",
124205234Smarcel				    ia64_ipi_wakeup);
12585211Smarcel			break;
12685211Smarcel		}
12785211Smarcel		}
12884121Sdfr		p += sizes[*p];
12984121Sdfr	}
13084121Sdfr}
131