+/********************************************************************/
+/* Interrupts */
+/********************************************************************/
+
+static inline void if_cs_enable_ints(struct if_cs_card *card)
+{
+ lbs_deb_enter(LBS_DEB_CS);
+ if_cs_write16(card, IF_CS_H_INT_MASK, 0);
+}
+
+static inline void if_cs_disable_ints(struct if_cs_card *card)
+{
+ lbs_deb_enter(LBS_DEB_CS);
+ if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK);
+}
+
+
+static irqreturn_t if_cs_interrupt(int irq, void *data)
+{
+ struct if_cs_card *card = data;
+ struct lbs_private *priv = card->priv;
+ u16 cause;
+
+ lbs_deb_enter(LBS_DEB_CS);
+
+ cause = if_cs_read16(card, IF_CS_C_INT_CAUSE);
+ if_cs_write16(card, IF_CS_C_INT_CAUSE, cause & IF_CS_C_IC_MASK);
+
+ lbs_deb_cs("cause 0x%04x\n", cause);
+ if (cause == 0) {
+ /* Not for us */
+ return IRQ_NONE;
+ }
+
+ if (cause == 0xffff) {
+ /* Read in junk, the card has probably been removed */
+ card->priv->surpriseremoved = 1;
+ return IRQ_HANDLED;
+ }
+
+ /* TODO: I'm not sure what the best ordering is */
+
+ cause = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK;
+
+ if (cause & IF_CS_C_S_RX_UPLD_RDY) {
+ struct sk_buff *skb;
+ lbs_deb_cs("rx packet\n");
+ skb = if_cs_receive_data(priv);
+ if (skb)
+ lbs_process_rxed_packet(priv, skb);
+ }
+
+ if (cause & IF_CS_H_IC_TX_OVER) {
+ lbs_deb_cs("tx over\n");
+ lbs_host_to_card_done(priv);
+ }
+
+ if (cause & IF_CS_C_S_CMD_UPLD_RDY) {
+ unsigned long flags;
+ u8 i;
+
+ lbs_deb_cs("cmd upload ready\n");
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ i = (priv->resp_idx == 0) ? 1 : 0;
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+ BUG_ON(priv->resp_len[i]);
+ if_cs_receive_cmdres(priv, priv->resp_buf[i],
+ &priv->resp_len[i]);
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ lbs_notify_command_response(priv, i);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ }
+
+ if (cause & IF_CS_H_IC_HOST_EVENT) {
+ u16 event = if_cs_read16(priv->card, IF_CS_C_STATUS)
+ & IF_CS_C_S_STATUS_MASK;
+ if_cs_write16(priv->card, IF_CS_H_INT_CAUSE,
+ IF_CS_H_IC_HOST_EVENT);
+ lbs_deb_cs("eventcause 0x%04x\n", event);
+ lbs_queue_event(priv, event >> 8 & 0xff);
+ }
+
+ return IRQ_HANDLED;
+}
+
+
+
+