From: Michael Hunold <hunold@linuxtv.org>

- [DVB] dvb-core: follow Linux coding style, kill dvb_ksyms.c and move the
  EXPORT_SYMBOLs to the files where the functions are, thanks to Adrian Bunk
  <bunk@stusta.de>

- [DVB] dvb-core: #if 0'ing unused code, make needlessly global code static,
  whitespace and newline cleanups, thanks to Adrian Bunk <bunk@stusta.de>

- [DVB] dvb_ca_en50221.c: support for KNC1/Cinergy CI modules, fix
  segfaults, enhanced poll_slot_status to support non-IRQ interfaces, Fix
  module usage count problem

- [DVB] dvb-frontend.c: core changes to support the refactorized frontend
  drivers

Signed-off-by: Michael Hunold <hunold@linuxtv.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 /dev/null                                           |   52 -
 25-akpm/drivers/media/dvb/dvb-core/dmxdev.c         |   13 
 25-akpm/drivers/media/dvb/dvb-core/dvb_ca_en50221.c |  388 ++++++++++----
 25-akpm/drivers/media/dvb/dvb-core/dvb_ca_en50221.h |    5 
 25-akpm/drivers/media/dvb/dvb-core/dvb_demux.c      |   10 
 25-akpm/drivers/media/dvb/dvb-core/dvb_filter.c     |   14 
 25-akpm/drivers/media/dvb/dvb-core/dvb_frontend.c   |  526 ++++++--------------
 25-akpm/drivers/media/dvb/dvb-core/dvb_frontend.h   |  129 +---
 25-akpm/drivers/media/dvb/dvb-core/dvb_net.c        |    8 
 25-akpm/drivers/media/dvb/dvb-core/dvbdev.c         |    7 
 25-akpm/drivers/media/dvb/dvb-core/dvbdev.h         |    1 
 25-akpm/include/linux/dvb/frontend.h                |    2 
 12 files changed, 519 insertions(+), 636 deletions(-)

diff -puN drivers/media/dvb/dvb-core/dmxdev.c~dvb-core-changes drivers/media/dvb/dvb-core/dmxdev.c
--- 25/drivers/media/dvb/dvb-core/dmxdev.c~dvb-core-changes	Thu Nov 18 15:18:06 2004
+++ 25-akpm/drivers/media/dvb/dvb-core/dmxdev.c	Thu Nov 18 15:18:06 2004
@@ -42,18 +42,12 @@ MODULE_PARM_DESC(debug, "Turn on/off deb
 
 #define dprintk	if (debug) printk
 
-inline struct dmxdev_filter *
+static inline struct dmxdev_filter *
 dvb_dmxdev_file_to_filter(struct file *file)
 {
 	return (struct dmxdev_filter *) file->private_data;
 }
 
-inline struct dmxdev_dvr *
-dvb_dmxdev_file_to_dvr(struct dmxdev *dmxdev, struct file *file)
-{
-	return (struct dmxdev_dvr *) file->private_data;
-}
-
 static inline void dvb_dmxdev_buffer_init(struct dmxdev_buffer *buffer) 
 {
 	buffer->data=NULL;
@@ -846,7 +840,7 @@ static ssize_t dvb_dmxdev_read_sec(struc
 }
 
 
-ssize_t 
+static ssize_t
 dvb_demux_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
 	struct dmxdev_filter *dmxdevfilter=dvb_dmxdev_file_to_filter(file);
@@ -1122,6 +1116,7 @@ dvb_dmxdev_init(struct dmxdev *dmxdev, s
 
 	return 0;
 }
+EXPORT_SYMBOL(dvb_dmxdev_init);
 
 void 
 dvb_dmxdev_release(struct dmxdev *dmxdev)
@@ -1138,5 +1133,5 @@ dvb_dmxdev_release(struct dmxdev *dmxdev
 	}
 	dmxdev->demux->close(dmxdev->demux);
 }
-
+EXPORT_SYMBOL(dvb_dmxdev_release);
 
diff -puN drivers/media/dvb/dvb-core/dvb_ca_en50221.c~dvb-core-changes drivers/media/dvb/dvb-core/dvb_ca_en50221.c
--- 25/drivers/media/dvb/dvb-core/dvb_ca_en50221.c~dvb-core-changes	Thu Nov 18 15:18:06 2004
+++ 25-akpm/drivers/media/dvb/dvb-core/dvb_ca_en50221.c	Thu Nov 18 15:18:06 2004
@@ -181,10 +181,12 @@ static u8* findstr(u8* haystack, int hle
 {
         int i;
 
-        if (hlen < nlen) return NULL;
+	if (hlen < nlen)
+		return NULL;
 
         for(i=0; i<= hlen - nlen; i++) {
-                  if (!strncmp(haystack+i, needle, nlen)) return haystack+i;
+		if (!strncmp(haystack + i, needle, nlen))
+			return haystack + i;
         }
 
         return NULL;
@@ -211,7 +213,7 @@ static int dvb_ca_en50221_check_camstatu
         }
 
         /* poll mode */
-        slot_status = ca->pub->poll_slot_status(ca->pub, slot);
+	slot_status = ca->pub->poll_slot_status(ca->pub, slot, ca->open);
 
         cam_present_now = (slot_status & DVB_CA_EN50221_POLL_CAM_PRESENT) ? 1: 0;
         cam_changed = (slot_status & DVB_CA_EN50221_POLL_CAM_CHANGED) ? 1: 0;
@@ -250,7 +252,8 @@ static int dvb_ca_en50221_check_camstatu
  *
  * @return 0 on success, nonzero on error.
  */
-static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private* ca, int slot, u8 waitfor, int timeout_hz)
+static int dvb_ca_en50221_wait_if_status(struct dvb_ca_private *ca, int slot,
+					 u8 waitfor, int timeout_hz)
 {
         unsigned long timeout;
         unsigned long start;
@@ -263,7 +266,8 @@ static int dvb_ca_en50221_wait_if_status
         while(1) {
                 /* read the status and check for error */
                 int res = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS);
-                if (res < 0) return -EIO;
+		if (res < 0)
+			return -EIO;
 
                 /* if we got the flags, it was successful! */
                 if (res & waitfor) {
@@ -311,24 +315,33 @@ static int dvb_ca_en50221_link_init(stru
         ca->slot_info[slot].link_buf_size = 2;
 
         /* read the buffer size from the CAM */
-        if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0) return ret;
-        if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ/10)) != 0) return ret;
-        if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2) return -EIO;
-        if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) return ret;
+	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0)
+		return ret;
+	if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ / 10)) != 0)
+		return ret;
+	if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2)
+		return -EIO;
+	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0)
+		return ret;
 
         /* store it, and choose the minimum of our buffer and the CAM's buffer size */
         buf_size = (buf[0] << 8) | buf[1];
-        if (buf_size > HOST_LINK_BUF_SIZE) buf_size = HOST_LINK_BUF_SIZE;
+	if (buf_size > HOST_LINK_BUF_SIZE)
+		buf_size = HOST_LINK_BUF_SIZE;
         ca->slot_info[slot].link_buf_size = buf_size;
         buf[0] = buf_size >> 8;
         buf[1] = buf_size & 0xff;
         dprintk("Chosen link buffer size of %i\n", buf_size);
 
         /* write the buffer size to the CAM */
-        if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SW)) != 0) return ret;
-        if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ/10)) != 0) return ret;
-        if ((ret = dvb_ca_en50221_write_data(ca, slot, buf, 2)) != 2) return -EIO;
-        if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) return ret;
+	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SW)) != 0)
+		return ret;
+	if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10)) != 0)
+		return ret;
+	if ((ret = dvb_ca_en50221_write_data(ca, slot, buf, 2)) != 2)
+		return -EIO;
+	if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0)
+		return ret;
 
         /* success */
         return 0;
@@ -355,7 +368,8 @@ static int dvb_ca_en50221_read_tuple(str
         int _address = *address;
 
         /* grab the next tuple length and type */
-        if ((_tupleType = ca->pub->read_attribute_mem(ca->pub, slot, _address)) < 0) return _tupleType;
+	if ((_tupleType = ca->pub->read_attribute_mem(ca->pub, slot, _address)) < 0)
+		return _tupleType;
         if (_tupleType == 0xff) {
                 dprintk("END OF CHAIN TUPLE type:0x%x\n", _tupleType);
                 *address += 2;
@@ -363,7 +377,8 @@ static int dvb_ca_en50221_read_tuple(str
                 *tupleLength = 0;
                 return 0;
         }
-        if ((_tupleLength = ca->pub->read_attribute_mem(ca->pub, slot, _address+2)) < 0) return _tupleLength;
+	if ((_tupleLength = ca->pub->read_attribute_mem(ca->pub, slot, _address + 2)) < 0)
+		return _tupleLength;
         _address += 4;
 
         dprintk("TUPLE type:0x%x length:%i\n", _tupleType, _tupleLength);
@@ -371,7 +386,9 @@ static int dvb_ca_en50221_read_tuple(str
         /* read in the whole tuple */
         for(i=0; i< _tupleLength; i++) {
                 tuple[i] = ca->pub->read_attribute_mem(ca->pub, slot, _address + (i*2));
-                dprintk("  0x%02x: 0x%02x %c\n", i, tuple[i] & 0xff, ((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.');
+		dprintk("  0x%02x: 0x%02x %c\n",
+			i, tuple[i] & 0xff,
+			((tuple[i] > 31) && (tuple[i] < 127)) ? tuple[i] : '.');
         }
         _address += (_tupleLength*2);
 
@@ -409,40 +426,58 @@ static int dvb_ca_en50221_parse_attribut
 
 
         // CISTPL_DEVICE_0A
-        if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status;
-        if (tupleType != 0x1D) return -EINVAL;
+	if ((status =
+	     dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0)
+		return status;
+	if (tupleType != 0x1D)
+		return -EINVAL;
 
 
 
         // CISTPL_DEVICE_0C
-        if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status;
-        if (tupleType != 0x1C) return -EINVAL;
+	if ((status =
+	     dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0)
+		return status;
+	if (tupleType != 0x1C)
+		return -EINVAL;
 
 
 
         // CISTPL_VERS_1
-        if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status;
-        if (tupleType != 0x15) return -EINVAL;
+	if ((status =
+	     dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0)
+		return status;
+	if (tupleType != 0x15)
+		return -EINVAL;
 
 
 
         // CISTPL_MANFID
-        if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status;
-        if (tupleType != 0x20) return -EINVAL;
-        if (tupleLength != 4) return -EINVAL;
+	if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType,
+						&tupleLength, tuple)) < 0)
+		return status;
+	if (tupleType != 0x20)
+		return -EINVAL;
+	if (tupleLength != 4)
+		return -EINVAL;
         manfid = (tuple[1] << 8) | tuple[0];
         devid = (tuple[3] << 8) | tuple[2];
 
 
 
         // CISTPL_CONFIG
-        if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status;
-        if (tupleType != 0x1A) return -EINVAL;
-        if (tupleLength < 3) return -EINVAL;
+	if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType,
+						&tupleLength, tuple)) < 0)
+		return status;
+	if (tupleType != 0x1A)
+		return -EINVAL;
+	if (tupleLength < 3)
+		return -EINVAL;
 
         /* extract the configbase */
         rasz = tuple[0] & 3;
-        if (tupleLength < (3 + rasz + 14)) return -EINVAL;
+	if (tupleLength < (3 + rasz + 14))
+		return -EINVAL;
         ca->slot_info[slot].config_base = 0;
         for(i=0; i< rasz+1; i++) {
                 ca->slot_info[slot].config_base |= (tuple[2+i] << (8*i));
@@ -450,8 +485,10 @@ static int dvb_ca_en50221_parse_attribut
 
         /* check it contains the correct DVB string */
         dvb_str = findstr(tuple, tupleLength, "DVB_CI_V", 8);
-        if (dvb_str == NULL) return -EINVAL;
-        if (tupleLength < ((dvb_str - (char*) tuple) + 12)) return -EINVAL;
+	if (dvb_str == NULL)
+		return -EINVAL;
+	if (tupleLength < ((dvb_str - (char *) tuple) + 12))
+		return -EINVAL;
 
         /* is it a version we support? */
         if (strncmp(dvb_str + 8, "1.00", 4)) {
@@ -462,20 +499,25 @@ static int dvb_ca_en50221_parse_attribut
 
         /* process the CFTABLE_ENTRY tuples, and any after those */
         while((!end_chain) && (address < 0x1000)) {
-                if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType, &tupleLength, tuple)) < 0) return status;
+		if ((status = dvb_ca_en50221_read_tuple(ca, slot, &address, &tupleType,
+						        &tupleLength, tuple)) < 0)
+			return status;
                 switch(tupleType) {
                 case 0x1B: // CISTPL_CFTABLE_ENTRY
-                        if (tupleLength < (2+11+17)) break;
+			if (tupleLength < (2 + 11 + 17))
+				break;
 
                         /* if we've already parsed one, just use it */
-                        if (got_cftableentry) break;
+			if (got_cftableentry)
+				break;
 
                         /* get the config option */
                         ca->slot_info[slot].config_option = tuple[0] & 0x3f;
 
                         /* OK, check it contains the correct strings */
                         if ((findstr(tuple, tupleLength, "DVB_HOST", 8) == NULL) ||
-                            (findstr(tuple, tupleLength, "DVB_CI_MODULE", 13) == NULL)) break;
+			    (findstr(tuple, tupleLength, "DVB_CI_MODULE", 13) == NULL))
+				break;
 
                         got_cftableentry = 1;
                         break;
@@ -488,17 +530,17 @@ static int dvb_ca_en50221_parse_attribut
                         break;
 
                 default: /* Unknown tuple type - just skip this tuple and move to the next one */
-                        dprintk("dvb_ca: Skipping unknown tuple type:0x%x length:0x%x\n", tupleType, tupleLength);
+			dprintk("dvb_ca: Skipping unknown tuple type:0x%x length:0x%x\n", tupleType,
+				tupleLength);
                         break;
                 }
         }
 
-        if ((address > 0x1000) || (!got_cftableentry)) return -EINVAL;
+	if ((address > 0x1000) || (!got_cftableentry))
+		return -EINVAL;
 
         dprintk("Valid DVB CAM detected MANID:%x DEVID:%x CONFIGBASE:0x%x CONFIGOPTION:0x%x\n",
-                manfid, devid,
-                ca->slot_info[slot].config_base,
-                ca->slot_info[slot].config_option);
+		manfid, devid, ca->slot_info[slot].config_base, ca->slot_info[slot].config_option);
 
         // success!
         return 0;
