diff options
Diffstat (limited to 'Documentation/laptops')
-rw-r--r-- | Documentation/laptops/hpfall.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/Documentation/laptops/hpfall.c b/Documentation/laptops/hpfall.c new file mode 100644 index 000000000000..a4a8fc5d05d4 --- /dev/null +++ b/Documentation/laptops/hpfall.c | |||
@@ -0,0 +1,146 @@ | |||
1 | /* Disk protection for HP machines. | ||
2 | * | ||
3 | * Copyright 2008 Eric Piel | ||
4 | * Copyright 2009 Pavel Machek <pavel@ucw.cz> | ||
5 | * | ||
6 | * GPLv2. | ||
7 | */ | ||
8 | |||
9 | #include <stdio.h> | ||
10 | #include <stdlib.h> | ||
11 | #include <unistd.h> | ||
12 | #include <fcntl.h> | ||
13 | #include <sys/stat.h> | ||
14 | #include <sys/types.h> | ||
15 | #include <string.h> | ||
16 | #include <stdint.h> | ||
17 | #include <errno.h> | ||
18 | #include <signal.h> | ||
19 | #include <sys/mman.h> | ||
20 | #include <sched.h> | ||
21 | |||
22 | char unload_heads_path[64]; | ||
23 | |||
24 | int set_unload_heads_path(char *device) | ||
25 | { | ||
26 | char devname[64]; | ||
27 | |||
28 | if (strlen(device) <= 5 || strncmp(device, "/dev/", 5) != 0) | ||
29 | return -EINVAL; | ||
30 | strncpy(devname, device + 5, sizeof(devname)); | ||
31 | |||
32 | snprintf(unload_heads_path, sizeof(unload_heads_path), | ||
33 | "/sys/block/%s/device/unload_heads", devname); | ||
34 | return 0; | ||
35 | } | ||
36 | int valid_disk(void) | ||
37 | { | ||
38 | int fd = open(unload_heads_path, O_RDONLY); | ||
39 | if (fd < 0) { | ||
40 | perror(unload_heads_path); | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | close(fd); | ||
45 | return 1; | ||
46 | } | ||
47 | |||
48 | void write_int(char *path, int i) | ||
49 | { | ||
50 | char buf[1024]; | ||
51 | int fd = open(path, O_RDWR); | ||
52 | if (fd < 0) { | ||
53 | perror("open"); | ||
54 | exit(1); | ||
55 | } | ||
56 | sprintf(buf, "%d", i); | ||
57 | if (write(fd, buf, strlen(buf)) != strlen(buf)) { | ||
58 | perror("write"); | ||
59 | exit(1); | ||
60 | } | ||
61 | close(fd); | ||
62 | } | ||
63 | |||
64 | void set_led(int on) | ||
65 | { | ||
66 | write_int("/sys/class/leds/hp::hddprotect/brightness", on); | ||
67 | } | ||
68 | |||
69 | void protect(int seconds) | ||
70 | { | ||
71 | write_int(unload_heads_path, seconds*1000); | ||
72 | } | ||
73 | |||
74 | int on_ac(void) | ||
75 | { | ||
76 | // /sys/class/power_supply/AC0/online | ||
77 | } | ||
78 | |||
79 | int lid_open(void) | ||
80 | { | ||
81 | // /proc/acpi/button/lid/LID/state | ||
82 | } | ||
83 | |||
84 | void ignore_me(void) | ||
85 | { | ||
86 | protect(0); | ||
87 | set_led(0); | ||
88 | } | ||
89 | |||
90 | int main(int argc, char **argv) | ||
91 | { | ||
92 | int fd, ret; | ||
93 | struct sched_param param; | ||
94 | |||
95 | if (argc == 1) | ||
96 | ret = set_unload_heads_path("/dev/sda"); | ||
97 | else if (argc == 2) | ||
98 | ret = set_unload_heads_path(argv[1]); | ||
99 | else | ||
100 | ret = -EINVAL; | ||
101 | |||
102 | if (ret || !valid_disk()) { | ||
103 | fprintf(stderr, "usage: %s <device> (default: /dev/sda)\n", | ||
104 | argv[0]); | ||
105 | exit(1); | ||
106 | } | ||
107 | |||
108 | fd = open("/dev/freefall", O_RDONLY); | ||
109 | if (fd < 0) { | ||
110 | perror("/dev/freefall"); | ||
111 | return EXIT_FAILURE; | ||
112 | } | ||
113 | |||
114 | daemon(0, 0); | ||
115 | param.sched_priority = sched_get_priority_max(SCHED_FIFO); | ||
116 | sched_setscheduler(0, SCHED_FIFO, ¶m); | ||
117 | mlockall(MCL_CURRENT|MCL_FUTURE); | ||
118 | |||
119 | signal(SIGALRM, ignore_me); | ||
120 | |||
121 | for (;;) { | ||
122 | unsigned char count; | ||
123 | |||
124 | ret = read(fd, &count, sizeof(count)); | ||
125 | alarm(0); | ||
126 | if ((ret == -1) && (errno == EINTR)) { | ||
127 | /* Alarm expired, time to unpark the heads */ | ||
128 | continue; | ||
129 | } | ||
130 | |||
131 | if (ret != sizeof(count)) { | ||
132 | perror("read"); | ||
133 | break; | ||
134 | } | ||
135 | |||
136 | protect(21); | ||
137 | set_led(1); | ||
138 | if (1 || on_ac() || lid_open()) | ||
139 | alarm(2); | ||
140 | else | ||
141 | alarm(20); | ||
142 | } | ||
143 | |||
144 | close(fd); | ||
145 | return EXIT_SUCCESS; | ||
146 | } | ||