📄 skystar2.c
字号:
} } } /* if we have not used a filter, this pid depended on whole bandwith */ dprintk("%s: pid=%d whole_bandwidth\n", __FUNCTION__, pid); whole_bandwidth_dec(adapter); return 1;}/* Adds a PID to the filters. Adding a pid more than once is possible, we keep reference counts. Whole stream available through pid==0x2000. Returns 1 on success, -1 on error */static int add_pid(struct adapter *adapter, u16 pid){ int i; dprintk("%s: pid=%d\n", __FUNCTION__, pid); if (pid > 0x1ffe && pid != 0x2000) return -1; // check if the pid is already present for (i = 0; i < adapter->pid_count; i++) if (adapter->pid_list[i] == pid) { adapter->pid_rc[i]++; // increment ref counter return 1; } if (adapter->pid_count == N_PID_SLOTS) return -1; // no more pids can be added adapter->pid_list[adapter->pid_count] = pid; // register pid adapter->pid_rc[adapter->pid_count] = 1; adapter->pid_count++; // hardware setting add_hw_pid(adapter, pid); return 1;}/* Removes a PID from the filters. */static int remove_pid(struct adapter *adapter, u16 pid){ int i; dprintk("%s: pid=%d\n", __FUNCTION__, pid); if (pid > 0x1ffe && pid != 0x2000) return -1; // check if the pid is present (it must be!) for (i = 0; i < adapter->pid_count; i++) { if (adapter->pid_list[i] == pid) { adapter->pid_rc[i]--; if (adapter->pid_rc[i] <= 0) { // remove from the list adapter->pid_count--; adapter->pid_list[i]=adapter->pid_list[adapter->pid_count]; adapter->pid_rc[i] = adapter->pid_rc[adapter->pid_count]; // hardware setting remove_hw_pid(adapter, pid); } return 1; } } return -1;}/* dma & irq */static void ctrl_enable_smc(struct adapter *adapter, u32 op){ write_reg_bitfield(adapter, 0x208, 0x00000800, op ? 0x00000800 : 0);}static void dma_enable_disable_irq(struct adapter *adapter, u32 flag1, u32 flag2, u32 flag3){ adapter->dma_ctrl = adapter->dma_ctrl & 0x000f0000; if (flag1 == 0) { if (flag2 == 0) adapter->dma_ctrl = adapter->dma_ctrl & ~0x00010000; else adapter->dma_ctrl = adapter->dma_ctrl | 0x00010000; if (flag3 == 0) adapter->dma_ctrl = adapter->dma_ctrl & ~0x00020000; else adapter->dma_ctrl = adapter->dma_ctrl | 0x00020000; } else { if (flag2 == 0) adapter->dma_ctrl = adapter->dma_ctrl & ~0x00040000; else adapter->dma_ctrl = adapter->dma_ctrl | 0x00040000; if (flag3 == 0) adapter->dma_ctrl = adapter->dma_ctrl & ~0x00080000; else adapter->dma_ctrl = adapter->dma_ctrl | 0x00080000; }}static void irq_dma_enable_disable_irq(struct adapter *adapter, u32 op){ u32 value; value = read_reg_dw(adapter, 0x208) & 0xfff0ffff; if (op != 0) value = value | (adapter->dma_ctrl & 0x000f0000); write_reg_dw(adapter, 0x208, value);}/* FlexCopII has 2 dma channels. DMA1 is used to transfer TS data to system memory. The DMA1 buffer is divided in 2 subbuffers of equal size. FlexCopII will transfer TS data to one subbuffer, signal an interrupt when the subbuffer is full and continue fillig the second subbuffer. For DMA1: subbuffer size in 32-bit words is stored in the first 24 bits of register 0x004. The last 8 bits of register 0x004 contain the number of subbuffers. the first 30 bits of register 0x000 contain the address of the first subbuffer. The last 2 bits contain 0, when dma1 is disabled and 1, when dma1 is enabled. the first 30 bits of register 0x00c contain the address of the second subbuffer. the last 2 bits contain 1. register 0x008 will contain the address of the subbuffer that was filled with TS data, when FlexCopII will generate an interrupt. For DMA2: subbuffer size in 32-bit words is stored in the first 24 bits of register 0x014. The last 8 bits of register 0x014 contain the number of subbuffers. the first 30 bits of register 0x010 contain the address of the first subbuffer. The last 2 bits contain 0, when dma1 is disabled and 1, when dma1 is enabled. the first 30 bits of register 0x01c contain the address of the second subbuffer. the last 2 bits contain 1. register 0x018 contains the address of the subbuffer that was filled with TS data, when FlexCopII generates an interrupt.*/static int dma_init_dma(struct adapter *adapter, u32 dma_channel){ u32 subbuffers, subbufsize, subbuf0, subbuf1; if (dma_channel == 0) { dprintk("%s: Initializing DMA1 channel\n", __FUNCTION__); subbuffers = 2; subbufsize = (((adapter->dmaq1.buffer_size / 2) / 4) << 8) | subbuffers; subbuf0 = adapter->dmaq1.bus_addr & 0xfffffffc; subbuf1 = ((adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) & 0xfffffffc) | 1; dprintk("%s: first subbuffer address = 0x%x\n", __FUNCTION__, subbuf0); udelay(1000); write_reg_dw(adapter, 0x000, subbuf0); dprintk("%s: subbuffer size = 0x%x\n", __FUNCTION__, (subbufsize >> 8) * 4); udelay(1000); write_reg_dw(adapter, 0x004, subbufsize); dprintk("%s: second subbuffer address = 0x%x\n", __FUNCTION__, subbuf1); udelay(1000); write_reg_dw(adapter, 0x00c, subbuf1); dprintk("%s: counter = 0x%x\n", __FUNCTION__, adapter->dmaq1.bus_addr & 0xfffffffc); write_reg_dw(adapter, 0x008, adapter->dmaq1.bus_addr & 0xfffffffc); udelay(1000); if (subbuffers == 0) dma_enable_disable_irq(adapter, 0, 1, 0); else dma_enable_disable_irq(adapter, 0, 1, 1); irq_dma_enable_disable_irq(adapter, 1); sram_set_media_dest(adapter, 1); sram_set_net_dest(adapter, 1); sram_set_cai_dest(adapter, 2); sram_set_cao_dest(adapter, 2); } if (dma_channel == 1) { dprintk("%s: Initializing DMA2 channel\n", __FUNCTION__); subbuffers = 2; subbufsize = (((adapter->dmaq2.buffer_size / 2) / 4) << 8) | subbuffers; subbuf0 = adapter->dmaq2.bus_addr & 0xfffffffc; subbuf1 = ((adapter->dmaq2.bus_addr + adapter->dmaq2.buffer_size / 2) & 0xfffffffc) | 1; dprintk("%s: first subbuffer address = 0x%x\n", __FUNCTION__, subbuf0); udelay(1000); write_reg_dw(adapter, 0x010, subbuf0); dprintk("%s: subbuffer size = 0x%x\n", __FUNCTION__, (subbufsize >> 8) * 4); udelay(1000); write_reg_dw(adapter, 0x014, subbufsize); dprintk("%s: second buffer address = 0x%x\n", __FUNCTION__, subbuf1); udelay(1000); write_reg_dw(adapter, 0x01c, subbuf1); sram_set_cai_dest(adapter, 2); } return 0;}static void ctrl_enable_receive_data(struct adapter *adapter, u32 op){ if (op == 0) { write_reg_bitfield(adapter, 0x208, 0x00008000, 0); adapter->dma_status = adapter->dma_status & ~0x00000004; } else { write_reg_bitfield(adapter, 0x208, 0x00008000, 0x00008000); adapter->dma_status = adapter->dma_status | 0x00000004; }}/* bit 0 of dma_mask is set to 1 if dma1 channel has to be enabled/disabled bit 1 of dma_mask is set to 1 if dma2 channel has to be enabled/disabled*/static void dma_start_stop(struct adapter *adapter, u32 dma_mask, int start_stop){ u32 dma_enable, dma1_enable, dma2_enable; dprintk("%s: dma_mask=%x\n", __FUNCTION__, dma_mask); if (start_stop == 1) { dprintk("%s: starting dma\n", __FUNCTION__); dma1_enable = 0; dma2_enable = 0; if (((dma_mask & 1) != 0) && ((adapter->dma_status & 1) == 0) && (adapter->dmaq1.bus_addr != 0)) { adapter->dma_status = adapter->dma_status | 1; dma1_enable = 1; } if (((dma_mask & 2) != 0) && ((adapter->dma_status & 2) == 0) && (adapter->dmaq2.bus_addr != 0)) { adapter->dma_status = adapter->dma_status | 2; dma2_enable = 1; } // enable dma1 and dma2 if ((dma1_enable == 1) && (dma2_enable == 1)) { write_reg_dw(adapter, 0x000, adapter->dmaq1.bus_addr | 1); write_reg_dw(adapter, 0x00c, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1); write_reg_dw(adapter, 0x010, adapter->dmaq2.bus_addr | 1); ctrl_enable_receive_data(adapter, 1); return; } // enable dma1 if ((dma1_enable == 1) && (dma2_enable == 0)) { write_reg_dw(adapter, 0x000, adapter->dmaq1.bus_addr | 1); write_reg_dw(adapter, 0x00c, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1); ctrl_enable_receive_data(adapter, 1); return; } // enable dma2 if ((dma1_enable == 0) && (dma2_enable == 1)) { write_reg_dw(adapter, 0x010, adapter->dmaq2.bus_addr | 1); ctrl_enable_receive_data(adapter, 1); return; } // start dma if ((dma1_enable == 0) && (dma2_enable == 0)) { ctrl_enable_receive_data(adapter, 1); return; } } else { dprintk("%s: stopping dma\n", __FUNCTION__); dma_enable = adapter->dma_status & 0x00000003; if (((dma_mask & 1) != 0) && ((adapter->dma_status & 1) != 0)) { dma_enable = dma_enable & 0xfffffffe; } if (((dma_mask & 2) != 0) && ((adapter->dma_status & 2) != 0)) { dma_enable = dma_enable & 0xfffffffd; } // stop dma if ((dma_enable == 0) && ((adapter->dma_status & 4) != 0)) { ctrl_enable_receive_data(adapter, 0); udelay(3000); } // disable dma1 if (((dma_mask & 1) != 0) && ((adapter->dma_status & 1) != 0) && (adapter->dmaq1.bus_addr != 0)) { write_reg_dw(adapter, 0x000, adapter->dmaq1.bus_addr); write_reg_dw(adapter, 0x00c, (adapter->dmaq1.bus_addr + adapter->dmaq1.buffer_size / 2) | 1); adapter->dma_status = adapter->dma_status & ~0x00000001; } // disable dma2 if (((dma_mask & 2) != 0) && ((adapter->dma_status & 2) != 0) && (adapter->dmaq2.bus_addr != 0)) { write_reg_dw(adapter, 0x010, adapter->dmaq2.bus_addr); adapter->dma_status = adapter->dma_status & ~0x00000002; } }}static void open_stream(struct adapter *adapter, u16 pid){ u32 dma_mask; ++adapter->capturing; filter_enable_mask_filter(adapter, 1); add_pid(adapter, pid); dprintk("%s: adapter->dma_status=%x\n", __FUNCTION__, adapter->dma_status); if ((adapter->dma_status & 7) != 7) { dma_mask = 0; if (((adapter->dma_status & 0x10000000) != 0) && ((adapter->dma_status & 1) == 0)) { dma_mask = dma_mask | 1; adapter->dmaq1.head = 0; adapter->dmaq1.tail = 0; memset(adapter->dmaq1.buffer, 0, adapter->dmaq1.buffer_size); } if (((adapter->dma_status & 0x20000000) != 0) && ((adapter->dma_status & 2) == 0)) { dma_mask = dma_mask | 2; adapter->dmaq2.head = 0; adapter->dmaq2.tail = 0; } if (dma_mask != 0) { irq_dma_enable_disable_irq(adapter, 1); dma_start_stop(adapter, dma_mask, 1); } }}static void close_stream(struct adapter *adapter, u16 pid){ if (adapter->capturing > 0) --adapter->capturing; dprintk("%s: dma_status=%x\n", __FUNCTION__, adapter->dma_status); if (adapter->capturing == 0) { u32 dma_mask = 0; if ((adapter->dma_status & 1) != 0) dma_mask = dma_mask | 0x00000001; if ((adapter->dma_status & 2) != 0) dma_mask = dma_mask | 0x00000002; if (dma_mask != 0) { dma_start_stop(adapter, dma_mask, 0); } } remove_pid(adapter, pid);}static void interrupt_service_dma1(struct adapter *adapter){ struct dvb_demux *dvbdmx = &adapter->demux; int n_cur_dma_counter; u32 n_num_bytes_parsed; u32 n_num_new_bytes_transferred; u32 dw_default_packet_size = 188; u8 gb_tmp_buffer[188]; u8 *pb_dma_buf_cur_pos; n_cur_dma_counter = readl(adapter->io_mem + 0x008) - adapter->dmaq1.bus_addr; n_cur_dma_counter = (n_cur_dma_counter / dw_default_packet_size) * dw_default_packet_size; if ((n_cur_dma_counter < 0) || (n_cur_dma_counter > adapter->dmaq1.buffer_size)) { dprintk("%s: dma counter outside dma buffer\n", __FUNCTION__); return; } adapter->dmaq1.head = n_cur_dma_counter; if (adapter->dmaq1.tail <= n_cur_dma_counter) { n_num_new_bytes_transferred = n_cur_dma_counter - adapter->dmaq1.tail; } else { n_num_new_bytes_transferred = (adapter->dmaq1.buffer_size - adapter->dmaq1.tail) + n_cur_dma_counter; } ddprintk("%s: n_cur_dma_counter = %d\n", __FUNCTION__, n_cur_dma_counter); ddprintk("%s: dmaq1.tail = %d\n", __FUNCTION__, adapter->dmaq1.tail); ddprintk("%s: bytes_transferred = %d\n", __FUNCTION__, n_num_new_bytes_transferred); if (n_num_new_bytes_transferred < dw_default_packet_size) return; n_num_bytes_parsed = 0; while (n_num_bytes_parsed < n_num_new_bytes_transferred) { pb_dma_buf_cur_pos = adapter->dmaq1.buffer + adapter->dmaq1.tail; if (adapter->dmaq1.buffer + adapter->dmaq1.buffer_size < adapter->dmaq1.buffer + adapter->dmaq1.tail + 188) { memcpy(gb_tmp_buffer, adapter->dmaq1.buffer + adapter->dmaq1.tail, adapter->dmaq1.buffer_size - adapter->dmaq1.tail); memcpy(gb_tmp_buffer + (adapter->dmaq1.buffer_size - adapter->dmaq1.tail), adapter->dmaq1.buffer, (188 - (adapter->dmaq1.buffer_size - adapter->dmaq1.tail))); pb_dma_buf_cur_pos = gb_tmp_buffer; } if (adapter->capturing != 0) { dvb_dmx_swfilter_packets(dvbdmx, pb_dma_buf_cur_pos, dw_default_packet_size / 188); } n_num_bytes_parsed = n_num_bytes_parsed + dw_default_packet_size; adapter->dmaq1.tail = adapter->dmaq1.tail + dw_default_packet_size; if (adapter->dmaq1.tail >= adapter->dmaq1.buffer_size) adapter->dmaq1.tail = adapter->dmaq1.tail - adapter->dmaq1.buffer_size; };}static void interrupt_service_dma2(struct adapter *adapter){ printk("%s:\n", __FUNCTION__);}static irqreturn_t isr(int irq, void *dev_id, struct pt_regs *regs){ struct adapter *tmp = dev_id; u32 value; ddprintk("%s:\n", __FUNCTION__); spin_lock_irq(&tmp->lock); if (0 == ((value = read_reg_dw(tmp, 0x20c)) & 0x0f)) { spin_unlock_irq(&tmp->lock); return IRQ_NONE; } while (value != 0) { if ((value & 0x03) != 0) interrupt_service_dma1(tmp); if ((value & 0x0c) != 0) interrupt_service_dma2(tmp); value = read_reg_dw(tmp, 0x20c) & 0x0f; } spin_unlock_irq(&tmp->lock); return IRQ_HANDLED;}static void init_dma_queue(struct adapter *adapter){ dma_addr_t dma_addr; if (adapter->dmaq1.buffer != 0) return; adapter->dmaq1.head = 0; adapter->dmaq1.tail = 0; adapter->dmaq1.buffer = 0; adapter->dmaq1.buffer = pci_alloc_consistent(adapter->pdev, SIZE_OF_BUF_DMA1 + 0x80, &dma_addr); if (adapter->dmaq1.buffer != 0) { memset(adapter->dmaq1.buffer, 0, SIZE_OF_BUF_DMA1); adapter->dmaq1.bus_addr = dma_addr; adapter->dmaq1.buffer_size = SIZE_OF_BUF_DMA1; dma_init_dma(adapter, 0); adapter->dma_status = adapter->dma_status | 0x10000000; ddprintk("%s: allocated dma buffer at 0x%p, length=%d\n", __FUNCTION__, adapter->dmaq1.buffer, SIZE_OF_BUF_DMA1); } else { adapter->dma_status = adapter->dma_status & ~0x10000000; } if (adapter->dmaq2.buffer != 0) return; adapter->dmaq2.head = 0; adapter->dmaq2.tail = 0; adapter->dmaq2.buffer = 0; adapter->dmaq2.buffer = pci_alloc_consistent(adapter->pdev, SIZE_OF_BUF_DMA2 + 0x80, &dma_addr); if (adapter->dmaq2.buffer != 0) { memset(adapter->dmaq2.buffer, 0, SIZE_OF_BUF_DMA2); adapter->dmaq2.bus_addr = dma_addr; adapter->dmaq2.buffer_size = SIZE_OF_BUF_DMA2; dma_init_dma(adapter, 1); adapter->dma_status = adapter->dma_status | 0x20000000; ddprintk("%s: allocated dma buffer at 0x%p, length=%d\n", __FUNCTION__, adapter->dmaq2.buffer, (int) SIZE_OF_BUF_DMA2); } else { adapter->dma_status = adapter->dma_status & ~0x20000000; }}static void free_dma_queue(struct adapter *adapter){ if (adapter->dmaq1.buffer != 0) { pci_free_consistent(adapter->pdev, SIZE_OF_BUF_DMA1 + 0x80, adapter->dmaq1.buffer, adapter->dmaq1.bus_addr); adapter->dmaq1.bus_addr = 0; adapter->dmaq1.head = 0; adapter->dmaq1.tail = 0; adapter->dmaq1.buffer_size = 0; adapter->dmaq1.buffer = 0; } if (adapter->dmaq2.buffer != 0) { pci_free_consistent(adapter->pdev, SIZE_OF_BUF_DMA2 + 0x80, adapter->dmaq2.buffer, adapter->dmaq2.bus_addr); adapter->dmaq2.bus_addr = 0; adapter->dmaq2.head = 0; adapter->dmaq2.tail = 0; adapter->dmaq2.buffer_size = 0; adapter->dmaq2.buffer = 0; }}static void free_adapter_object(struct adapter *adapter){ dprintk("%s:\n", __FUNCTION__); close_stream(adapter, 0); if (adapter->irq != 0) free_irq(adapter->irq, adapter); free_dma_queue(adapter); if (adapter->io_mem != 0) iounmap((void *) adapter->io_mem); if (adapter != 0) kfree(adapter);}static struct pci_driver skystar2_pci_driver;static int claim_adapter(struct adapter *adapter){ struct pci_dev *pdev = adapter->pdev; u16 var; if (!request_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1), skystar2_pci_driver.name)) return -EBUSY;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -