aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/pcmcia_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia/pcmcia_ioctl.c')
-rw-r--r--drivers/pcmcia/pcmcia_ioctl.c90
1 files changed, 88 insertions, 2 deletions
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 5f186abca108..758ece8dc362 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -138,6 +138,94 @@ static int proc_read_drivers(char *buf, char **start, off_t pos,
138} 138}
139#endif 139#endif
140 140
141
142#ifdef CONFIG_PCMCIA_PROBE
143
144static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
145{
146 int irq;
147 u32 mask;
148
149 irq = adj->resource.irq.IRQ;
150 if ((irq < 0) || (irq > 15))
151 return CS_BAD_IRQ;
152
153 if (adj->Action != REMOVE_MANAGED_RESOURCE)
154 return 0;
155
156 mask = 1 << irq;
157
158 if (!(s->irq_mask & mask))
159 return 0;
160
161 s->irq_mask &= ~mask;
162
163 return 0;
164}
165
166#else
167
168static inline int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) {
169 return CS_SUCCESS;
170}
171
172#endif
173
174static int pcmcia_adjust_resource_info(adjust_t *adj)
175{
176 struct pcmcia_socket *s;
177 int ret = CS_UNSUPPORTED_FUNCTION;
178 unsigned long flags;
179
180 down_read(&pcmcia_socket_list_rwsem);
181 list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
182
183 if (adj->Resource == RES_IRQ)
184 ret = adjust_irq(s, adj);
185
186 else if (s->resource_ops->add_io) {
187 unsigned long begin, end;
188
189 /* you can't use the old interface if the new
190 * one was used before */
191 spin_lock_irqsave(&s->lock, flags);
192 if ((s->resource_setup_new) &&
193 !(s->resource_setup_old)) {
194 spin_unlock_irqrestore(&s->lock, flags);
195 continue;
196 } else if (!(s->resource_setup_old))
197 s->resource_setup_old = 1;
198 spin_unlock_irqrestore(&s->lock, flags);
199
200 switch (adj->Resource) {
201 case RES_MEMORY_RANGE:
202 begin = adj->resource.memory.Base;
203 end = adj->resource.memory.Base + adj->resource.memory.Size - 1;
204 if (s->resource_ops->add_mem)
205 ret =s->resource_ops->add_mem(s, adj->Action, begin, end);
206 case RES_IO_RANGE:
207 begin = adj->resource.io.BasePort;
208 end = adj->resource.io.BasePort + adj->resource.io.NumPorts - 1;
209 if (s->resource_ops->add_io)
210 ret = s->resource_ops->add_io(s, adj->Action, begin, end);
211 }
212 if (!ret) {
213 /* as there's no way we know this is the
214 * last call to adjust_resource_info, we
215 * always need to assume this is the latest
216 * one... */
217 spin_lock_irqsave(&s->lock, flags);
218 s->resource_setup_done = 1;
219 spin_unlock_irqrestore(&s->lock, flags);
220 }
221 }
222 }
223 up_read(&pcmcia_socket_list_rwsem);
224
225 return (ret);
226}
227
228
141/*====================================================================== 229/*======================================================================
142 230
143 These manage a ring buffer of events pending for one user process 231 These manage a ring buffer of events pending for one user process
@@ -546,8 +634,6 @@ static u_int ds_poll(struct file *file, poll_table *wait)
546 634
547/*====================================================================*/ 635/*====================================================================*/
548 636
549extern int pcmcia_adjust_resource_info(adjust_t *adj);
550
551static int ds_ioctl(struct inode * inode, struct file * file, 637static int ds_ioctl(struct inode * inode, struct file * file,
552 u_int cmd, u_long arg) 638 u_int cmd, u_long arg)
553{ 639{