@@ -518,7 +560,9 @@ static int dvb_ca_en50221_set_configopti
         dprintk ("%s\n", __FUNCTION__);
 
         /* set the config option */
-        ca->pub->write_attribute_mem(ca->pub, slot, ca->slot_info[slot].config_base, ca->slot_info[slot].config_option);
+	ca->pub->write_attribute_mem(ca->pub, slot,
+				     ca->slot_info[slot].config_base,
+				     ca->slot_info[slot].config_option);
 
         /* check it */
         configoption = ca->pub->read_attribute_mem(ca->pub, slot, ca->slot_info[slot].config_base);
@@ -558,6 +602,11 @@ static int dvb_ca_en50221_read_data(stru
 		int buf_free;
 
 		down_read(&ca->slot_info[slot].sem);
+		if (ca->slot_info[slot].rx_buffer.data == NULL) {
+			up_read(&ca->slot_info[slot].sem);
+			status = -EIO;
+			goto exit;
+		}
 		buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer);
 		up_read(&ca->slot_info[slot].sem);
 
@@ -568,7 +617,8 @@ static int dvb_ca_en50221_read_data(stru
         }
 
         /* check if there is data available */
-        if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit;
+	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
+		goto exit;
         if (!(status & STATUSREG_DA)) {
                 /* no data */
                 status = 0;
@@ -576,28 +626,33 @@ static int dvb_ca_en50221_read_data(stru
         }
 
         /* read the amount of data */
-        if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0) goto exit;
+	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0)
+		goto exit;
         bytes_read = status << 8;
-        if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0) goto exit;
+	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0)
+		goto exit;
         bytes_read |= status;
 
         /* check it will fit */
         if (ebuf == NULL) {
                 if (bytes_read > ca->slot_info[slot].link_buf_size) {
-                        printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size!\n", ca->dvbdev->adapter->num);
+			printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n",
+			       ca->dvbdev->adapter->num, bytes_read, ca->slot_info[slot].link_buf_size);
                         ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
                         status = -EIO;
                         goto exit;
                 }
                 if (bytes_read < 2) {
-                        printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n", ca->dvbdev->adapter->num);
+			printk("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n",
+			       ca->dvbdev->adapter->num);
                         ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
                         status = -EIO;
                         goto exit;
                 }
         } else {
                 if (bytes_read > ecount) {
-                        printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n", ca->dvbdev->adapter->num);
+			printk("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n",
+			       ca->dvbdev->adapter->num);
                         status = -EIO;
                         goto exit;
                 }
@@ -606,14 +661,16 @@ static int dvb_ca_en50221_read_data(stru
         /* fill the buffer */
         for(i=0; i < bytes_read; i++) {
                 /* read byte and check */
-                if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0) goto exit;
+		if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0)
+			goto exit;
 
                 /* OK, store it in the buffer */
                 buf[i] = status;
         }
 
         /* check for read error (RE should now be 0) */
-        if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit;
+	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
+		goto exit;
         if (status & STATUSREG_RE) {
 		ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
                 status = -EIO;
@@ -623,13 +680,19 @@ static int dvb_ca_en50221_read_data(stru
         /* OK, add it to the receive buffer, or copy into external buffer if supplied */
         if (ebuf == NULL) {
 		down_read(&ca->slot_info[slot].sem);
+		if (ca->slot_info[slot].rx_buffer.data == NULL) {
+			up_read(&ca->slot_info[slot].sem);
+			status = -EIO;
+			goto exit;
+		}
                 dvb_ringbuffer_pkt_write(&ca->slot_info[slot].rx_buffer, buf, bytes_read);
 		up_read(&ca->slot_info[slot].sem);
         } else {
                 memcpy(ebuf, buf, bytes_read);
         }
 
-	dprintk("Received CA packet for slot %i connection id 0x%x last_frag:%i size:0x%x\n", slot, buf[0], (buf[1] & 0x80) == 0, bytes_read);
+	dprintk("Received CA packet for slot %i connection id 0x%x last_frag:%i size:0x%x\n", slot,
+		buf[0], (buf[1] & 0x80) == 0, bytes_read);
 
         /* wake up readers when a last_fragment is received */
         if ((buf[1] & 0x80) == 0x00) {
@@ -664,20 +727,25 @@ static int dvb_ca_en50221_write_data(str
 
 
         // sanity check
-        if (bytes_write > ca->slot_info[slot].link_buf_size) return -EINVAL;
+	if (bytes_write > ca->slot_info[slot].link_buf_size)
+		return -EINVAL;
 
         /* check if interface is actually waiting for us to read from it, or if a read is in progress */
-        if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exitnowrite;
+	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
+		goto exitnowrite;
         if (status & (STATUSREG_DA|STATUSREG_RE)) {
                 status = -EAGAIN;
                 goto exitnowrite;
         }
 
         /* OK, set HC bit */
-        if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_HC)) != 0) goto exit;
+	if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND,
+						 IRQEN | CMDREG_HC)) != 0)
+		goto exit;
 
         /* check if interface is still free */
-        if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit;
+	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
+		goto exit;
         if (!(status & STATUSREG_FR)) {
                 /* it wasn't free => try again later */
                 status = -EAGAIN;
@@ -685,16 +753,21 @@ static int dvb_ca_en50221_write_data(str
         }
 
         /* send the amount of data */
-        if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0) goto exit;
-        if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW, bytes_write & 0xff)) != 0) goto exit;
+	if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0)
+		goto exit;
+	if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW,
+						 bytes_write & 0xff)) != 0)
+		goto exit;
 
         /* send the buffer */
         for(i=0; i < bytes_write; i++) {
-                if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_DATA, buf[i])) != 0) goto exit;
+		if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_DATA, buf[i])) != 0)
+			goto exit;
         }
 
         /* check for write error (WE should now be 0) */
-        if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit;
+	if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0)
+		goto exit;
         if (status & STATUSREG_WE) {
 		ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
                 status = -EIO;
@@ -702,7 +775,8 @@ static int dvb_ca_en50221_write_data(str
         }
         status = bytes_write;
 
-	dprintk("Wrote CA packet for slot %i, connection id 0x%x last_frag:%i size:0x%x\n", slot, buf[0], (buf[1] & 0x80) == 0, bytes_write);
+	dprintk("Wrote CA packet for slot %i, connection id 0x%x last_frag:%i size:0x%x\n", slot,
+		buf[0], (buf[1] & 0x80) == 0, bytes_write);
 
 exit:
         ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN);
@@ -710,6 +784,7 @@ exit:
 exitnowrite:
         return status;
 }
+EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq);
 
 
 
