- } else {
- *base = res->start;
- }
- return ret;
-}
-
-/*======================================================================
-
- This checks to see if an interrupt is available, with support
- for interrupt sharing. We don't support reserving interrupts
- yet. If the interrupt is available, we allocate it.
-
-======================================================================*/
-
-#ifdef CONFIG_PCMCIA_PROBE
-
-static irqreturn_t fake_irq(int i, void *d, struct pt_regs *r) { return IRQ_NONE; }
-static inline int check_irq(int irq)
-{
- if (request_irq(irq, fake_irq, 0, "bogus", NULL) != 0)
- return -1;
- free_irq(irq, NULL);
- return 0;
-}
-
-int try_irq(u_int Attributes, int irq, int specific)
-{
- irq_info_t *info = &irq_table[irq];
- int ret = 0;
-
- down(&rsrc_sem);
- if (info->Attributes & RES_ALLOCATED) {
- switch (Attributes & IRQ_TYPE) {
- case IRQ_TYPE_EXCLUSIVE:
- ret = CS_IN_USE;
- break;
- case IRQ_TYPE_TIME:
- if ((info->Attributes & RES_IRQ_TYPE)
- != RES_IRQ_TYPE_TIME) {
- ret = CS_IN_USE;
- break;
- }
- if (Attributes & IRQ_FIRST_SHARED) {
- ret = CS_BAD_ATTRIBUTE;
- break;
- }
- info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
- info->time_share++;
- break;
- case IRQ_TYPE_DYNAMIC_SHARING:
- if ((info->Attributes & RES_IRQ_TYPE)
- != RES_IRQ_TYPE_DYNAMIC) {
- ret = CS_IN_USE;
- break;
- }
- if (Attributes & IRQ_FIRST_SHARED) {
- ret = CS_BAD_ATTRIBUTE;
- break;
- }
- info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
- info->dyn_share++;
- break;
- }
- } else {
- if ((info->Attributes & RES_RESERVED) && !specific) {
- ret = CS_IN_USE;
- goto out;
- }
- if (check_irq(irq) != 0) {
- ret = CS_IN_USE;
- goto out;
- }
- switch (Attributes & IRQ_TYPE) {
- case IRQ_TYPE_EXCLUSIVE:
- info->Attributes |= RES_ALLOCATED;
- break;
- case IRQ_TYPE_TIME:
- if (!(Attributes & IRQ_FIRST_SHARED)) {
- ret = CS_BAD_ATTRIBUTE;
- break;
- }
- info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
- info->time_share = 1;
- break;
- case IRQ_TYPE_DYNAMIC_SHARING:
- if (!(Attributes & IRQ_FIRST_SHARED)) {
- ret = CS_BAD_ATTRIBUTE;
- break;
- }
- info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
- info->dyn_share = 1;
- break;
- }
- }
- out:
- up(&rsrc_sem);
- return ret;
-}
-
-#endif
-
-/*====================================================================*/
-
-#ifdef CONFIG_PCMCIA_PROBE
-
-void undo_irq(u_int Attributes, int irq)
-{
- irq_info_t *info;
-
- info = &irq_table[irq];
- down(&rsrc_sem);
- switch (Attributes & IRQ_TYPE) {
- case IRQ_TYPE_EXCLUSIVE:
- info->Attributes &= RES_RESERVED;
- break;
- case IRQ_TYPE_TIME:
- info->time_share--;
- if (info->time_share == 0)
- info->Attributes &= RES_RESERVED;
- break;
- case IRQ_TYPE_DYNAMIC_SHARING:
- info->dyn_share--;
- if (info->dyn_share == 0)
- info->Attributes &= RES_RESERVED;
- break;
- }
- up(&rsrc_sem);
-}
-
-#endif
-
-/*======================================================================
-
- The various adjust_* calls form the external interface to the
- resource database.
-
-======================================================================*/
-
-static int adjust_memory(adjust_t *adj)
-{
- u_long base, num;
- int ret;
-
- base = adj->resource.memory.Base;
- num = adj->resource.memory.Size;
- if ((num == 0) || (base+num-1 < base))
- return CS_BAD_SIZE;
-
- ret = CS_SUCCESS;
-
- down(&rsrc_sem);
- switch (adj->Action) {
- case ADD_MANAGED_RESOURCE:
- ret = add_interval(&mem_db, base, num);
- break;
- case REMOVE_MANAGED_RESOURCE:
- ret = sub_interval(&mem_db, base, num);
- if (ret == CS_SUCCESS) {
- struct pcmcia_socket *socket;
- down_read(&pcmcia_socket_list_rwsem);
- list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
- release_cis_mem(socket);
- up_read(&pcmcia_socket_list_rwsem);
- }
- break;
- default:
- ret = CS_UNSUPPORTED_FUNCTION;
- }
- up(&rsrc_sem);
-
- return ret;
-}
-
-/*====================================================================*/
-
-static int adjust_io(adjust_t *adj)
-{
- int base, num, ret = CS_SUCCESS;
-
- base = adj->resource.io.BasePort;
- num = adj->resource.io.NumPorts;
- if ((base < 0) || (base > 0xffff))
- return CS_BAD_BASE;
- if ((num <= 0) || (base+num > 0x10000) || (base+num <= base))
- return CS_BAD_SIZE;
-
- down(&rsrc_sem);
- switch (adj->Action) {
- case ADD_MANAGED_RESOURCE:
- if (add_interval(&io_db, base, num) != 0) {
- ret = CS_IN_USE;
- break;
- }
-#ifdef CONFIG_PCMCIA_PROBE
- if (probe_io)
- do_io_probe(base, num);
-#endif
- break;
- case REMOVE_MANAGED_RESOURCE:
- sub_interval(&io_db, base, num);
- break;
- default:
- ret = CS_UNSUPPORTED_FUNCTION;
- break;
- }
- up(&rsrc_sem);
-
- return ret;
-}
-
-/*====================================================================*/
-
-static int adjust_irq(adjust_t *adj)
-{
- int ret = CS_SUCCESS;
-#ifdef CONFIG_PCMCIA_PROBE
- int irq;
- irq_info_t *info;
-
- irq = adj->resource.irq.IRQ;
- if ((irq < 0) || (irq > 15))
- return CS_BAD_IRQ;
- info = &irq_table[irq];
-
- down(&rsrc_sem);
- switch (adj->Action) {
- case ADD_MANAGED_RESOURCE:
- if (info->Attributes & RES_REMOVED)
- info->Attributes &= ~(RES_REMOVED|RES_ALLOCATED);
- else
- if (adj->Attributes & RES_ALLOCATED) {
- ret = CS_IN_USE;
- break;
- }
- if (adj->Attributes & RES_RESERVED)
- info->Attributes |= RES_RESERVED;
- else
- info->Attributes &= ~RES_RESERVED;
- break;
- case REMOVE_MANAGED_RESOURCE:
- if (info->Attributes & RES_REMOVED) {
- ret = 0;
- break;
- }
- if (info->Attributes & RES_ALLOCATED) {
- ret = CS_IN_USE;
- break;