/* * This function should only ever be called with interrupts disabled. */ static void hs_unmap_irq(hs_socket_t *sp, unsigned int irq) { DPRINTK("hs_unmap_irq(sock=%d irq=%d)\n", hs_sockno(sp), irq); if (irq >= HS_NUM_MAPPED_IRQS) return; /* restore the original irq controller */ irq_desc[irq].handler = hs_mapped_irq[irq].old_handler; }
static void hs_socket_disable_ireq(hs_socket_t *sp) { unsigned short cscier; DPRINTK("hs_socket_disable_ireq(sock=%d)\n", hs_sockno(sp)); cscier = hs_in(sp, CSCIER); cscier &= ~HD64465_PCCCSCIER_PIREQE_MASK; hs_out(sp, cscier, CSCIER); }
/* * This function should only ever be called with interrupts disabled. */ static void hs_map_irq(hs_socket_t *sp, unsigned int irq) { DPRINTK("hs_map_irq(sock=%d irq=%d)\n", hs_sockno(sp), irq); if (irq >= HS_NUM_MAPPED_IRQS) return; hs_mapped_irq[irq].sock = sp; /* insert ourselves as the irq controller */ hs_mapped_irq[irq].old_handler = irq_desc[irq].handler; irq_desc[irq].handler = &hd64465_ss_irq_type; }
/* * This function should only ever be called with interrupts disabled. */ static void hs_map_irq(hs_socket_t *sp, unsigned int irq) { DPRINTK("hs_map_irq(sock=%d irq=%d)\n", hs_sockno(sp), irq); if (irq >= HS_NUM_MAPPED_IRQS) return; hs_mapped_irq[irq].sock = sp; /* insert ourselves as the irq controller */ hs_mapped_irq[irq].old_handler = irq_desc[irq].handler; irq_desc[irq].handler = &hd64465_ss_irq_type; /* * some drivers may not ever mess with there interrupts, so * we must make sure the interrupt for the slot is in the right state */ if (irq_desc[irq].status & IRQ_DISABLED) hs_socket_disable_ireq(hs_mapped_irq[irq].sock); else if ((irq_desc[irq].status & IRQ_INPROGRESS) == 0) hs_socket_enable_ireq(hs_mapped_irq[irq].sock); }
static int hs_set_voltages(hs_socket_t *sp, int Vcc, int Vpp) { u_int psr; u_int vcci = 0; u_int sock = hs_sockno(sp); DPRINTK("hs_set_voltage(%d, %d, %d)\n", sock, Vcc, Vpp); switch (Vcc) { case 0: vcci = 0; break; case 33: vcci = 1; break; case 50: vcci = 2; break; default: return 0; } /* Note: Vpp = 120 not supported -- Greg Banks */ if (Vpp != 0 && Vpp != Vcc) return 0; /* The PSR register holds 8 of the 9 bits which control * the TPS2206 via its serial interface. */ psr = inw(HD64465_REG_PCCPSR); switch (sock) { case 0: psr &= 0x0f; psr |= hs_tps2206_avcc[vcci]; psr |= (Vpp == 0 ? 0x00 : 0x02); break; case 1: psr &= 0xf0; psr |= hs_tps2206_bvcc[vcci]; psr |= (Vpp == 0 ? 0x00 : 0x20); break; }; outw(psr, HD64465_REG_PCCPSR); return 1; }
static void hs_interrupt(int irq, void *dev, struct pt_regs *regs) { hs_socket_t *sp = (hs_socket_t *)dev; u_int events = 0; u_int cscr; cscr = hs_in(sp, CSCR); DPRINTK("hs_interrupt, cscr=%04x\n", cscr); /* check for bus-related changes to be reported to Socket Services */ if (cscr & HD64465_PCCCSCR_PCDC) { /* double-check for a 16-bit card, as we don't support CardBus */ if ((hs_in(sp, ISR) & HD64465_PCCISR_PCD_MASK) != 0) { printk(KERN_NOTICE MODNAME ": socket %d, card not a supported card type or not inserted correctly\n", hs_sockno(sp)); /* Don't do the rest unless a card is present */ cscr &= ~(HD64465_PCCCSCR_PCDC| HD64465_PCCCSCR_PRC| HD64465_PCCCSCR_PBW| HD64465_PCCCSCR_PBD| HD64465_PCCCSCR_PSC); } else { cscr &= ~HD64465_PCCCSCR_PCDC; events |= SS_DETECT; /* card insertion or removal */ } } if (cscr & HD64465_PCCCSCR_PRC) { cscr &= ~HD64465_PCCCSCR_PRC; events |= SS_READY; /* ready signal changed */ } if (cscr & HD64465_PCCCSCR_PBW) { cscr &= ~HD64465_PCCCSCR_PSC; events |= SS_BATWARN; /* battery warning */ } if (cscr & HD64465_PCCCSCR_PBD) { cscr &= ~HD64465_PCCCSCR_PSC; events |= SS_BATDEAD; /* battery dead */ } if (cscr & HD64465_PCCCSCR_PSC) { cscr &= ~HD64465_PCCCSCR_PSC; events |= SS_STSCHG; /* STSCHG (status changed) signal */ } if (cscr & HD64465_PCCCSCR_PIREQ) { cscr &= ~HD64465_PCCCSCR_PIREQ; /* This should have been dealt with during irq demux */ printk(KERN_NOTICE MODNAME ": unexpected IREQ from card\n"); } hs_out(sp, cscr, CSCR); if (events) { /* * Arrange for events to be reported to the registered * event handler function (from CardServices) in a process * context (keventd) "soon". */ spin_lock(&hs_pending_event_lock); sp->pending_events |= events; spin_unlock(&hs_pending_event_lock); schedule_task(&hs_events_task); } }