static irqreturn_t snd_bt87x_interrupt(int irq, void *dev_id) { struct snd_bt87x *chip = dev_id; unsigned int status, irq_status; status = snd_bt87x_readl(chip, REG_INT_STAT); irq_status = status & chip->interrupt_mask; if (!irq_status) return IRQ_NONE; snd_bt87x_writel(chip, REG_INT_STAT, irq_status); if (irq_status & ERROR_INTERRUPTS) { if (irq_status & (INT_FBUS | INT_FTRGT)) snd_printk(KERN_WARNING "FIFO overrun, status %#08x\n", status); if (irq_status & INT_OCERR) snd_printk(KERN_ERR "internal RISC error, status %#08x\n", status); if (irq_status & (INT_PPERR | INT_RIPERR | INT_PABORT)) snd_bt87x_pci_error(chip, irq_status); } if ((irq_status & INT_RISCI) && (chip->reg_control & CTL_ACAP_EN)) { int current_block, irq_block; /* assume that exactly one line has been recorded */ chip->current_line = (chip->current_line + 1) % chip->lines; /* but check if some interrupts have been skipped */ current_block = chip->current_line * 16 / chip->lines; irq_block = status >> INT_RISCS_SHIFT; if (current_block != irq_block) chip->current_line = (irq_block * chip->lines + 15) / 16; snd_pcm_period_elapsed(chip->substream); }
static void snd_bt87x_pci_error(struct snd_bt87x *chip, unsigned int status) { u16 pci_status; pci_read_config_word(chip->pci, PCI_STATUS, &pci_status); pci_status &= PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY; pci_write_config_word(chip->pci, PCI_STATUS, pci_status); if (pci_status != PCI_STATUS_DETECTED_PARITY) snd_printk(KERN_ERR "Aieee - PCI error! status %#08x, PCI status %#04x\n", status & ERROR_INTERRUPTS, pci_status); else { snd_printk(KERN_ERR "Aieee - PCI parity error detected!\n"); /* error 'handling' similar to aic7xxx_pci.c: */ chip->pci_parity_errors++; if (chip->pci_parity_errors > 20) { snd_printk(KERN_ERR "Too many PCI parity errors observed.\n"); snd_printk(KERN_ERR "Some device on this bus is generating bad parity.\n"); snd_printk(KERN_ERR "This is an error *observed by*, not *generated by*, this card.\n"); snd_printk(KERN_ERR "PCI parity error checking has been disabled.\n"); chip->interrupt_mask &= ~(INT_PPERR | INT_RIPERR); snd_bt87x_writel(chip, REG_INT_MASK, chip->interrupt_mask); } } }
static irqreturn_t snd_bt87x_interrupt(int irq, void *dev_id, struct pt_regs *regs) { bt87x_t *chip = dev_id; unsigned int status; status = snd_bt87x_readl(chip, REG_INT_STAT); if (!(status & MY_INTERRUPTS)) return IRQ_NONE; snd_bt87x_writel(chip, REG_INT_STAT, status & MY_INTERRUPTS); if (status & ERROR_INTERRUPTS) { if (status & (INT_FBUS | INT_FTRGT)) snd_printk(KERN_WARNING "FIFO overrun, status %#08x\n", status); if (status & INT_OCERR) snd_printk(KERN_ERR "internal RISC error, status %#08x\n", status); if (status & (INT_PPERR | INT_RIPERR | INT_PABORT)) { u16 pci_status; pci_read_config_word(chip->pci, PCI_STATUS, &pci_status); pci_write_config_word(chip->pci, PCI_STATUS, pci_status & (PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY)); snd_printk(KERN_ERR "Aieee - PCI error! status %#08x, PCI status %#04x\n", status, pci_status); } } if ((status & INT_RISCI) && (chip->reg_control & CTL_ACAP_EN)) { int current_block, irq_block; /* assume that exactly one line has been recorded */ chip->current_line = (chip->current_line + 1) % chip->lines; /* but check if some interrupts have been skipped */ current_block = chip->current_line * 16 / chip->lines; irq_block = status >> INT_RISCS_SHIFT; if (current_block != irq_block) chip->current_line = (irq_block * chip->lines + 15) / 16; snd_pcm_period_elapsed(chip->substream); }