|
@@ -138,6 +138,94 @@ static int proc_read_drivers(char *buf, char **start, off_t pos,
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+
|
|
|
+#ifdef CONFIG_PCMCIA_PROBE
|
|
|
+
|
|
|
+static int adjust_irq(struct pcmcia_socket *s, adjust_t *adj)
|
|
|
+{
|
|
|
+ int irq;
|
|
|
+ u32 mask;
|
|
|
+
|
|
|
+ irq = adj->resource.irq.IRQ;
|
|
|
+ if ((irq < 0) || (irq > 15))
|
|
|
+ return CS_BAD_IRQ;
|
|
|
+
|
|
|
+ if (adj->Action != REMOVE_MANAGED_RESOURCE)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ mask = 1 << irq;
|
|
|
+
|
|
|
+ if (!(s->irq_mask & mask))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ s->irq_mask &= ~mask;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+#else
|
|
|
+
|
|
|
+static inline int adjust_irq(struct pcmcia_socket *s, adjust_t *adj) {
|
|
|
+ return CS_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+static int pcmcia_adjust_resource_info(adjust_t *adj)
|
|
|
+{
|
|
|
+ struct pcmcia_socket *s;
|
|
|
+ int ret = CS_UNSUPPORTED_FUNCTION;
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ down_read(&pcmcia_socket_list_rwsem);
|
|
|
+ list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
|
|
|
+
|
|
|
+ if (adj->Resource == RES_IRQ)
|
|
|
+ ret = adjust_irq(s, adj);
|
|
|
+
|
|
|
+ else if (s->resource_ops->add_io) {
|
|
|
+ unsigned long begin, end;
|
|
|
+
|
|
|
+ /* you can't use the old interface if the new
|
|
|
+ * one was used before */
|
|
|
+ spin_lock_irqsave(&s->lock, flags);
|
|
|
+ if ((s->resource_setup_new) &&
|
|
|
+ !(s->resource_setup_old)) {
|
|
|
+ spin_unlock_irqrestore(&s->lock, flags);
|
|
|
+ continue;
|
|
|
+ } else if (!(s->resource_setup_old))
|
|
|
+ s->resource_setup_old = 1;
|
|
|
+ spin_unlock_irqrestore(&s->lock, flags);
|
|
|
+
|
|
|
+ switch (adj->Resource) {
|
|
|
+ case RES_MEMORY_RANGE:
|
|
|
+ begin = adj->resource.memory.Base;
|
|
|
+ end = adj->resource.memory.Base + adj->resource.memory.Size - 1;
|
|
|
+ if (s->resource_ops->add_mem)
|
|
|
+ ret =s->resource_ops->add_mem(s, adj->Action, begin, end);
|
|
|
+ case RES_IO_RANGE:
|
|
|
+ begin = adj->resource.io.BasePort;
|
|
|
+ end = adj->resource.io.BasePort + adj->resource.io.NumPorts - 1;
|
|
|
+ if (s->resource_ops->add_io)
|
|
|
+ ret = s->resource_ops->add_io(s, adj->Action, begin, end);
|
|
|
+ }
|
|
|
+ if (!ret) {
|
|
|
+ /* as there's no way we know this is the
|
|
|
+ * last call to adjust_resource_info, we
|
|
|
+ * always need to assume this is the latest
|
|
|
+ * one... */
|
|
|
+ spin_lock_irqsave(&s->lock, flags);
|
|
|
+ s->resource_setup_done = 1;
|
|
|
+ spin_unlock_irqrestore(&s->lock, flags);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ up_read(&pcmcia_socket_list_rwsem);
|
|
|
+
|
|
|
+ return (ret);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/*======================================================================
|
|
|
|
|
|
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)
|
|
|
|
|
|
/*====================================================================*/
|
|
|
|
|
|
-extern int pcmcia_adjust_resource_info(adjust_t *adj);
|
|
|
-
|
|
|
static int ds_ioctl(struct inode * inode, struct file * file,
|
|
|
u_int cmd, u_long arg)
|
|
|
{
|