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 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 26 * 02110-1301, USA 27 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 28 */ 29 30 #include <linux/module.h> 31 #include <linux/init.h> 32 #include <linux/delay.h> 33 #include <linux/slab.h> 34 #include <linux/poll.h> 35 #include <linux/io.h> 36 #include <asm/div64.h> 37 #include <linux/pci.h> 38 #include <linux/timer.h> 39 #include <linux/byteorder/generic.h> 40 #include <linux/firmware.h> 41 #include <linux/vmalloc.h> 42 43 #include "ngene.h" 44 45 46 /****************************************************************************/ 47 /* COMMAND API interface ****************************************************/ 48 /****************************************************************************/ 49 50 static ssize_t ts_write(struct file *file, const char *buf, 51 size_t count, loff_t *ppos) 52 { 53 struct dvb_device *dvbdev = file->private_data; 54 struct ngene_channel *chan = dvbdev->priv; 55 struct ngene *dev = chan->dev; 56 57 if (wait_event_interruptible(dev->tsout_rbuf.queue, 58 dvb_ringbuffer_free 59 (&dev->tsout_rbuf) >= count) < 0) 60 return 0; 61 62 dvb_ringbuffer_write(&dev->tsout_rbuf, buf, count); 63 64 return count; 65 } 66 67 static ssize_t ts_read(struct file *file, char *buf, 68 size_t count, loff_t *ppos) 69 { 70 struct dvb_device *dvbdev = file->private_data; 71 struct ngene_channel *chan = dvbdev->priv; 72 struct ngene *dev = chan->dev; 73 int left, avail; 74 75 left = count; 76 while (left) { 77 if (wait_event_interruptible( 78 dev->tsin_rbuf.queue, 79 dvb_ringbuffer_avail(&dev->tsin_rbuf) > 0) < 0) 80 return -EAGAIN; 81 avail = dvb_ringbuffer_avail(&dev->tsin_rbuf); 82 if (avail > left) 83 avail = left; 84 dvb_ringbuffer_read_user(&dev->tsin_rbuf, buf, avail); 85 left -= avail; 86 buf += avail; 87 } 88 return count; 89 } 90 91 static const struct file_operations ci_fops = { 92 .owner = THIS_MODULE, 93 .read = ts_read, 94 .write = ts_write, 95 .open = dvb_generic_open, 96 .release = dvb_generic_release, 97 }; 98 99 struct dvb_device ngene_dvbdev_ci = { 100 .priv = 0, 101 .readers = -1, 102 .writers = -1, 103 .users = -1, 104 .fops = &ci_fops, 105 }; 106 107 108 /****************************************************************************/ 109 /* DVB functions and API interface ******************************************/ 110 /****************************************************************************/ 111 112 static void swap_buffer(u32 *p, u32 len) 113 { 114 while (len) { 115 *p = swab32(*p); 116 p++; 117 len -= 4; 118 } 119 } 120 121 /* start of filler packet */ 122 static u8 fill_ts[] = { 0x47, 0x1f, 0xff, 0x10, TS_FILLER }; 123 124 /* #define DEBUG_CI_XFER */ 125 #ifdef DEBUG_CI_XFER 126 static u32 ok; 127 static u32 overflow; 128 static u32 stripped; 129 #endif 130 131 void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) 132 { 133 struct ngene_channel *chan = priv; 134 struct ngene *dev = chan->dev; 135 136 137 if (flags & DF_SWAP32) 138 swap_buffer(buf, len); 139 140 if (dev->ci.en && chan->number == 2) { 141 while (len >= 188) { 142 if (memcmp(buf, fill_ts, sizeof fill_ts) != 0) { 143 if (dvb_ringbuffer_free(&dev->tsin_rbuf) >= 188) { 144 dvb_ringbuffer_write(&dev->tsin_rbuf, buf, 188); 145 wake_up(&dev->tsin_rbuf.queue); 146 #ifdef DEBUG_CI_XFER 147 ok++; 148 #endif 149 } 150 #ifdef DEBUG_CI_XFER 151 else 152 overflow++; 153 #endif 154 } 155 #ifdef DEBUG_CI_XFER 156 else 157 stripped++; 158 159 if (ok % 100 == 0 && overflow) 160 printk(KERN_WARNING "%s: ok %u overflow %u dropped %u\n", __func__, ok, overflow, stripped); 161 #endif 162 buf += 188; 163 len -= 188; 164 } 165 return NULL; 166 } 167 168 if (chan->users > 0) 169 dvb_dmx_swfilter(&chan->demux, buf, len); 170 171 return NULL; 172 } 173 174 void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags) 175 { 176 struct ngene_channel *chan = priv; 177 struct ngene *dev = chan->dev; 178 u32 alen; 179 180 alen = dvb_ringbuffer_avail(&dev->tsout_rbuf); 181 alen -= alen % 188; 182 183 if (alen < len) 184 FillTSBuffer(buf + alen, len - alen, flags); 185 else 186 alen = len; 187 dvb_ringbuffer_read(&dev->tsout_rbuf, buf, alen); 188 if (flags & DF_SWAP32) 189 swap_buffer((u32 *)buf, alen); 190 wake_up_interruptible(&dev->tsout_rbuf.queue); 191 return buf; 192 } 193 194 195 196 int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed) 197 { 198 struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 199 struct ngene_channel *chan = dvbdmx->priv; 200 201 if (chan->users == 0) { 202 if (!chan->dev->cmd_timeout_workaround || !chan->running) 203 set_transfer(chan, 1); 204 } 205 206 return ++chan->users; 207 } 208 209 int ngene_stop_feed(struct dvb_demux_feed *dvbdmxfeed) 210 { 211 struct dvb_demux *dvbdmx = dvbdmxfeed->demux; 212 struct ngene_channel *chan = dvbdmx->priv; 213 214 if (--chan->users) 215 return chan->users; 216 217 if (!chan->dev->cmd_timeout_workaround) 218 set_transfer(chan, 0); 219 220 return 0; 221 } 222 223 int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id, 224 int (*start_feed)(struct dvb_demux_feed *), 225 int (*stop_feed)(struct dvb_demux_feed *), 226 void *priv) 227 { 228 dvbdemux->priv = priv; 229 230 dvbdemux->filternum = 256; 231 dvbdemux->feednum = 256; 232 dvbdemux->start_feed = start_feed; 233 dvbdemux->stop_feed = stop_feed; 234 dvbdemux->write_to_decoder = NULL; 235 dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | 236 DMX_SECTION_FILTERING | 237 DMX_MEMORY_BASED_FILTERING); 238 return dvb_dmx_init(dvbdemux); 239 } 240 241 int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev, 242 struct dvb_demux *dvbdemux, 243 struct dmx_frontend *hw_frontend, 244 struct dmx_frontend *mem_frontend, 245 struct dvb_adapter *dvb_adapter) 246 { 247 int ret; 248 249 dmxdev->filternum = 256; 250 dmxdev->demux = &dvbdemux->dmx; 251 dmxdev->capabilities = 0; 252 ret = dvb_dmxdev_init(dmxdev, dvb_adapter); 253 if (ret < 0) 254 return ret; 255 256 hw_frontend->source = DMX_FRONTEND_0; 257 dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend); 258 mem_frontend->source = DMX_MEMORY_FE; 259 dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend); 260 return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend); 261 } 262