1 | /* |
2 | * natfeat.c - ARAnyM hardware support via Native Features (natfeats) |
3 | * |
4 | * Copyright (c) 2005 Petr Stehlik of ARAnyM dev team |
5 | * |
6 | * Reworked for Linux by Roman Zippel <zippel@linux-m68k.org> |
7 | * |
8 | * This software may be used and distributed according to the terms of |
9 | * the GNU General Public License (GPL), incorporated herein by reference. |
10 | */ |
11 | |
12 | #include <linux/init.h> |
13 | #include <linux/types.h> |
14 | #include <linux/console.h> |
15 | #include <linux/string.h> |
16 | #include <linux/kernel.h> |
17 | #include <linux/module.h> |
18 | #include <linux/reboot.h> |
19 | #include <linux/io.h> |
20 | #include <asm/machdep.h> |
21 | #include <asm/natfeat.h> |
22 | |
23 | extern long nf_get_id_phys(unsigned long feature_name); |
24 | |
25 | asm("\n" |
26 | " .global nf_get_id_phys,nf_call\n" |
27 | "nf_get_id_phys:\n" |
28 | " .short 0x7300\n" |
29 | " rts\n" |
30 | "nf_call:\n" |
31 | " .short 0x7301\n" |
32 | " rts\n" |
33 | "1: moveq.l #0,%d0\n" |
34 | " rts\n" |
35 | " .section __ex_table,\"a\"\n" |
36 | " .long nf_get_id_phys,1b\n" |
37 | " .long nf_call,1b\n" |
38 | " .previous" ); |
39 | EXPORT_SYMBOL_GPL(nf_call); |
40 | |
41 | long nf_get_id(const char *feature_name) |
42 | { |
43 | /* feature_name may be in vmalloc()ed memory, so make a copy */ |
44 | char name_copy[32]; |
45 | ssize_t n; |
46 | |
47 | n = strscpy(name_copy, feature_name, sizeof(name_copy)); |
48 | if (n < 0) |
49 | return 0; |
50 | |
51 | return nf_get_id_phys(virt_to_phys(address: name_copy)); |
52 | } |
53 | EXPORT_SYMBOL_GPL(nf_get_id); |
54 | |
55 | void nfprint(const char *fmt, ...) |
56 | { |
57 | static char buf[256]; |
58 | va_list ap; |
59 | |
60 | va_start(ap, fmt); |
61 | vsnprintf(buf, size: 256, fmt, args: ap); |
62 | nf_call(nf_get_id(feature_name: "NF_STDERR" ), virt_to_phys(address: buf)); |
63 | va_end(ap); |
64 | } |
65 | |
66 | static void nf_poweroff(void) |
67 | { |
68 | long id = nf_get_id(feature_name: "NF_SHUTDOWN" ); |
69 | |
70 | if (id) |
71 | nf_call(id); |
72 | } |
73 | |
74 | void __init nf_init(void) |
75 | { |
76 | unsigned long id, version; |
77 | char buf[256]; |
78 | |
79 | id = nf_get_id(feature_name: "NF_VERSION" ); |
80 | if (!id) |
81 | return; |
82 | version = nf_call(id); |
83 | |
84 | id = nf_get_id(feature_name: "NF_NAME" ); |
85 | if (!id) |
86 | return; |
87 | nf_call(id, virt_to_phys(address: buf), 256); |
88 | buf[255] = 0; |
89 | |
90 | pr_info("NatFeats found (%s, %lu.%lu)\n" , buf, version >> 16, |
91 | version & 0xffff); |
92 | |
93 | register_platform_power_off(power_off: nf_poweroff); |
94 | } |
95 | |