예제 #1
0
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);
	}
예제 #2
0
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);
		}
	}
}
예제 #3
0
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);
	}