__aeabi_ldivmod: fix sign logic
[minix.git] / drivers / fbd / rule.c
blob81ebc6620fdff0ead7809120edc7c9289ddd2885
1 #include <minix/drivers.h>
2 #include <minix/ioctl.h>
3 #include <sys/ioc_fbd.h>
5 #include "action.h"
6 #include "rule.h"
8 static struct fbd_rule rules[MAX_RULES];
9 static struct fbd_rule *matches[MAX_RULES];
10 static int nr_matches;
12 /*===========================================================================*
13 * rule_ctl *
14 *===========================================================================*/
15 int rule_ctl(int request, endpoint_t endpt, cp_grant_id_t grant)
17 /* Handle an I/O control request regarding rules. */
18 fbd_rulenum_t i;
19 int r;
21 /* Note that any of the safecopy calls may fail if the ioctl is
22 * improperly defined in userland; never panic if they fail!
24 switch (request) {
25 case FBDCADDRULE:
26 /* Find a free rule slot. */
27 for (i = 1; i <= MAX_RULES; i++)
28 if (rules[i-1].num == 0)
29 break;
31 if (i == MAX_RULES+1)
32 return ENOMEM;
34 /* Copy in the rule. */
35 if ((r = sys_safecopyfrom(endpt, grant, 0,
36 (vir_bytes) &rules[i-1], sizeof(rules[0]))) != OK)
37 return r;
39 /* Mark the rule as active, and return its number. */
40 rules[i-1].num = i;
42 return i;
44 case FBDCDELRULE:
45 /* Copy in the given rule number. */
46 if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &i,
47 sizeof(i))) != OK)
48 return r;
50 /* Fail if the given rule number is not valid or in use.
51 * Allow the caller to determine the maximum rule number.
53 if (i <= 0 || i > MAX_RULES) return EINVAL;
55 if (rules[i-1].num != i) return ENOENT;
57 /* Mark the rule as not active. */
58 rules[i-1].num = 0;
60 return OK;
62 case FBDCGETRULE:
63 /* Copy in just the rule number from the given structure. */
64 if ((r = sys_safecopyfrom(endpt, grant,
65 offsetof(struct fbd_rule, num), (vir_bytes) &i,
66 sizeof(i))) != OK)
67 return r;
69 /* Fail if the given rule number is not valid or in use.
70 * Allow the caller to determine the maximum rule number.
72 if (i <= 0 || i > MAX_RULES) return EINVAL;
74 if (rules[i-1].num != i) return ENOENT;
76 /* Copy out the entire rule as is. */
77 return sys_safecopyto(endpt, grant, 0, (vir_bytes) &rules[i-1],
78 sizeof(rules[0]));
80 default:
81 return EINVAL;
85 /*===========================================================================*
86 * rule_match *
87 *===========================================================================*/
88 static int rule_match(struct fbd_rule *rule, u64_t pos, size_t size, int flag)
90 /* Check whether the given rule matches the given parameters. As side
91 * effect, update counters in the rule as appropriate.
94 /* Ranges must overlap (start < pos+size && end > pos). */
95 if (cmp64(rule->start, add64u(pos, size)) >= 0 ||
96 (cmp64u(rule->end, 0) && cmp64(rule->end, pos) <= 0))
97 return FALSE;
99 /* Flags must match. */
100 if (!(rule->flags & flag)) return FALSE;
102 /* This is a match, but is it supposed to trigger yet? */
103 if (rule->skip > 0) {
104 rule->skip--;
106 return FALSE;
109 return TRUE;
112 /*===========================================================================*
113 * rule_find *
114 *===========================================================================*/
115 int rule_find(u64_t pos, size_t size, int flag)
117 /* Find all matching rules, and return a hook mask. */
118 struct fbd_rule *rule;
119 int i, hooks;
121 nr_matches = 0;
122 hooks = 0;
124 for (i = 0; i < MAX_RULES; i++) {
125 rule = &rules[i];
127 if (rule->num == 0) continue;
129 if (!rule_match(rule, pos, size, flag))
130 continue;
132 matches[nr_matches++] = rule;
134 /* If the rule has a limited lifetime, update it now. */
135 if (rule->count > 0) {
136 rule->count--;
138 /* Disable the rule from future matching. */
139 if (rule->count == 0)
140 rule->num = 0;
143 hooks |= action_mask(rule);
146 return hooks;
149 /*===========================================================================*
150 * rule_pre_hook *
151 *===========================================================================*/
152 void rule_pre_hook(iovec_t *iov, unsigned *count, size_t *size,
153 u64_t *pos)
155 int i;
157 for (i = 0; i < nr_matches; i++)
158 if (action_mask(matches[i]) & PRE_HOOK)
159 action_pre_hook(matches[i], iov, count, size, pos);
162 /*===========================================================================*
163 * rule_io_hook *
164 *===========================================================================*/
165 void rule_io_hook(char *buf, size_t size, u64_t pos, int flag)
167 int i;
169 for (i = 0; i < nr_matches; i++)
170 if (action_mask(matches[i]) & IO_HOOK)
171 action_io_hook(matches[i], buf, size, pos, flag);
174 /*===========================================================================*
175 * rule_post_hook *
176 *===========================================================================*/
177 void rule_post_hook(size_t osize, int *result)
179 int i;
181 for (i = 0; i < nr_matches; i++)
182 if (action_mask(matches[i]) & POST_HOOK)
183 action_post_hook(matches[i], osize, result);