@@ -730,7 +805,8 @@ static int dvb_ca_en50221_slot_shutdown(
         down_write(&ca->slot_info[slot].sem);
         ca->pub->slot_shutdown(ca->pub, slot);
         ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
-        if (ca->slot_info[slot].rx_buffer.data) vfree(ca->slot_info[slot].rx_buffer.data);
+	if (ca->slot_info[slot].rx_buffer.data)
+		vfree(ca->slot_info[slot].rx_buffer.data);
         ca->slot_info[slot].rx_buffer.data = NULL;
         up_write(&ca->slot_info[slot].sem);
 
@@ -743,6 +819,7 @@ static int dvb_ca_en50221_slot_shutdown(
         /* success */
         return 0;
 }
+EXPORT_SYMBOL(dvb_ca_en50221_camready_irq);
 
 
 /**
@@ -771,6 +848,7 @@ void dvb_ca_en50221_camchange_irq(struct
         atomic_inc(&ca->slot_info[slot].camchange_count);
         dvb_ca_en50221_thread_wakeup(ca);
 }
+EXPORT_SYMBOL(dvb_ca_en50221_frda_irq);
 
 
 /**
@@ -815,7 +893,8 @@ void dvb_ca_en50221_frda_irq(struct dvb_
                 break;
 
         case DVB_CA_SLOTSTATE_RUNNING:
-		if (ca->open) dvb_ca_en50221_read_data(ca, slot, NULL, 0);
+		if (ca->open)
+			dvb_ca_en50221_read_data(ca, slot, NULL, 0);
                 break;
         }
 }
@@ -851,7 +930,8 @@ static int dvb_ca_en50221_thread_should_
                 ca->wakeup = 0;
                 return 1;
         }
-        if (ca->exit) return 1;
+	if (ca->exit)
+		return 1;
    
         return 0;
 }
@@ -901,7 +981,8 @@ static void dvb_ca_en50221_thread_update
                         break;
                 }
 
-                if (delay < curdelay) curdelay = delay;
+		if (delay < curdelay)
+			curdelay = delay;
         }
 
         ca->delay = curdelay;
@@ -918,6 +999,7 @@ static int dvb_ca_en50221_thread(void* d
         char name[15];
         int slot;
         int flags;
+	int status;
         int pktcount;
         void* rxbuf;
 
@@ -938,7 +1020,9 @@ static int dvb_ca_en50221_thread(void* d
         while(!ca->exit) {
                 /* sleep for a bit */
                 if (!ca->wakeup) {
-                        flags = wait_event_interruptible_timeout(ca->thread_queue, dvb_ca_en50221_thread_should_wakeup(ca), ca->delay);
+			flags = wait_event_interruptible_timeout(ca->thread_queue,
+								 dvb_ca_en50221_thread_should_wakeup(ca),
+								 ca->delay);
                         if ((flags == -ERESTARTSYS) || ca->exit) {
                                 /* got signal or quitting */
                                 break;
@@ -952,7 +1036,8 @@ static int dvb_ca_en50221_thread(void* d
                         // check the cam status + deal with CAMCHANGEs
                         while(dvb_ca_en50221_check_camstatus(ca, slot)) {
                                 /* clear down an old CI slot if necessary */
-                                if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) dvb_ca_en50221_slot_shutdown(ca, slot);
+				if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE)
+					dvb_ca_en50221_slot_shutdown(ca, slot);
 
                                 /* if a CAM is NOW present, initialise it */
                                 if (ca->slot_info[slot].camchange_type == DVB_CA_EN50221_CAMCHANGE_INSERTED) {
@@ -979,7 +1064,8 @@ static int dvb_ca_en50221_thread(void* d
 
                         case DVB_CA_SLOTSTATE_WAITREADY:
                                 if (time_after(jiffies, ca->slot_info[slot].timeout)) {
-                                        printk("dvb_ca adaptor %d: PC card did not respond :(\n", ca->dvbdev->adapter->num);
+					printk("dvb_ca adaptor %d: PC card did not respond :(\n",
+					       ca->dvbdev->adapter->num);
                                         ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 				        dvb_ca_en50221_thread_update_delay(ca);
                                         break;
@@ -988,20 +1074,25 @@ static int dvb_ca_en50221_thread(void* d
                                 break;
 
                         case DVB_CA_SLOTSTATE_VALIDATE:
-                                if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) {
-                                        printk("dvb_ca adapter %d: Invalid PC card inserted :(\n", ca->dvbdev->adapter->num);
+				if (dvb_ca_en50221_parse_attributes(ca, slot)
+				    != 0) {
+					printk("dvb_ca adapter %d: Invalid PC card inserted :(\n",
+					       ca->dvbdev->adapter->num);
                                         ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
                                         dvb_ca_en50221_thread_update_delay(ca);
                                         break;
                                 }
                                 if (dvb_ca_en50221_set_configoption(ca, slot) != 0) {
-                                        printk("dvb_ca adapter %d: Unable to initialise CAM :(\n", ca->dvbdev->adapter->num);
+					printk("dvb_ca adapter %d: Unable to initialise CAM :(\n",
+					       ca->dvbdev->adapter->num);
                                         ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 				        dvb_ca_en50221_thread_update_delay(ca);
                                         break;
                                 }
-                                if (ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, CMDREG_RS) != 0) {
-                                        printk("dvb_ca adapter %d: Unable to reset CAM IF\n", ca->dvbdev->adapter->num);
+				if (ca->pub->write_cam_control(ca->pub, slot,
+							       CTRLIF_COMMAND, CMDREG_RS) != 0) {
+					printk("dvb_ca adapter %d: Unable to reset CAM IF\n",
+					       ca->dvbdev->adapter->num);
                                         ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 				        dvb_ca_en50221_thread_update_delay(ca);
                                         break;
@@ -1016,7 +1107,8 @@ static int dvb_ca_en50221_thread(void* d
 
                         case DVB_CA_SLOTSTATE_WAITFR:
                                 if (time_after(jiffies, ca->slot_info[slot].timeout)) {
-                                        printk("dvb_ca adapter %d: DVB CAM did not respond :(\n", ca->dvbdev->adapter->num);
+					printk("dvb_ca adapter %d: DVB CAM did not respond :(\n",
+					       ca->dvbdev->adapter->num);
                                         ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
 				        dvb_ca_en50221_thread_update_delay(ca);
                                         break;
@@ -1044,7 +1136,9 @@ static int dvb_ca_en50221_thread(void* d
 				        dvb_ca_en50221_thread_update_delay(ca);
                                         break;
                                 }
+				down_write(&ca->slot_info[slot].sem);
                                 dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE);
+				up_write(&ca->slot_info[slot].sem);
 
                                 ca->pub->slot_ts_enable(ca->pub, slot);
                                 ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING;
@@ -1053,15 +1147,18 @@ static int dvb_ca_en50221_thread(void* d
                                 break;
 
                         case DVB_CA_SLOTSTATE_RUNNING:
-                                if (!ca->open) break;
+				if (!ca->open)
+					continue;
 
 				// no need to poll if the CAM supports IRQs
-				if (ca->slot_info[slot].da_irq_supported) break;
+				if (ca->slot_info[slot].da_irq_supported)
+					break;
 
 				// poll mode
                                 pktcount = 0;
-                                while(dvb_ca_en50221_read_data(ca, slot, NULL, 0) > 0) {
-                                        if (!ca->open) break;
+				while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) > 0) {
+					if (!ca->open)
+						break;
 
                                         /* if a CAMCHANGE occurred at some point, do not do any more processing of this slot */
                                         if (dvb_ca_en50221_check_camstatus(ca, slot)) {
@@ -1105,7 +1202,8 @@ static int dvb_ca_en50221_thread(void* d
  *
  * @return 0 on success, <0 on error.
  */
-static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg)
+static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
+				      unsigned int cmd, void *parg)
 {
         struct dvb_device* dvbdev=(struct dvb_device*) file->private_data;
         struct dvb_ca_private* ca = (struct dvb_ca_private*) dvbdev->priv;
@@ -1120,15 +1218,16 @@ static int dvb_ca_en50221_io_do_ioctl(st
                         if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE) {
                                 dvb_ca_en50221_slot_shutdown(ca, slot);
                                 if (ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)
-                                        dvb_ca_en50221_camchange_irq(ca->pub, slot, DVB_CA_EN50221_CAMCHANGE_INSERTED);
+					dvb_ca_en50221_camchange_irq(ca->pub,
+								     slot,
+								     DVB_CA_EN50221_CAMCHANGE_INSERTED);
                         }
                 }
                 ca->next_read_slot = 0;
                 dvb_ca_en50221_thread_wakeup(ca);
                 break;
 
-        case CA_GET_CAP:
-        {
+	case CA_GET_CAP: {
                 struct ca_caps *caps = (struct ca_caps*) parg;
 
                 caps->slot_num=ca->slot_count;
@@ -1138,9 +1237,7 @@ static int dvb_ca_en50221_io_do_ioctl(st
                 break;
         }
 
-
-        case CA_GET_SLOT_INFO:
-        {
+	case CA_GET_SLOT_INFO: {
                 struct ca_slot_info *info=(struct ca_slot_info *)parg;
 
                 if ((info->num > ca->slot_count) || (info->num < 0))
@@ -1148,8 +1245,8 @@ static int dvb_ca_en50221_io_do_ioctl(st
 
                 info->type = CA_CI_LINK;
                 info->flags = 0;
-                if ((ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_NONE) &&
-                    (ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_INVALID)) {
+		if ((ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_NONE)
+			&& (ca->slot_info[info->num].slot_state != DVB_CA_SLOTSTATE_INVALID)) {
                         info->flags = CA_CI_MODULE_PRESENT;
                 }
                 if (ca->slot_info[info->num].slot_state == DVB_CA_SLOTSTATE_RUNNING) {
@@ -1177,7 +1274,8 @@ static int dvb_ca_en50221_io_do_ioctl(st
  *
  * @return 0 on success, <0 on error.
  */
-static int dvb_ca_en50221_io_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int dvb_ca_en50221_io_ioctl(struct inode *inode, struct file *file,
+				   unsigned int cmd, unsigned long arg)
 {
         return dvb_usercopy(inode, file, cmd, arg, dvb_ca_en50221_io_do_ioctl);
 }
@@ -1193,7 +1291,8 @@ static int dvb_ca_en50221_io_ioctl(struc
  *
  * @return Number of bytes read, or <0 on error.
  */
-static ssize_t dvb_ca_en50221_io_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+static ssize_t dvb_ca_en50221_io_write(struct file *file,
+				       const char __user * buf, size_t count, loff_t * ppos)
 {
         struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         struct dvb_ca_private *ca=(struct dvb_ca_private*) dvbdev->priv;
@@ -1208,35 +1307,48 @@ static ssize_t dvb_ca_en50221_io_write(s
         dprintk ("%s\n", __FUNCTION__);
 
         /* Incoming packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
-        if (count < 2) return -EINVAL;
+	if (count < 2)
+		return -EINVAL;
 
         /* extract slot & connection id */
-        if (copy_from_user(&slot, buf, 1)) return -EFAULT;
-        if (copy_from_user(&connection_id, buf+1, 1)) return -EFAULT;
+	if (copy_from_user(&slot, buf, 1))
+		return -EFAULT;
+	if (copy_from_user(&connection_id, buf + 1, 1))
+		return -EFAULT;
         buf+=2;
         count-=2;
 
         /* check if the slot is actually running */
-        if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) return -EINVAL;
+	if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING)
+		return -EINVAL;
 
         /* fragment the packets & store in the buffer */
         while(fragpos < count) {
                 fraglen = ca->slot_info[slot].link_buf_size - 2;
-                if ((count - fragpos) < fraglen) fraglen = count - fragpos;
+		if ((count - fragpos) < fraglen)
+			fraglen = count - fragpos;
 
                 fragbuf[0] = connection_id;
                 fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00;
-                if ((status = copy_from_user(fragbuf+2, buf+fragpos, fraglen)) != 0) goto exit;
+		if ((status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen)) != 0)
+			goto exit;
 
 		timeout = jiffies + HZ/2;
 	        written = 0;
                 while(!time_after(jiffies, timeout)) {
+			/* check the CAM hasn't been removed/reset in the meantime */
+			if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) {
+				status = -EIO;
+				goto exit;
+			}
+
                         status = dvb_ca_en50221_write_data(ca, slot, fragbuf, fraglen+2);
 		        if (status == (fraglen+2)) {
 			       written = 1;
 			       break;
 			}
-                        if (status != -EAGAIN) goto exit;
+			if (status != -EAGAIN)
+				goto exit;
 
                         msleep(1);
                 }
@@ -1269,14 +1381,21 @@ static int dvb_ca_en50221_io_read_condit
 
         slot = ca->next_read_slot;
         while((slot_count < ca->slot_count) && (!found)) {
-                if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING) goto nextslot;
+		if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_RUNNING)
+			goto nextslot;
 
                 down_read(&ca->slot_info[slot].sem);
 
+		if (ca->slot_info[slot].rx_buffer.data == NULL) {
+			up_read(&ca->slot_info[slot].sem);
+			return 0;
+		}
+
                 idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, -1, &fraglen);
                 while(idx != -1) {
                         dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0);
-                        if (connection_id == -1) connection_id = hdr[0];
+			if (connection_id == -1)
+				connection_id = hdr[0];
                         if ((hdr[0] == connection_id) && ((hdr[1] & 0x80) == 0)) {
                                 *_slot = slot;
                                 found = 1;
@@ -1286,7 +1405,8 @@ static int dvb_ca_en50221_io_read_condit
                         idx = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen);
                 }
 
-                if (!found) up_read(&ca->slot_info[slot].sem);
+		if (!found)
+			up_read(&ca->slot_info[slot].sem);
 
 nextslot:
                 slot = (slot + 1) % ca->slot_count;
@@ -1308,7 +1428,8 @@ nextslot:
  *
  * @return Number of bytes read, or <0 on error.
  */
-static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
+				      size_t count, loff_t * ppos)
 {
         struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         struct dvb_ca_private *ca=(struct dvb_ca_private*) dvbdev->priv;
@@ -1326,19 +1447,24 @@ static ssize_t dvb_ca_en50221_io_read(st
         dprintk ("%s\n", __FUNCTION__);
 
         /* Outgoing packet has a 2 byte header. hdr[0] = slot_id, hdr[1] = connection_id */
-        if (count < 2) return -EINVAL;
+	if (count < 2)
+		return -EINVAL;
 
         /* wait for some data */
         if ((status = dvb_ca_en50221_io_read_condition(ca, &result, &slot)) == 0) {
 
                 /* if we're in nonblocking mode, exit immediately */
-                if (file->f_flags & O_NONBLOCK) return -EWOULDBLOCK;
+		if (file->f_flags & O_NONBLOCK)
+			return -EWOULDBLOCK;
 
                 /* wait for some data */
-                status = wait_event_interruptible(ca->wait_queue, dvb_ca_en50221_io_read_condition(ca, &result, &slot));
+		status = wait_event_interruptible(ca->wait_queue,
+						  dvb_ca_en50221_io_read_condition
+						  (ca, &result, &slot));
         }
         if ((status < 0) || (result < 0)) {
-                if (result) return result;
+		if (result)
+			return result;
                 return status;
         }
 
@@ -1352,7 +1478,8 @@ static ssize_t dvb_ca_en50221_io_read(st
                 }
 
                 dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 0, hdr, 2, 0);
-                if (connection_id == -1) connection_id = hdr[0];
+		if (connection_id == -1)
+			connection_id = hdr[0];
                 if (hdr[0] == connection_id) {
                         if (pktlen < count) {
                                 if ((pktlen + fraglen - 2) > count) {
@@ -1361,25 +1488,29 @@ static ssize_t dvb_ca_en50221_io_read(st
                                         fraglen -= 2;
                                 }
 
-			        if ((status = dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 2, buf + pktlen, fraglen, 1)) < 0) {
+				if ((status = dvb_ringbuffer_pkt_read(&ca->slot_info[slot].rx_buffer, idx, 2,
+								      buf + pktlen, fraglen, 1)) < 0) {
                                         goto exit;
                                 }
                                 pktlen += fraglen;
                         }
 
-                        if ((hdr[1] & 0x80) == 0) last_fragment = 1;
+			if ((hdr[1] & 0x80) == 0)
+				last_fragment = 1;
                         dispose = 1;
                 }
 
                 idx2 = dvb_ringbuffer_pkt_next(&ca->slot_info[slot].rx_buffer, idx, &fraglen);
-                if (dispose) dvb_ringbuffer_pkt_dispose(&ca->slot_info[slot].rx_buffer, idx);
+		if (dispose)
+			dvb_ringbuffer_pkt_dispose(&ca->slot_info[slot].rx_buffer, idx);
                 idx = idx2;
                 dispose = 0;
         } while (!last_fragment);
 
         hdr[0] = slot;
         hdr[1] = connection_id;
-        if ((status = copy_to_user(buf, hdr, 2)) != 0) goto exit;
+	if ((status = copy_to_user(buf, hdr, 2)) != 0)
+		goto exit;
         status = pktlen;
 
 exit:
@@ -1405,14 +1536,20 @@ static int dvb_ca_en50221_io_open(struct
 
         dprintk ("%s\n", __FUNCTION__);
 
+	if (!try_module_get(ca->pub->owner))
+		return -EIO;
+
         err=dvb_generic_open(inode, file);
         if (err<0)
                 return err;
 
         for(i=0; i< ca->slot_count; i++) {
+
                 if (ca->slot_info[i].slot_state == DVB_CA_SLOTSTATE_RUNNING) {
 		        down_write(&ca->slot_info[i].sem);
+			if (ca->slot_info[i].rx_buffer.data != NULL) {
                         dvb_ringbuffer_flush(&ca->slot_info[i].rx_buffer);
+			}
 		        up_write(&ca->slot_info[i].sem);
                 }
         }
@@ -1437,7 +1574,7 @@ static int dvb_ca_en50221_io_release(str
 {
         struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
         struct dvb_ca_private *ca=(struct dvb_ca_private*) dvbdev->priv;
-        int err;
+	int err = 0;
 
         dprintk ("%s\n", __FUNCTION__);
 
@@ -1446,8 +1583,9 @@ static int dvb_ca_en50221_io_release(str
         dvb_ca_en50221_thread_update_delay(ca);
 
         err=dvb_generic_release(inode, file);
-        if (err<0)
-                return err;
+
+	module_put(ca->pub->owner);
+
         return 0;
 }
 
@@ -1476,7 +1614,8 @@ static unsigned int dvb_ca_en50221_io_po
         }
 
         /* if there is something, return now */
-        if (mask) return mask;
+	if (mask)
+		return mask;
 
         /* wait for something to happen */
         poll_wait(file, &ca->wait_queue, wait);
@@ -1488,6 +1627,8 @@ static unsigned int dvb_ca_en50221_io_po
 
         return mask;
 }
+EXPORT_SYMBOL(dvb_ca_en50221_init);
+
 
 static struct file_operations dvb_ca_fops = {
 	.owner	= THIS_MODULE,
@@ -1521,7 +1662,8 @@ static struct dvb_device dvbdev_ca = {
  *
  * @return 0 on success, nonzero on failure
  */
-int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter, struct dvb_ca_en50221* pubca, int flags, int slot_count)
+int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
+			struct dvb_ca_en50221 *pubca, int flags, int slot_count)
 {
         int ret;
         struct dvb_ca_private* ca = NULL;
@@ -1529,10 +1671,13 @@ int dvb_ca_en50221_init(struct dvb_adapt
 
         dprintk ("%s\n", __FUNCTION__);
 
-        if (slot_count < 1) return -EINVAL;
+	if (slot_count < 1)
+		return -EINVAL;
 
         /* initialise the system data */
-        if ((ca = (struct dvb_ca_private*) kmalloc(sizeof(struct dvb_ca_private), GFP_KERNEL)) == NULL) {
+	if ((ca =
+	     (struct dvb_ca_private *) kmalloc(sizeof(struct dvb_ca_private),
+					       GFP_KERNEL)) == NULL) {
                 ret = -ENOMEM;
                 goto error;
         }
@@ -1556,7 +1701,8 @@ int dvb_ca_en50221_init(struct dvb_adapt
 
         /* register the DVB device */
         ret = dvb_register_device(dvb_adapter, &ca->dvbdev, &dvbdev_ca, ca, DVB_DEVICE_CA);
-        if (ret) goto error;
+	if (ret)
+		goto error;
 
         /* now initialise each slot */
         for(i=0; i< slot_count; i++) {
@@ -1584,13 +1730,16 @@ int dvb_ca_en50221_init(struct dvb_adapt
 
 error:
         if (ca != NULL) {
-                if (ca->dvbdev != NULL) dvb_unregister_device(ca->dvbdev);
-                if (ca->slot_info != NULL) kfree(ca->slot_info);
+		if (ca->dvbdev != NULL)
+			dvb_unregister_device(ca->dvbdev);
+		if (ca->slot_info != NULL)
+			kfree(ca->slot_info);
                 kfree(ca);
         }
         pubca->private = NULL;
         return ret;
 }
+EXPORT_SYMBOL(dvb_ca_en50221_release);
 
 
 
@@ -1610,7 +1759,8 @@ void dvb_ca_en50221_release(struct dvb_c
         /* shutdown the thread if there was one */
         if (ca->thread_pid) {
                 if (kill_proc(ca->thread_pid, 0, 1) == -ESRCH) {
-                        printk("dvb_ca_release adapter %d: thread PID %d already died\n", ca->dvbdev->adapter->num, ca->thread_pid);
+			printk("dvb_ca_release adapter %d: thread PID %d already died\n",
+			       ca->dvbdev->adapter->num, ca->thread_pid);
                 } else {
                         ca->exit = 1;
                         mb();
diff -puN drivers/media/dvb/dvb-core/dvb_ca_en50221.h~dvb-core-changes drivers/media/dvb/dvb-core/dvb_ca_en50221.h
--- 25/drivers/media/dvb/dvb-core/dvb_ca_en50221.h~dvb-core-changes	Thu Nov 18 15:18:06 2004
+++ 25-akpm/drivers/media/dvb/dvb-core/dvb_ca_en50221.h	Thu Nov 18 15:18:06 2004
@@ -42,6 +42,9 @@
 /* Structure describing a CA interface */
 struct dvb_ca_en50221 {
 
+	/* the module owning this structure */
+	struct module* owner;
+
 	/* NOTE: the read_*, write_* and poll_slot_status functions must use locks as
 	 * they may be called from several threads at once */
 
@@ -62,7 +65,7 @@ struct dvb_ca_en50221 {
 	* Poll slot status.
 	* Only necessary if DVB_CA_FLAG_EN50221_IRQ_CAMCHANGE is not set
 	*/
-	int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot);
+	int (*poll_slot_status)(struct dvb_ca_en50221* ca, int slot, int open);
 
 	/* private data, used by caller */
 	void* data;
diff -puN drivers/media/dvb/dvb-core/dvb_demux.c~dvb-core-changes drivers/media/dvb/dvb-core/dvb_demux.c
--- 25/drivers/media/dvb/dvb-core/dvb_demux.c~dvb-core-changes	Thu Nov 18 15:18:06 2004
+++ 25-akpm/drivers/media/dvb/dvb-core/dvb_demux.c	Thu Nov 18 15:18:06 2004
@@ -424,7 +424,7 @@ void dvb_dmx_swfilter_packet(struct dvb_
 			feed->cb.ts(buf, 188, NULL, 0, &feed->feed.ts, DMX_OK);
 	}
 }
-
+EXPORT_SYMBOL(dvb_dmx_swfilter_packet);
 
 void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf, size_t count)
 {
@@ -439,6 +439,7 @@ void dvb_dmx_swfilter_packets(struct dvb
 
 	spin_unlock(&demux->lock);
 }
+EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
 
 
 void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
@@ -478,6 +479,7 @@ void dvb_dmx_swfilter(struct dvb_demux *
 bailout:
 	spin_unlock(&demux->lock);
 }
+EXPORT_SYMBOL(dvb_dmx_swfilter);
 
 void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
 {
@@ -522,6 +524,7 @@ void dvb_dmx_swfilter_204(struct dvb_dem
 bailout:
 	spin_unlock(&demux->lock);
 }
+EXPORT_SYMBOL(dvb_dmx_swfilter_204);
 
 
 static struct dvb_demux_filter * dvb_dmx_filter_alloc(struct dvb_demux *demux)
@@ -1163,6 +1166,7 @@ int dvbdmx_connect_frontend(struct dmx_d
 	up(&dvbdemux->mutex);
 	return 0;
 }
+EXPORT_SYMBOL(dvbdmx_connect_frontend);
 
 
 int dvbdmx_disconnect_frontend(struct dmx_demux *demux)
@@ -1176,6 +1180,7 @@ int dvbdmx_disconnect_frontend(struct dm
 	up(&dvbdemux->mutex);
 	return 0;
 }
+EXPORT_SYMBOL(dvbdmx_disconnect_frontend);
 
 
 static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 *pids)
@@ -1256,6 +1261,7 @@ int dvb_dmx_init(struct dvb_demux *dvbde
 
 	return 0;
 }
+EXPORT_SYMBOL(dvb_dmx_init);
 
 
 int dvb_dmx_release(struct dvb_demux *dvbdemux)
@@ -1269,3 +1275,5 @@ int dvb_dmx_release(struct dvb_demux *dv
 		vfree(dvbdemux->feed);
 	return 0;
 }
+EXPORT_SYMBOL(dvb_dmx_release);
+
diff -puN drivers/media/dvb/dvb-core/dvbdev.c~dvb-core-changes drivers/media/dvb/dvb-core/dvbdev.c
--- 25/drivers/media/dvb/dvb-core/dvbdev.c~dvb-core-changes	Thu Nov 18 15:18:06 2004
+++ 25-akpm/drivers/media/dvb/dvb-core/dvbdev.c	Thu Nov 18 15:18:06 2004
@@ -132,6 +132,7 @@ int dvb_generic_open(struct inode *inode
 	dvbdev->users--;
 	return 0;
 }
+EXPORT_SYMBOL(dvb_generic_open);
 
 
 int dvb_generic_release(struct inode *inode, struct file *file)
@@ -150,6 +151,7 @@ int dvb_generic_release(struct inode *in
 	dvbdev->users++;
 	return 0;
 }
+EXPORT_SYMBOL(dvb_generic_release);
 
 
 int dvb_generic_ioctl(struct inode *inode, struct file *file,
@@ -165,6 +167,7 @@ int dvb_generic_ioctl(struct inode *inod
 
 	return dvb_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl);
 }
+EXPORT_SYMBOL(dvb_generic_ioctl);
 
 
 static int dvbdev_get_free_id (struct dvb_adapter *adap, int type)
@@ -235,6 +238,7 @@ int dvb_register_device(struct dvb_adapt
 
 	return 0;
 }
+EXPORT_SYMBOL(dvb_register_device);
 
 
 void dvb_unregister_device(struct dvb_device *dvbdev)
@@ -251,6 +255,7 @@ void dvb_unregister_device(struct dvb_de
 		list_del(&dvbdev->list_head);
 		kfree(dvbdev);
 	}
+EXPORT_SYMBOL(dvb_unregister_device);
 
 
 static int dvbdev_get_free_adapter_num (void)
@@ -309,6 +314,7 @@ int dvb_register_adapter(struct dvb_adap
 
 	return num;
 }
+EXPORT_SYMBOL(dvb_register_adapter);
 
 
 int dvb_unregister_adapter(struct dvb_adapter *adap)
@@ -322,6 +328,7 @@ int dvb_unregister_adapter(struct dvb_ad
 	kfree (adap);
 	return 0;
 }
+EXPORT_SYMBOL(dvb_unregister_adapter);
 
 /* if the miracle happens and "generic_usercopy()" is included into
    the kernel, then this can vanish. please don't make the mistake and
diff -puN drivers/media/dvb/dvb-core/dvbdev.h~dvb-core-changes drivers/media/dvb/dvb-core/dvbdev.h
--- 25/drivers/media/dvb/dvb-core/dvbdev.h~dvb-core-changes	Thu Nov 18 15:18:06 2004
+++ 25-akpm/drivers/media/dvb/dvb-core/dvbdev.h	Thu Nov 18 15:18:06 2004
@@ -49,6 +49,7 @@ struct dvb_adapter {
 	struct list_head device_list;
 	const char *name;
 	u8 proposed_mac [6];
+	void* priv;
 
 	struct module *module;
 };
diff -puN drivers/media/dvb/dvb-core/dvb_filter.c~dvb-core-changes drivers/media/dvb/dvb-core/dvb_filter.c
--- 25/drivers/media/dvb/dvb-core/dvb_filter.c~dvb-core-changes	Thu Nov 18 15:18:06 2004
+++ 25-akpm/drivers/media/dvb/dvb-core/dvb_filter.c	Thu Nov 18 15:18:06 2004
@@ -3,19 +3,20 @@
 #include <linux/string.h>
 #include "dvb_filter.h"
 
-unsigned int bitrates[3][16] =
+#if 0
+static unsigned int bitrates[3][16] =
 {{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
  {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0},
  {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}};
+#endif
 
-u32 freq[4] = {441, 480, 320, 0};
+static u32 freq[4] = {480, 441, 320, 0};
 
-unsigned int ac3_bitrates[32] =
+static unsigned int ac3_bitrates[32] =
     {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640,
      0,0,0,0,0,0,0,0,0,0,0,0,0};
 
-u32 ac3_freq[4] = {480, 441, 320, 0};
-u32 ac3_frames[3][32] =
+static u32 ac3_frames[3][32] =
     {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024,
       1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0},
      {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114,
@@ -389,6 +390,7 @@ int dvb_filter_get_ac3info(u8 *mbuf, int
 
 	return 0;
 }
+EXPORT_SYMBOL(dvb_filter_get_ac3info);
 
 
 #if 0
@@ -563,6 +565,7 @@ void dvb_filter_pes2ts_init(struct dvb_f
 	p2ts->cb=cb;
 	p2ts->priv=priv;
 }
+EXPORT_SYMBOL(dvb_filter_pes2ts_init);
 
 int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes,
 		      int len, int payload_start)
@@ -597,4 +600,5 @@ int dvb_filter_pes2ts(struct dvb_filter_
 	memcpy(buf+5+rest, pes, len);
 	return p2ts->cb(p2ts->priv, buf);
 }
+EXPORT_SYMBOL(dvb_filter_pes2ts);
 
diff -puN drivers/media/dvb/dvb-core/dvb_frontend.c~dvb-core-changes drivers/media/dvb/dvb-core/dvb_frontend.c
--- 25/drivers/media/dvb/dvb-core/dvb_frontend.c~dvb-core-changes	Thu Nov 18 15:18:06 2004
+++ 25-akpm/drivers/media/dvb/dvb-core/dvb_frontend.c	Thu Nov 18 15:18:06 2004
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/list.h>
+#include <linux/suspend.h>
 #include <asm/processor.h>
 #include <asm/semaphore.h>
 
@@ -45,6 +46,7 @@ static int dvb_shutdown_timeout = 5;
 static int dvb_override_frequency_bending;
 static int dvb_force_auto_inversion;
 static int dvb_override_tune_delay;
+static int dvb_powerdown_on_sleep = 1;
 static int do_frequency_bending;
 
 module_param_named(frontend_debug, dvb_frontend_debug, int, 0644);
@@ -57,6 +59,8 @@ module_param(dvb_force_auto_inversion, i
 MODULE_PARM_DESC(dvb_force_auto_inversion, "0: normal (default), 1: INVERSION_AUTO forced always");
 module_param(dvb_override_tune_delay, int, 0444);
 MODULE_PARM_DESC(dvb_override_tune_delay, "0: normal (default), >0 => delay in milliseconds to wait for lock after a tune attempt");
+module_param(dvb_powerdown_on_sleep, int, 0444);
+MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volatage off on sleep (default)");
 
 #define dprintk if (dvb_frontend_debug) printk
 
@@ -100,12 +104,10 @@ struct dvb_fe_events {
 
 
 struct dvb_frontend_data {
-	struct dvb_frontend_info *info;
-	struct dvb_frontend frontend;
+	struct dvb_frontend *frontend;
 	struct dvb_device *dvbdev;
 	struct dvb_frontend_parameters parameters;
 	struct dvb_fe_events events;
-	struct module *module;
 	struct semaphore sem;
 	struct list_head list_head;
 	wait_queue_head_t wait_queue;
@@ -126,53 +128,11 @@ struct dvb_frontend_data {
         fe_status_t status;
 };
 
-
-struct dvb_frontend_ioctl_data {
-	struct list_head list_head;
-	struct dvb_adapter *adapter;
-	int (*before_ioctl) (struct dvb_frontend *frontend,
-			     unsigned int cmd, void *arg);
-	int (*after_ioctl)  (struct dvb_frontend *frontend,
-			     unsigned int cmd, void *arg);
-	void *before_after_data;
-};
-
-
-struct dvb_frontend_notifier_data {
-	struct list_head list_head;
-	struct dvb_adapter *adapter;
-	void (*callback) (fe_status_t s, void *data);
-	void *data;
-};
-
-
 static LIST_HEAD(frontend_list);
-static LIST_HEAD(frontend_ioctl_list);
-static LIST_HEAD(frontend_notifier_list);
 
 static DECLARE_MUTEX(frontend_mutex);
 
 
-static int dvb_frontend_internal_ioctl (struct dvb_frontend *frontend, 
-				 unsigned int cmd, void *arg)
-{
-	int err = -EOPNOTSUPP;
-
-	dprintk ("%s\n", __FUNCTION__);
-
-	if (frontend->before_ioctl)
-		err = frontend->before_ioctl (frontend, cmd, arg);
-
-	if (err == -EOPNOTSUPP) {
-		err = frontend->ioctl (frontend, cmd, arg);
-
-		if ((err == -EOPNOTSUPP) && frontend->after_ioctl)
-			err = frontend->after_ioctl (frontend, cmd, arg);
-	}
-
-	return err;
-}
-
 
 /**
  *  if 2 tuners are located side by side you can get interferences when
@@ -184,8 +144,8 @@ static int dvb_frontend_internal_ioctl (
 static void dvb_bend_frequency (struct dvb_frontend_data *this_fe, int recursive)
 {
 	struct list_head *entry;
-	int stepsize = this_fe->info->frequency_stepsize;
-	int this_fe_adap_num = this_fe->frontend.dvb_adapter->num;
+	int stepsize = this_fe->frontend->ops->info.frequency_stepsize;
+	int this_fe_adap_num = this_fe->frontend->dvb->num;
 	int frequency;
 
 	if (!stepsize || recursive > 10) {
@@ -209,7 +169,7 @@ static void dvb_bend_frequency (struct d
 
 		fe = list_entry (entry, struct dvb_frontend_data, list_head);
 
-		if (fe->frontend.dvb_adapter->num != this_fe_adap_num)
+		if (fe->frontend->dvb->num != this_fe_adap_num)
 			continue;
 
 		f = fe->parameters.frequency;
@@ -237,25 +197,6 @@ done:
 		up (&frontend_mutex);
 }
 
-
-static void dvb_call_frontend_notifiers (struct dvb_frontend_data *fe,
-				  fe_status_t s)
-{
-	dprintk ("%s\n", __FUNCTION__);
-
-	if (((s ^ fe->status) & FE_HAS_LOCK) && (s & FE_HAS_LOCK))
-		msleep (fe->info->notifier_delay);
-
-	fe->status = s;
-
-	/**
-	 *   now tell the Demux about the TS status changes...
-	 */
-	if (fe->frontend.notifier_callback)
-		fe->frontend.notifier_callback(fe->status, fe->frontend.notifier_data);
-}
-
-
 static void dvb_frontend_add_event (struct dvb_frontend_data *fe, fe_status_t status)
 {
 	struct dvb_fe_events *events = &fe->events;
@@ -280,15 +221,13 @@ static void dvb_frontend_add_event (stru
 		sizeof (struct dvb_frontend_parameters));
 
 	if (status & FE_HAS_LOCK)
-		dvb_frontend_internal_ioctl (&fe->frontend,
-					     FE_GET_FRONTEND,
-					     &e->parameters);
+		if (fe->frontend->ops->get_frontend) fe->frontend->ops->get_frontend(fe->frontend, &e->parameters);
+
 	events->eventw = wp;
 
 	up (&events->sem);
 
 	e->status = status;
-	dvb_call_frontend_notifiers (fe, status);
 
 	wake_up_interruptible (&events->wait_queue);
 }
@@ -339,13 +278,11 @@ static int dvb_frontend_get_event (struc
 
 static void dvb_frontend_init (struct dvb_frontend_data *fe)
 {
-	struct dvb_frontend *frontend = &fe->frontend;
-
 	dprintk ("DVB: initialising frontend %i (%s)...\n",
-		 frontend->dvb_adapter->num,
-		 fe->info->name);
+		 fe->frontend->dvb->num,
+		 fe->frontend->ops->info.name);
 
-	dvb_frontend_internal_ioctl (frontend, FE_INIT, NULL);
+	if (fe->frontend->ops->init) fe->frontend->ops->init(fe->frontend);
 }
 
 static void update_delay (int *quality, int *delay, int min_delay, int locked)
@@ -380,7 +317,7 @@ static int dvb_frontend_autotune(struct 
 	u32 original_frequency = fe->parameters.frequency;
 
 	/* are we using autoinversion? */
-	autoinversion = ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) &&
+	autoinversion = ((!(fe->frontend->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
 			 (fe->parameters.inversion == INVERSION_AUTO));
 
 	/* setup parameters correctly */
@@ -453,7 +390,7 @@ static int dvb_frontend_autotune(struct 
 	/* set the frontend itself */
 	fe->parameters.frequency += fe->lnb_drift + fe->bending;
 	if (autoinversion) fe->parameters.inversion = fe->inversion;
-	dvb_frontend_internal_ioctl (&fe->frontend, FE_SET_FRONTEND, &fe->parameters);
+	if (fe->frontend->ops->set_frontend) fe->frontend->ops->set_frontend(fe->frontend, &fe->parameters);
 	fe->parameters.frequency = original_frequency;
 	fe->parameters.inversion = original_inversion;
 
@@ -489,6 +426,9 @@ static void dvb_frontend_wakeup (struct 
 	wake_up_interruptible(&fe->wait_queue);
 }
 
+/*
+ * FIXME: use linux/kthread.h
+ */
 static int dvb_frontend_thread (void *data)
 {
 	struct dvb_frontend_data *fe = (struct dvb_frontend_data *) data;
@@ -501,14 +441,14 @@ static int dvb_frontend_thread (void *da
 	dprintk ("%s\n", __FUNCTION__);
 
 	snprintf (name, sizeof(name), "kdvb-fe-%i",
-		  fe->frontend.dvb_adapter->num);
+		  fe->frontend->dvb->num);
 
         lock_kernel ();
         daemonize (name);
         sigfillset (&current->blocked);
         unlock_kernel ();
 
-	dvb_call_frontend_notifiers (fe, 0);
+	fe->status = 0;
 	dvb_frontend_init (fe);
 	fe->wakeup = 0;
 
@@ -516,11 +456,14 @@ static int dvb_frontend_thread (void *da
 		up (&fe->sem);      /* is locked when we enter the thread... */
 
 		timeout = wait_event_interruptible_timeout(fe->wait_queue,0 != dvb_frontend_should_wakeup (fe), delay);
-		if (-ERESTARTSYS == timeout || 0 != dvb_frontend_is_exiting (fe)) {
+		if (0 != dvb_frontend_is_exiting (fe)) {
 			/* got signal or quitting */
 			break;
 		}
 
+		if (current->flags & PF_FREEZE)
+			refrigerator(PF_FREEZE);
+
 		if (down_interruptible (&fe->sem))
 			break;
 
@@ -535,9 +478,10 @@ static int dvb_frontend_thread (void *da
 		if (fe->state & FESTATE_RETUNE) {
 			s = 0;
 		} else {
-		dvb_frontend_internal_ioctl (&fe->frontend, FE_READ_STATUS, &s);
+			if (fe->frontend->ops->read_status) fe->frontend->ops->read_status(fe->frontend, &s);
 			if (s != fe->status) {
 			dvb_frontend_add_event (fe, s);
+				fe->status = s;
 			}
 		}
 		/* if we're not tuned, and we have a lock, move to the TUNED state */
@@ -546,7 +490,7 @@ static int dvb_frontend_thread (void *da
 			fe->state = FESTATE_TUNED;
 
 			/* if we're tuned, then we have determined the correct inversion */
-			if ((!(fe->info->caps & FE_CAN_INVERSION_AUTO)) &&
+			if ((!(fe->frontend->ops->info.caps & FE_CAN_INVERSION_AUTO)) &&
 			    (fe->parameters.inversion == INVERSION_AUTO)) {
 				fe->parameters.inversion = fe->inversion;
 			}
@@ -572,7 +516,7 @@ static int dvb_frontend_thread (void *da
 		/* don't actually do anything if we're in the LOSTLOCK state,
 		 * the frontend is set to FE_CAN_RECOVER, and the max_drift is 0 */
 		if ((fe->state & FESTATE_LOSTLOCK) && 
-		    (fe->info->caps & FE_CAN_RECOVER) && (fe->max_drift == 0)) {
+		    (fe->frontend->ops->info.caps & FE_CAN_RECOVER) && (fe->max_drift == 0)) {
 			update_delay(&quality, &delay, fe->min_delay, s & FE_HAS_LOCK);
 						continue;
 				}
@@ -630,8 +574,11 @@ static int dvb_frontend_thread (void *da
 		}
 	};
 
-	if (dvb_shutdown_timeout)
-		dvb_frontend_internal_ioctl (&fe->frontend, FE_SLEEP, NULL); 
+	if (dvb_shutdown_timeout) {
+		if (dvb_powerdown_on_sleep)
+			if (fe->frontend->ops->set_voltage) fe->frontend->ops->set_voltage(fe->frontend, SEC_VOLTAGE_OFF);
+		if (fe->frontend->ops->sleep) fe->frontend->ops->sleep(fe->frontend);
+	}
 
 	fe->thread_pid = 0;
 	mb();
@@ -720,12 +667,11 @@ static int dvb_frontend_ioctl (struct in
 {
 	struct dvb_device *dvbdev = file->private_data;
 	struct dvb_frontend_data *fe = dvbdev->priv;
-	struct dvb_frontend_tune_settings fetunesettings;
-	int err = 0;
+	int err = -EOPNOTSUPP;
 
 	dprintk ("%s\n", __FUNCTION__);
 
-	if (!fe || !fe->frontend.ioctl || fe->exit)
+	if (!fe || fe->exit)
 		return -ENODEV;
 
 	if ((file->f_flags & O_ACCMODE) == O_RDONLY &&
@@ -737,18 +683,103 @@ static int dvb_frontend_ioctl (struct in
 		return -ERESTARTSYS;
 
 	switch (cmd) {
+	case FE_GET_INFO: {
+		struct dvb_frontend_info* info = (struct dvb_frontend_info*) parg;
+		memcpy(info, &fe->frontend->ops->info, sizeof(struct dvb_frontend_info));
+
+		/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
+		 * do it, it is done for it. */
+		info->caps |= FE_CAN_INVERSION_AUTO;
+		err = 0;
+		break;
+	}
+
+	case FE_READ_STATUS:
+		if (fe->frontend->ops->read_status)
+			err = fe->frontend->ops->read_status(fe->frontend, (fe_status_t*) parg);
+		break;
+
+	case FE_READ_BER:
+		if (fe->frontend->ops->read_ber)
+			err = fe->frontend->ops->read_ber(fe->frontend, (__u32*) parg);
+		break;
+
+	case FE_READ_SIGNAL_STRENGTH:
+		if (fe->frontend->ops->read_signal_strength)
+			err = fe->frontend->ops->read_signal_strength(fe->frontend, (__u16*) parg);
+		break;
+
+	case FE_READ_SNR:
+		if (fe->frontend->ops->read_snr)
+			err = fe->frontend->ops->read_snr(fe->frontend, (__u16*) parg);
+		break;
+
+	case FE_READ_UNCORRECTED_BLOCKS:
+		if (fe->frontend->ops->read_ucblocks)
+			err = fe->frontend->ops->read_ucblocks(fe->frontend, (__u32*) parg);
+		break;
+
+
+	case FE_DISEQC_RESET_OVERLOAD:
+		if (fe->frontend->ops->diseqc_reset_overload) {
+			err = fe->frontend->ops->diseqc_reset_overload(fe->frontend);
+			fe->state = FESTATE_DISEQC;
+			fe->status = 0;
+		}
+		break;
+
 	case FE_DISEQC_SEND_MASTER_CMD:
+		if (fe->frontend->ops->diseqc_send_master_cmd) {
+			err = fe->frontend->ops->diseqc_send_master_cmd(fe->frontend, (struct dvb_diseqc_master_cmd*) parg);
+			fe->state = FESTATE_DISEQC;
+			fe->status = 0;
+		}
+		break;
+
 	case FE_DISEQC_SEND_BURST:
+		if (fe->frontend->ops->diseqc_send_burst) {
+			err = fe->frontend->ops->diseqc_send_burst(fe->frontend, (fe_sec_mini_cmd_t) parg);
+			fe->state = FESTATE_DISEQC;
+			fe->status = 0;
+		}
+		break;
+
 	case FE_SET_TONE:
+		if (fe->frontend->ops->set_tone) {
+			err = fe->frontend->ops->set_tone(fe->frontend, (fe_sec_tone_mode_t) parg);
+			fe->state = FESTATE_DISEQC;
+			fe->status = 0;
+		}
+		break;
+
 	case FE_SET_VOLTAGE:
-		if (fe->status)
-			dvb_call_frontend_notifiers (fe, 0);
-		dvb_frontend_internal_ioctl (&fe->frontend, cmd, parg);
+		if (fe->frontend->ops->set_voltage) {
+			err = fe->frontend->ops->set_voltage(fe->frontend, (fe_sec_voltage_t) parg);
 		fe->state = FESTATE_DISEQC;
+			fe->status = 0;
+		}
 		break;
 
-	case FE_SET_FRONTEND:
-		fe->state = FESTATE_RETUNE;
+	case FE_DISHNETWORK_SEND_LEGACY_CMD:
+		if (fe->frontend->ops->dishnetwork_send_legacy_command) {
+			err = fe->frontend->ops->dishnetwork_send_legacy_command(fe->frontend, (unsigned int) parg);
+			fe->state = FESTATE_DISEQC;
+			fe->status = 0;
+		}
+		break;
+
+	case FE_DISEQC_RECV_SLAVE_REPLY:
+		if (fe->frontend->ops->diseqc_recv_slave_reply)
+			err = fe->frontend->ops->diseqc_recv_slave_reply(fe->frontend, (struct dvb_diseqc_slave_reply*) parg);
+		break;
+
+	case FE_ENABLE_HIGH_LNB_VOLTAGE:
+		if (fe->frontend->ops->enable_high_lnb_voltage);
+			err = fe->frontend->ops->enable_high_lnb_voltage(fe->frontend, (int) parg);
+		break;
+
+	case FE_SET_FRONTEND: {
+		struct dvb_frontend_tune_settings fetunesettings;
 	    
 		memcpy (&fe->parameters, parg,
 			sizeof (struct dvb_frontend_parameters));
@@ -762,7 +793,7 @@ static int dvb_frontend_ioctl (struct in
 			fe->parameters.inversion = INVERSION_AUTO;
 			fetunesettings.parameters.inversion = INVERSION_AUTO;
 		}
-		if (fe->info->type == FE_OFDM) {
+		if (fe->frontend->ops->info.type == FE_OFDM) {
 			/* without hierachical coding code_rate_LP is irrelevant,
 			 * so we tolerate the otherwise invalid FEC_NONE setting */
 			if (fe->parameters.u.ofdm.hierarchy_information == HIERARCHY_NONE &&
@@ -771,14 +802,13 @@ static int dvb_frontend_ioctl (struct in
 		}
 
 		/* get frontend-specific tuning settings */
-		if (dvb_frontend_internal_ioctl(&fe->frontend, FE_GET_TUNE_SETTINGS,
-						&fetunesettings) == 0) {
+		if (fe->frontend->ops->get_tune_settings && (fe->frontend->ops->get_tune_settings(fe->frontend, &fetunesettings) == 0)) {
 			fe->min_delay = (fetunesettings.min_delay_ms * HZ) / 1000;
 			fe->max_drift = fetunesettings.max_drift;
 			fe->step_size = fetunesettings.step_size;
 		} else {
 			/* default values */
-			switch(fe->info->type) {
+			switch(fe->frontend->ops->info.type) {
 			case FE_QPSK:
 				fe->min_delay = HZ/20;
 				fe->step_size = fe->parameters.u.qpsk.symbol_rate / 16000;
@@ -793,8 +823,8 @@ static int dvb_frontend_ioctl (struct in
 			    
 			case FE_OFDM:
 				fe->min_delay = HZ/20;
-				fe->step_size = fe->info->frequency_stepsize * 2;
-				fe->max_drift = (fe->info->frequency_stepsize * 2) + 1;
+				fe->step_size = fe->frontend->ops->info.frequency_stepsize * 2;
+				fe->max_drift = (fe->frontend->ops->info.frequency_stepsize * 2) + 1;
 				break;
 			case FE_ATSC:
 				printk("dvb-core: FE_ATSC not handled yet.\n");
@@ -805,32 +835,27 @@ static int dvb_frontend_ioctl (struct in
 		       fe->min_delay = (dvb_override_tune_delay * HZ) / 1000;
 		}
 
+		fe->state = FESTATE_RETUNE;
 		dvb_frontend_wakeup(fe);
 		dvb_frontend_add_event (fe, 0);	    
+		fe->status = 0;
+		err = 0;
 		break;
+	}
 
 	case FE_GET_EVENT:
 		err = dvb_frontend_get_event (fe, parg, file->f_flags);
 		break;
+
 	case FE_GET_FRONTEND:
-		memcpy (parg, &fe->parameters,
-			sizeof (struct dvb_frontend_parameters));
-		/*  fall-through... */
-	default:
-		err = dvb_frontend_internal_ioctl (&fe->frontend, cmd, parg);
+		if (fe->frontend->ops->get_frontend) {
+			memcpy (parg, &fe->parameters, sizeof (struct dvb_frontend_parameters));
+			err = fe->frontend->ops->get_frontend(fe->frontend, (struct dvb_frontend_parameters*) parg);
+		}
+		break;
 	};
 
 	up (&fe->sem);
-	if (err < 0)
-		return err;
-
-	/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
-	 * do it, it is done for it. */
-	if ((cmd == FE_GET_INFO) && (err == 0)) {
-		struct dvb_frontend_info* tmp = (struct dvb_frontend_info*) parg;
-		tmp->caps |= FE_CAN_INVERSION_AUTO;
-	}
-
 	return err;
 }
 
@@ -871,11 +896,6 @@ static int dvb_frontend_open (struct ino
 		fe->events.eventr = fe->events.eventw = 0;
 	}
 	
-	if (!ret && fe->module) {
-		if (!try_module_get(fe->module))
-			return -EINVAL;
-	}
-
 	return ret;
 }
 
@@ -884,206 +904,13 @@ static int dvb_frontend_release (struct 
 {
 	struct dvb_device *dvbdev = file->private_data;
 	struct dvb_frontend_data *fe = dvbdev->priv;
-	int ret = 0;
 
 	dprintk ("%s\n", __FUNCTION__);
 
 	if ((file->f_flags & O_ACCMODE) != O_RDONLY)
 		fe->release_jiffies = jiffies;
 
-	ret = dvb_generic_release (inode, file);
-
-	if (!ret && fe->module)
-		module_put(fe->module);
-
-	return ret;
-}
-
-
-
-int
-dvb_add_frontend_ioctls (struct dvb_adapter *adapter,
-                         int (*before_ioctl) (struct dvb_frontend *frontend,
-                                              unsigned int cmd, void *arg),
-                         int (*after_ioctl)  (struct dvb_frontend *frontend,
-                                              unsigned int cmd, void *arg),
-			 void *before_after_data)
-{
-	struct dvb_frontend_ioctl_data *ioctl;
-        struct list_head *entry;
-
-	dprintk ("%s\n", __FUNCTION__);
-
-	if (down_interruptible (&frontend_mutex))
-		return -ERESTARTSYS;
-
-	ioctl = kmalloc (sizeof(struct dvb_frontend_ioctl_data), GFP_KERNEL);
-
-	if (!ioctl) {
-		up (&frontend_mutex);
-		return -ENOMEM;
-	}
-
-	ioctl->adapter = adapter;
-	ioctl->before_ioctl = before_ioctl;
-	ioctl->after_ioctl = after_ioctl;
-	ioctl->before_after_data = before_after_data;
-
-	list_add_tail (&ioctl->list_head, &frontend_ioctl_list);
-
-	list_for_each (entry, &frontend_list) {
-		struct dvb_frontend_data *fe;
-
-		fe = list_entry (entry, struct dvb_frontend_data, list_head);
-
-		if (fe->frontend.dvb_adapter == adapter &&
-		    fe->frontend.before_ioctl == NULL &&
-		    fe->frontend.after_ioctl == NULL)
-		{
-			fe->frontend.before_ioctl = before_ioctl;
-			fe->frontend.after_ioctl = after_ioctl;
-			fe->frontend.before_after_data = before_after_data;
-		}
-	}
-
-	up (&frontend_mutex);
-
-	return 0;
-}
-
-
-void
-dvb_remove_frontend_ioctls (struct dvb_adapter *adapter,
-			    int (*before_ioctl) (struct dvb_frontend *frontend,
-                                                 unsigned int cmd, void *arg),
-                            int (*after_ioctl)  (struct dvb_frontend *frontend,
-                                                 unsigned int cmd, void *arg))
-{
-	struct list_head *entry, *n;
-
-	dprintk ("%s\n", __FUNCTION__);
-
-	down (&frontend_mutex);
-
-	list_for_each (entry, &frontend_list) {
-		struct dvb_frontend_data *fe;
-
-		fe = list_entry (entry, struct dvb_frontend_data, list_head);
-
-		if (fe->frontend.dvb_adapter == adapter &&
-		    fe->frontend.before_ioctl == before_ioctl &&
-		    fe->frontend.after_ioctl == after_ioctl)
-		{
-			fe->frontend.before_ioctl = NULL;
-			fe->frontend.after_ioctl = NULL;
-
-		}
-	}
-
-	list_for_each_safe (entry, n, &frontend_ioctl_list) {
-		struct dvb_frontend_ioctl_data *ioctl;
-
-		ioctl = list_entry (entry, struct dvb_frontend_ioctl_data, list_head);
-
-		if (ioctl->adapter == adapter &&
-		    ioctl->before_ioctl == before_ioctl &&
-		    ioctl->after_ioctl == after_ioctl)
-		{
-			list_del (&ioctl->list_head);
-			kfree (ioctl);
-			
-			break;
-		}
-	}
-
-	up (&frontend_mutex);
-}
-
-
-int
-dvb_add_frontend_notifier (struct dvb_adapter *adapter,
-			   void (*callback) (fe_status_t s, void *data),
-			   void *data)
-{
-	struct dvb_frontend_notifier_data *notifier;
-	struct list_head *entry;
-
-	dprintk ("%s\n", __FUNCTION__);
-
-	if (down_interruptible (&frontend_mutex))
-		return -ERESTARTSYS;
-
-	notifier = kmalloc (sizeof(struct dvb_frontend_notifier_data), GFP_KERNEL);
-
-	if (!notifier) {
-		up (&frontend_mutex);
-		return -ENOMEM;
-	}
-
-	notifier->adapter = adapter;
-	notifier->callback = callback;
-	notifier->data = data;
-
-	list_add_tail (&notifier->list_head, &frontend_notifier_list);
-
-	list_for_each (entry, &frontend_list) {
-		struct dvb_frontend_data *fe;
-
-		fe = list_entry (entry, struct dvb_frontend_data, list_head);
-
-		if (fe->frontend.dvb_adapter == adapter &&
-		    fe->frontend.notifier_callback == NULL)
-		{
-			fe->frontend.notifier_callback = callback;
-			fe->frontend.notifier_data = data;
-		}
-	}
-
-	up (&frontend_mutex);
-
-	return 0;
-}
-
-
-void
-dvb_remove_frontend_notifier (struct dvb_adapter *adapter,
-			      void (*callback) (fe_status_t s, void *data))
-{
-	struct list_head *entry, *n;
-
-	dprintk ("%s\n", __FUNCTION__);
-
-	down (&frontend_mutex);
-
-	list_for_each (entry, &frontend_list) {
-		struct dvb_frontend_data *fe;
-
-		fe = list_entry (entry, struct dvb_frontend_data, list_head);
-
-		if (fe->frontend.dvb_adapter == adapter &&
-		    fe->frontend.notifier_callback == callback)
-		{
-			fe->frontend.notifier_callback = NULL;
-
-		}
-	}
-
-	list_for_each_safe (entry, n, &frontend_notifier_list) {
-		struct dvb_frontend_notifier_data *notifier;
-
-		notifier = list_entry (entry, struct dvb_frontend_notifier_data, list_head);
-
-		if (notifier->adapter == adapter &&
-		    notifier->callback == callback)
-		{
-			list_del (&notifier->list_head);
-			kfree (notifier);
-			
-			break;
-		}
-	}
-
-	up (&frontend_mutex);
+	return dvb_generic_release (inode, file);
 }
 
 
@@ -1096,16 +923,9 @@ static struct file_operations dvb_fronte
 };
 
 
-
-int
-dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
-				     unsigned int cmd, void *arg),
-		       struct dvb_adapter *dvb_adapter,
-		       void *data,
-		       struct dvb_frontend_info *info,
-		       struct module *module)
+int dvb_register_frontend(struct dvb_adapter* dvb,
+			  struct dvb_frontend* frontend)
 {
-	struct list_head *entry;
 	struct dvb_frontend_data *fe;
 	static const struct dvb_device dvbdev_template = {
 		.users = ~0,
@@ -1133,63 +953,30 @@ dvb_register_frontend (int (*ioctl) (str
 	init_MUTEX (&fe->events.sem);
 	fe->events.eventw = fe->events.eventr = 0;
 	fe->events.overflow = 0;
-	fe->module = module;
 
-	fe->frontend.ioctl = ioctl;
-	fe->frontend.dvb_adapter = dvb_adapter;
-	fe->frontend.data = data;
-	fe->info = info;
-	fe->inversion = INVERSION_OFF;
+	fe->frontend = frontend;
+	fe->frontend->dvb = dvb;
 
-	list_for_each (entry, &frontend_ioctl_list) {
-		struct dvb_frontend_ioctl_data *ioctl;
-
-		ioctl = list_entry (entry,
-				    struct dvb_frontend_ioctl_data,
-				    list_head);
-
-		if (ioctl->adapter == dvb_adapter) {
-			fe->frontend.before_ioctl = ioctl->before_ioctl;
-			fe->frontend.after_ioctl = ioctl->after_ioctl;
-			fe->frontend.before_after_data = ioctl->before_after_data;
-			break;
-		}
-	}
-
-	list_for_each (entry, &frontend_notifier_list) {
-		struct dvb_frontend_notifier_data *notifier;
-
-		notifier = list_entry (entry,
-				       struct dvb_frontend_notifier_data,
-				       list_head);
-
-		if (notifier->adapter == dvb_adapter) {
-			fe->frontend.notifier_callback = notifier->callback;
-			fe->frontend.notifier_data = notifier->data;
-			break;
-		}
-	}
+	fe->inversion = INVERSION_OFF;
 
 	list_add_tail (&fe->list_head, &frontend_list);
 
 	printk ("DVB: registering frontend %i (%s)...\n",
-		fe->frontend.dvb_adapter->num,
-		fe->info->name);
+		fe->frontend->dvb->num,
+		fe->frontend->ops->info.name);
 
-	dvb_register_device (dvb_adapter, &fe->dvbdev, &dvbdev_template,
+	dvb_register_device (fe->frontend->dvb, &fe->dvbdev, &dvbdev_template,
 			     fe, DVB_DEVICE_FRONTEND);
 
-	if ((info->caps & FE_NEEDS_BENDING) || (dvb_override_frequency_bending == 2))
+	if ((fe->frontend->ops->info.caps & FE_NEEDS_BENDING) || (dvb_override_frequency_bending == 2))
 		do_frequency_bending = 1;
     
 	up (&frontend_mutex);
-
 	return 0;
 }
+EXPORT_SYMBOL(dvb_register_frontend);
 
-int dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend,
-					   unsigned int cmd, void *arg),
-			     struct dvb_adapter *dvb_adapter)
+int dvb_unregister_frontend (struct dvb_frontend* frontend)
 {
         struct list_head *entry, *n;
 
@@ -1202,11 +989,16 @@ int dvb_unregister_frontend (int (*ioctl
 
 		fe = list_entry (entry, struct dvb_frontend_data, list_head);
 
-		if (fe->frontend.ioctl == ioctl && fe->frontend.dvb_adapter == dvb_adapter) {
+		if (fe->frontend == frontend) {
 			dvb_unregister_device (fe->dvbdev);
 			list_del (entry);
 			up (&frontend_mutex);
 			dvb_frontend_stop (fe);
+			if (fe->frontend->ops->release) {
+				fe->frontend->ops->release(fe->frontend);
+			} else {
+				printk("dvb_frontend: Demodulator (%s) does not have a release callback!\n", fe->frontend->ops->info.name);
+			}
 			kfree (fe);
 			return 0;
 		}
@@ -1215,4 +1007,4 @@ int dvb_unregister_frontend (int (*ioctl
 	up (&frontend_mutex);
 	return -EINVAL;
 }
-
+EXPORT_SYMBOL(dvb_unregister_frontend);
diff -puN drivers/media/dvb/dvb-core/dvb_frontend.h~dvb-core-changes drivers/media/dvb/dvb-core/dvb_frontend.h
--- 25/drivers/media/dvb/dvb-core/dvb_frontend.h~dvb-core-changes	Thu Nov 18 15:18:06 2004
+++ 25-akpm/drivers/media/dvb/dvb-core/dvb_frontend.h	Thu Nov 18 15:18:06 2004
@@ -1,9 +1,12 @@
 /* 
  * dvb_frontend.h
  *
- * Copyright (C) 2001 Ralph Metzler for convergence integrated media GmbH
- *                    overhauled by Holger Waechtler for Convergence GmbH
+ * Copyright (C) 2001 convergence integrated media GmbH
+ * Copyright (C) 2004 convergence GmbH
  *
+ * Written by Ralph Metzler
+ * Overhauled by Holger Waechtler
+ * Kernel I2C stuff by Michael Hunold <hunold@convergence.de>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -38,8 +41,8 @@
 #include "dvbdev.h"
 
 /* FIXME: Move to i2c-id.h */
-#define I2C_DRIVERID_DVBFE_ALPS_TDLB7	I2C_DRIVERID_EXP2
-#define I2C_DRIVERID_DVBFE_ALPS_TDMB7	I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_SP8870	I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_CX22700	I2C_DRIVERID_EXP2
 #define I2C_DRIVERID_DVBFE_AT76C651	I2C_DRIVERID_EXP2
 #define I2C_DRIVERID_DVBFE_CX24110	I2C_DRIVERID_EXP2
 #define I2C_DRIVERID_DVBFE_CX22702	I2C_DRIVERID_EXP2
@@ -56,22 +59,8 @@
 #define I2C_DRIVERID_DVBFE_TDA8083	I2C_DRIVERID_EXP2
 #define I2C_DRIVERID_DVBFE_VES1820	I2C_DRIVERID_EXP2
 #define I2C_DRIVERID_DVBFE_VES1X93	I2C_DRIVERID_EXP2
+#define I2C_DRIVERID_DVBFE_TDA80XX	I2C_DRIVERID_EXP2
 
-/**
- *   when before_ioctl is registered and returns value 0, ioctl and after_ioctl
- *   are not executed.
- */
-
-struct dvb_frontend {
-	int (*before_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg);
-	int (*ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg);
-	int (*after_ioctl) (struct dvb_frontend *frontend, unsigned int cmd, void *arg);
-	void (*notifier_callback) (fe_status_t s, void *data);
-	struct dvb_adapter *dvb_adapter;
-	void *before_after_data;   /*  can be used by hardware module... */
-	void *notifier_data;       /*  can be used by hardware module... */
-	void *data;                /*  can be used by hardware module... */
-};
 
 struct dvb_frontend_tune_settings {
         int min_delay_ms;
@@ -80,67 +69,47 @@ struct dvb_frontend_tune_settings {
         struct dvb_frontend_parameters parameters;
 };
 
+struct dvb_frontend;
 
-/**
- *   private frontend command ioctl's.
- *   keep them in sync with the public ones defined in linux/dvb/frontend.h
- * 
- *   FE_SLEEP. Ioctl used to put frontend into a low power mode.
- *   FE_INIT. Ioctl used to initialise the frontend.
- *   FE_GET_TUNE_SETTINGS. Get the frontend-specific tuning loop settings for the supplied set of parameters.
- */
-#define FE_SLEEP              _IO('v', 80)
-#define FE_INIT               _IO('v', 81)
-#define FE_GET_TUNE_SETTINGS  _IOWR('v', 83, struct dvb_frontend_tune_settings)
-#define FE_REGISTER	      _IO  ('v', 84)
-#define FE_UNREGISTER	      _IO  ('v', 85)
-
-extern int
-dvb_register_frontend (int (*ioctl) (struct dvb_frontend *frontend,
-				     unsigned int cmd, void *arg),
-		       struct dvb_adapter *dvb_adapter,
-		       void *data,
-		       struct dvb_frontend_info *info,
-		       struct module *module);
-
-extern int
-dvb_unregister_frontend (int (*ioctl) (struct dvb_frontend *frontend,
-				       unsigned int cmd, void *arg),
-			 struct dvb_adapter *dvb_adapter);
-
-
-/**
- *  Add special ioctl code performed before and after the main ioctl
- *  to all frontend devices on the specified DVB adapter.
- *  This is necessairy because the 22kHz/13V-18V/DiSEqC stuff depends
- *  heavily on the hardware around the frontend, the same tuner can create 
- *  these signals on about a million different ways...
- *
- *  Return value: number of frontends where the ioctl's were applied.
- */
-extern int
-dvb_add_frontend_ioctls (struct dvb_adapter *adapter,
-			 int (*before_ioctl) (struct dvb_frontend *frontend,
-					      unsigned int cmd, void *arg),
-			 int (*after_ioctl)  (struct dvb_frontend *frontend,
-					      unsigned int cmd, void *arg),
-			 void *before_after_data);
-
-
-extern void
-dvb_remove_frontend_ioctls (struct dvb_adapter *adapter,
-			    int (*before_ioctl) (struct dvb_frontend *frontend,
-					         unsigned int cmd, void *arg),
-			    int (*after_ioctl)  (struct dvb_frontend *frontend,
-					         unsigned int cmd, void *arg));
-
-extern int
-dvb_add_frontend_notifier (struct dvb_adapter *adapter,
-			   void (*callback) (fe_status_t s, void *data),
-			   void *data);
-extern void
-dvb_remove_frontend_notifier (struct dvb_adapter *adapter,
-			      void (*callback) (fe_status_t s, void *data));
+struct dvb_frontend_ops {
 
-#endif
+	struct dvb_frontend_info info;
+
+	void (*release)(struct dvb_frontend* fe);
 
+	int (*init)(struct dvb_frontend* fe);
+	int (*sleep)(struct dvb_frontend* fe);
+
+	int (*set_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+	int (*get_frontend)(struct dvb_frontend* fe, struct dvb_frontend_parameters* params);
+	int (*get_tune_settings)(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* settings);
+
+	int (*read_status)(struct dvb_frontend* fe, fe_status_t* status);
+	int (*read_ber)(struct dvb_frontend* fe, u32* ber);
+	int (*read_signal_strength)(struct dvb_frontend* fe, u16* strength);
+	int (*read_snr)(struct dvb_frontend* fe, u16* snr);
+	int (*read_ucblocks)(struct dvb_frontend* fe, u32* ucblocks);
+
+	int (*diseqc_reset_overload)(struct dvb_frontend* fe);
+	int (*diseqc_send_master_cmd)(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd);
+	int (*diseqc_recv_slave_reply)(struct dvb_frontend* fe, struct dvb_diseqc_slave_reply* reply);
+	int (*diseqc_send_burst)(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd);
+	int (*set_tone)(struct dvb_frontend* fe, fe_sec_tone_mode_t tone);
+	int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
+	int (*enable_high_lnb_voltage)(struct dvb_frontend* fe, int arg);
+	int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned int cmd);
+};
+
+struct dvb_frontend {
+
+	struct dvb_frontend_ops* ops;
+	struct dvb_adapter *dvb;
+	void* demodulator_priv;
+};
+
+extern int dvb_register_frontend(struct dvb_adapter* dvb,
+				 struct dvb_frontend* fe);
+
+extern int dvb_unregister_frontend(struct dvb_frontend* fe);
+
+#endif
diff -L drivers/media/dvb/dvb-core/dvb_ksyms.c -puN drivers/media/dvb/dvb-core/dvb_ksyms.c~dvb-core-changes /dev/null
--- 25/drivers/media/dvb/dvb-core/dvb_ksyms.c
+++ /dev/null	Thu Apr 11 07:25:15 2002
@@ -1,52 +0,0 @@
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/ioctl.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <asm/uaccess.h>
-
-#include "dmxdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-#include "dvb_filter.h"
-#include "dvb_ca_en50221.h"
-
-EXPORT_SYMBOL(dvb_dmxdev_init);
-EXPORT_SYMBOL(dvb_dmxdev_release);
-EXPORT_SYMBOL(dvb_dmx_init);
-EXPORT_SYMBOL(dvb_dmx_release);
-EXPORT_SYMBOL(dvb_dmx_swfilter_packet);
-EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
-EXPORT_SYMBOL(dvb_dmx_swfilter);
-EXPORT_SYMBOL(dvb_dmx_swfilter_204);
-EXPORT_SYMBOL(dvbdmx_connect_frontend);
-EXPORT_SYMBOL(dvbdmx_disconnect_frontend);
-
-EXPORT_SYMBOL(dvb_register_frontend);
-EXPORT_SYMBOL(dvb_unregister_frontend);
-EXPORT_SYMBOL(dvb_add_frontend_ioctls);
-EXPORT_SYMBOL(dvb_remove_frontend_ioctls);
-EXPORT_SYMBOL(dvb_add_frontend_notifier);
-EXPORT_SYMBOL(dvb_remove_frontend_notifier);
-
-EXPORT_SYMBOL(dvb_net_init);
-EXPORT_SYMBOL(dvb_net_release);
-
-EXPORT_SYMBOL(dvb_register_adapter);
-EXPORT_SYMBOL(dvb_unregister_adapter);
-EXPORT_SYMBOL(dvb_register_device);
-EXPORT_SYMBOL(dvb_unregister_device);
-EXPORT_SYMBOL(dvb_generic_ioctl);
-EXPORT_SYMBOL(dvb_generic_open);
-EXPORT_SYMBOL(dvb_generic_release);
-
-EXPORT_SYMBOL(dvb_filter_pes2ts_init);
-EXPORT_SYMBOL(dvb_filter_pes2ts);
-EXPORT_SYMBOL(dvb_filter_get_ac3info);
-
-EXPORT_SYMBOL(dvb_ca_en50221_init);
-EXPORT_SYMBOL(dvb_ca_en50221_release);
-EXPORT_SYMBOL(dvb_ca_en50221_frda_irq);
-EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq);
-EXPORT_SYMBOL(dvb_ca_en50221_camready_irq);
diff -puN drivers/media/dvb/dvb-core/dvb_net.c~dvb-core-changes drivers/media/dvb/dvb-core/dvb_net.c
--- 25/drivers/media/dvb/dvb-core/dvb_net.c~dvb-core-changes	Thu Nov 18 15:18:06 2004
+++ 25-akpm/drivers/media/dvb/dvb-core/dvb_net.c	Thu Nov 18 15:18:06 2004
@@ -30,6 +30,7 @@
  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
  */
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -141,7 +142,11 @@ static unsigned short dvb_net_eth_type_t
 	
 	skb->mac.raw=skb->data;
 	skb_pull(skb,dev->hard_header_len);
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,8)
+	eth = skb->mac.ethernet;
+#else
 	eth = eth_hdr(skb);
+#endif
 	
 	if (*eth->h_dest & 1) {
 		if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
@@ -1193,6 +1198,7 @@ void dvb_net_release (struct dvb_net *dv
 		dvb_net_remove_if(dvbnet, i);
 	}
 }
+EXPORT_SYMBOL(dvb_net_release);
 
 
 int dvb_net_init (struct dvb_adapter *adap, struct dvb_net *dvbnet,
@@ -1210,4 +1216,4 @@ int dvb_net_init (struct dvb_adapter *ad
 
 	return 0;
 }
-
+EXPORT_SYMBOL(dvb_net_init);
diff -puN include/linux/dvb/frontend.h~dvb-core-changes include/linux/dvb/frontend.h
--- 25/include/linux/dvb/frontend.h~dvb-core-changes	Thu Nov 18 15:18:06 2004
+++ 25-akpm/include/linux/dvb/frontend.h	Thu Nov 18 15:18:06 2004
@@ -78,7 +78,7 @@ struct dvb_frontend_info {
 	__u32      symbol_rate_min;
         __u32      symbol_rate_max;
 	__u32      symbol_rate_tolerance;     /* ppm */
-	__u32      notifier_delay;            /* ms */
+	__u32      notifier_delay;		/* DEPRECATED */
 	fe_caps_t  caps;
 };
 
_