1 /* 2 * ngene-dvb.c: nGene PCIe bridge driver - DVB functions 3 * 4 * Copyright (C) 2005-2007 Micronas 5 * 6 * Copyright (C) 2008-2009 Ralph Metzler <rjkm@metzlerbros.de> 7 * Modifications for new nGene firmware, 8 * support for EEPROM-copying, 9 * support for new dual DVB-S2 card prototype 10 * 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * version 2 only, as published by the Free Software Foundation. 15 * 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * To obtain the license, point your browser to 23 * http://www.gnu.org/copyleft/gpl.html 24 */ 25 26 #include <linux/module.h> 27 #include <linux/init.h> 28 #include <linux/delay.h> 29 #include <linux/slab.h> 30 #include <linux/poll.h> 31 #include <linux/io.h> 32 #include <asm/div64.h> 33 #include <linux/pci.h> 34 #include <linux/timer.h> 35 #include <linux/byteorder/generic.h> 36 #include <linux/firmware.h> 37 #include <linux/vmalloc.h> 38 39 #include "ngene.h" 40 41 42 /****************************************************************************/ 43 /* COMMAND API interface ****************************************************/ 44 /****************************************************************************/ 45 46 static ssize_t ts_write(struct file *file, const char __user *buf, 47 size_t count, loff_t *ppos) 48 { 49 struct dvb_device *dvbdev = file->private_data; 50 struct ngene_channel *chan = dvbdev->priv; 51 struct ngene *dev = chan->dev; 52 53 if (wait_event_interruptible(dev->tsout_rbuf.queue, 54 dvb_ringbuffer_free 55 (&dev->tsout_rbuf) >= count) < 0) 56 return 0; 57 58 dvb_ringbuffer_write_user(&dev->tsout_rbuf, buf, count); 59 60 return count; 61 } 62 63 static ssize_t ts_read(struct file *file, char __user *buf, 64 size_t count, loff_t *ppos) 65 { 66 struct dvb_device *dvbdev = file->private_data; 67 struct ngene_channel *chan = dvbdev->priv; 68 struct ngene *dev = chan->dev; 69 int left, avail; 70 71 left = count; 72 while (left) { 73 if (wait_event_interruptible( 74 dev->tsin_rbuf.queue, 75 dvb_ringbuffer_avail(&dev->tsin_rbuf) > 0) < 0) 76 return -EAGAIN; 77 avail = dvb_ringbuffer_avail(&dev->tsin_rbuf); 78 if (avail > left) 79 avail = left; 80 dvb_ringbuffer_read_user(&dev->tsin_rbuf, buf, avail); 81 left -= avail; 82 buf += avail; 83 } 84 return count; 85 } 86 87 static const struct file_operations ci_fops = { 88 .owner = THIS_MODULE, 89 .read = ts_read, 90 .write = ts_write, 91 .open = dvb_generic_open, 92 .release = dvb_generic_release, 93 }; 94 95 struct dvb_device ngene_dvbdev_ci = { 96 .readers = -1, 97 .writers = -1, 98 .users = -1, 99 .fops = &ci_fops, 100 }; 101 102 103 /****************************************************************************/ 104 /* DVB functions and API interface ******************************************/ 105 /****************************************************************************/ 106 107 static void swap_buffer(u32 *p, u32 len) 108 { 109 while (len) { 110 *p = swab32(*p); 111 p++; 112 len -= 4; 113 } 114 } 115 116 /* start of filler packet */ 117 static u8 fill_ts[] = { 0x47, 0x1f, 0xff, 0x10, TS_FILLER }; 118 119 /* #define DEBUG_CI_XFER */ 120 #ifdef DEBUG_CI_XFER 121 static u32 ok; 122 static u32 overflow; 123 static u32 stripped; 124 #endif 125 126 void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) 127 { 128 struct ngene_channel *chan = priv; 129 struct ngene *dev = chan->dev; 130 131 132 if (flags & DF_SWAP32) 133 swap_buffer(buf, len); 134 135 if (dev->ci.en && chan->number == 2) { 136 while (len >= 188) { 137 if (memcmp(buf, fill_ts, sizeof fill_ts) != 0) { 138 if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) { 139 dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188); 140 wake_up(&dev->tsin_rbuf.queue); 141 #ifdef DEBUG_CI_XFER 142 ok++; 143 #endif 144 } 145 #ifdef DEBUG_CI_XFER 146 else 147 overflow++; 148 #endif 149 } 150 #ifdef DEBUG_CI_XFER 151 else 152 stripped++; 153 154 if (ok % 100 == 0 && overflow) 155 printk(KERN_WARNING "%s: ok %u overflow %u dropped %u\n", __func__, ok, overflow, stripped); 156 #endif 157 buf += 188; 158 len -= 188; 159 } 160 return NULL; 161 } 162 163 if (chan->users > 0) 164 dvb_dmx_swfilter(&chan->demux, buf, len); 165 166 return NULL; 167 } 168 169 void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) 170 { 171 struct ngene_channel *chan = priv; 172 struct ngene *dev = chan->dev; 173 u32 alen; 174 175 alen = dvb_ringbuffer_avail(&dev->tsout_rbuf); 176 alen -= alen % 188; 177 178 if (alen < len) 179 FillTSBuffer(buf + alen, len - alen, flags); 180 else 181 alen = len; 182 dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen); 183 if (flags & DF_SWAP32) 184 swap_buffer((u32 *)buf, alen); 185 wake_up_interruptible(&dev->tsout_rbuf.queue); 186 return buf; 187 } 188 189 190 191 int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) 192 { 193 struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 194 struct ngene_channel *chan = dvbdmx->priv; 195 196 if (chan->users == 0) { 197 if (!chan->dev->cmd_timeout_workaround || !chan->running) 198 set_transfer(chan, 1); 199 } 200 201 return ++chan->users; 202 } 203 204 int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 205 { 206 struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 207 struct ngene_channel *chan = dvbdmx->priv; 208 209 if (--chan->users) 210 return chan->users; 211 212 if (!chan->dev->cmd_timeout_workaround) 213 set_transfer(chan, 0); 214 215 return 0; 216 } 217 218 int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, 219 int (*start_feed)(struct dvb_demux_feed *), 220 int (*stop_feed)(struct dvb_demux_feed *), 221 void *priv) 222 { 223 dvbdemux->priv = priv; 224 225 dvbdemux->filternum = 256; 226 dvbdemux->feednum = 256; 227 dvbdemux->start_feed = start_feed; 228 dvbdemux->stop_feed = stop_feed; 229 dvbdemux->write_to_decoder = NULL; 230 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | 231 DMX_SECTION_FILTERING | 232 DMX_MEMORY_BASED_FILTERING); 233 return dvb_dmx_init(dvbdemux); 234 } 235 236 int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, 237 struct dvb_demux *dvbdemux, 238 struct dmx_frontend *hw_frontend, 239 struct dmx_frontend *mem_frontend, 240 struct dvb_adapter *dvb_adapter) 241 { 242 int ret; 243 244 dmxdev->filternum = 256; 245 dmxdev->demux = &dvbdemux->dmx; 246 dmxdev->capabilities = 0; 247 ret = dvb_dmxdev_init(dmxdev, dvb_adapter); 248 if (ret < 0) 249 return ret; 250 251 hw_frontend->source = DMX_FRONTEND_0; 252 dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend); 253 mem_frontend->source = DMX_MEMORY_FE; 254 dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend); 255 return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); 256 } 257