static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, int buffer_length) { u8 *b; int l; deb_ts("tmp_buffer_length=%d, buffer_length=%d\n", fc_usb->tmp_buffer_length, buffer_length); if (fc_usb->tmp_buffer_length > 0) { memcpy(fc_usb->tmp_buffer+fc_usb->tmp_buffer_length, buffer, buffer_length); fc_usb->tmp_buffer_length += buffer_length; b = fc_usb->tmp_buffer; l = fc_usb->tmp_buffer_length; } else { b=buffer; l=buffer_length; } while (l >= 190) { if (*b == 0xff) { switch (*(b+1) & 0x03) { case 0x01: /* media packet */ if (*(b+2) == 0x47) flexcop_pass_dmx_packets( fc_usb->fc_dev, b+2, 1); else deb_ts( "not ts packet %02x %02x %02x %02x \n", *(b+2), *(b+3), *(b+4), *(b+5)); b += 190; l -= 190; break; default: deb_ts("wrong packet type\n"); l = 0; break; } } else { deb_ts("wrong header\n"); l = 0; } } if (l>0) memcpy(fc_usb->tmp_buffer, b, l); fc_usb->tmp_buffer_length = l; }
/* When PID filtering is turned on, we use the timer IRQ, because small amounts * of data need to be passed to the user space instantly as well. When PID * filtering is turned off, we use the page-change-IRQ */ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id, struct pt_regs *regs) { struct flexcop_pci *fc_pci = dev_id; struct flexcop_device *fc = fc_pci->fc_dev; flexcop_ibi_value v; irqreturn_t ret = IRQ_HANDLED; spin_lock_irq(&fc_pci->irq_lock); v = fc->read_ibi_reg(fc,irq_20c); /* errors */ if (v.irq_20c.Data_receiver_error) deb_chk("data receiver error\n"); if (v.irq_20c.Continuity_error_flag) deb_chk("Contunuity error flag is set\n"); if (v.irq_20c.LLC_SNAP_FLAG_set) deb_chk("LLC_SNAP_FLAG_set is set\n"); if (v.irq_20c.Transport_Error) deb_chk("Transport error\n"); if ((fc_pci->count % 1000) == 0) deb_chk("%d valid irq took place so far\n",fc_pci->count); if (v.irq_20c.DMA1_IRQ_Status == 1) { if (fc_pci->active_dma1_addr == 0) flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr0,fc_pci->dma[0].size / 188); else flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr1,fc_pci->dma[0].size / 188); deb_irq("page change to page: %d\n",!fc_pci->active_dma1_addr); fc_pci->active_dma1_addr = !fc_pci->active_dma1_addr; } else if (v.irq_20c.DMA1_Timer_Status == 1) { /* for the timer IRQ we only can use buffer dmx feeding, because we don't have * complete TS packets when reading from the DMA memory */ dma_addr_t cur_addr = fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2; u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0; deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ", jiffies_to_usecs(jiffies - fc_pci->last_irq), v.raw, (unsigned long long)cur_addr, cur_pos, fc_pci->last_dma1_cur_pos); fc_pci->last_irq = jiffies; /* buffer end was reached, restarted from the beginning * pass the data from last_cur_pos to the buffer end to the demux */ if (cur_pos < fc_pci->last_dma1_cur_pos) { deb_irq(" end was reached: passing %d bytes ",(fc_pci->dma[0].size*2 - 1) - fc_pci->last_dma1_cur_pos); flexcop_pass_dmx_data(fc_pci->fc_dev, fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos, (fc_pci->dma[0].size*2) - fc_pci->last_dma1_cur_pos); fc_pci->last_dma1_cur_pos = 0; } if (cur_pos > fc_pci->last_dma1_cur_pos) { deb_irq(" passing %d bytes ",cur_pos - fc_pci->last_dma1_cur_pos); flexcop_pass_dmx_data(fc_pci->fc_dev, fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos, cur_pos - fc_pci->last_dma1_cur_pos); } deb_irq("\n"); fc_pci->last_dma1_cur_pos = cur_pos; fc_pci->count++; } else { deb_irq("isr for flexcop called, apparently without reason (%08x)\n",v.raw); ret = IRQ_NONE; } spin_unlock_irq(&fc_pci->irq_lock); return ret; }