diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2008-11-02 12:45:00 (GMT) |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-02-24 13:51:28 (GMT) |
commit | 8ae83cdf3297d7da301af36bdb6ff45bd331c6d0 (patch) | |
tree | 0363a01f1b3655507bdaf7e1f55af6a3ee9d26b7 /drivers | |
parent | 00fc3072e484c1c6fdbd9c3b1851f866000a6cb9 (diff) | |
download | linux-fsl-qoriq-8ae83cdf3297d7da301af36bdb6ff45bd331c6d0.tar.xz |
firedtv: cleanups and minor fixes
Combination of the following changes:
Sun, 2 Nov 2008 13:45:00 +0100 (CET)
firedtv: increase FCP frame length for DVB-S2 tune QSPK
The last three bytes didn't go out to the wire.
Effect of the fix not yet tested.
Sun, 2 Nov 2008 13:45:00 +0100 (CET)
firedtv: replace mdelay by msleep
These functions can sleep (and in fact sleep for the duration of a whole
FCP transaction). Hence msleep is more appropriate here.
Sun, 2 Nov 2008 13:45:00 +0100 (CET)
firedtv: trivial reorganization in avc_api
Reduce nesting level by factoring code out of avc_tuner_dsd() into
helper functions.
Sun, 2 Nov 2008 13:45:00 +0100 (CET)
firedtv: trivial cleanups in avc_api
Use dev_err(), no CamelCase function names, adjust comment style, put
#if 0 around unused code and add FIXME comments, standardize on
lower-case hexadecimal constants, use ALIGN() for some frame length
calculations, make a local function static...
The code which writes FCP command frames and reads FCP response frames
is not yet brought into canonical kernel coding style because this
involves changes of typedefs (on-the-wire bitfields).
Sun, 2 Nov 2008 13:45:00 +0100 (CET)
firedtv: don't retry oPCR updates endlessly
In the theoretical case that the target node wasn't handling the lock
transactions as expected or there was continued interference by other
initiating nodes, these functions wouldn't return for ages.
Sun, 2 Nov 2008 13:45:00 +0100 (CET)
firedtv: remove bitfield typedefs from cmp, fix for big endian CPUs
Use macros/ inline functions/ standard byte order accessors to read and
write oPCR register values (big endian bitfields, on-the-wire data).
The new code may not be the ultimate optimum, but it doesn't occur in a
hot path.
This fixes the CMP code for big endian CPUs. So far I tested it only on
a little endian CPU though.
For now, include <asm/byteorder.h> instead of <linux/byteorder.h>
because drivers/ieee1394/*.h also include the former. I will fix this
in drivers/ieee1394 and firedtv later.
Sun, 2 Nov 2008 13:45:00 +0100 (CET)
firedtv: trivial cleanups in cmp
Reduce nesting level by means of early exit and goto.
Remove obsolete includes, use dev_err(), no CamelCase function names...
Sun, 2 Nov 2008 13:45:00 +0100 (CET)
firedtv: trivial cleanups in firesat-ci
Whitespace, variable names, comment style...
Also, use dvb_generic_open() and dvb_generic_release() directly as
our hooks in struct file_operations because firedtv's wrappers merely
called these generic functions.
Sun, 2 Nov 2008 13:45:00 +0100 (CET)
firedtv: remove CA debug code
This looks like it is not necessary to have available for endusers who
cannot patch kernels for bug reporting and tests of fixes.
Sun, 2 Nov 2008 13:45:00 +0100 (CET)
firedtv: remove AV/C debug code
This looks like it is not necessary to have available for endusers who
cannot patch kernels for bug reporting and tests of fixes.
Sun, 2 Nov 2008 13:45:00 +0100 (CET)
firedtv: remove various debug code
Most of this was already commented out. And that which wasn't is not
relevant in normal use.
Mon, 29 Sep 2008 19:22:48 +0200 (CEST)
firedtv: register input device as child of a FireWire device
Instead of one virtual input device which exists for the whole lifetime
of the driver and receives events from all connected FireDTVs, register
one input device for each firedtv device. These input devices will show
up as children of the respective firedtv devices in the sysfs hierarchy.
However, the implementation falls short because of a bug in userspace:
Udev's path_id script gets stuck with 100% CPU utilization, maybe
because of an assumption about the maximum ieee1394 device hierarchy
depth.
To avoid this bug, we use the fw-host device instead of the proper
unit_directory device as parent of the input device.
There is hope that the port to the new firewire stack won't be inhibited
by this userspace bug because there are no fw-host devices there.
Mon, 29 Sep 2008 19:21:52 +0200 (CEST)
firedtv: fix string comparison and a few sparse warnings
Sparse found a bug:
while ((kv_buf + kv_len - 1) == '\0')
should have been
while (kv_buf[kv_len - 1] == '\0')
We fix it by a better implementation without a temporary copy.
Also fix sparse warnings of 0 instead of NULL and signedness mismatches.
Mon, 29 Sep 2008 19:21:20 +0200 (CEST)
firedtv: remove unused struct members
and redefine an int as a bool.
Mon, 29 Sep 2008 19:20:36 +0200 (CEST)
firedtv: fix initialization of dvb_frontend.ops
There was a NULL pointer reference if no dvb_frontend_info was found.
Also, don't directly assign struct typed values to struct typed
variables. Instead write out assignments to individual strcut members.
This reduces module size by about 1 kB.
Mon, 29 Sep 2008 19:19:41 +0200 (CEST)
firedtv: remove unused dual subunit code from initialization
No FireDTVs with more than one subunit exists, hence simplify the
initialization for the special case of one subunit. The driver was able
to check for more than one subunit but was broken for more than two
subunits.
While we are at it, add several missing cleanups after failure, and
include a few dynamically allocated structures diretly into struct
firesat instead of allocating them separately.
Mon, 29 Sep 2008 19:19:08 +0200 (CEST)
firedtv: add vendor_id and version to driver match table
Now that nodemgr was enhanced to match against the root directory's
vendor ID if there isn't one in the unit directory, use this to
prevent firedtv to be bound to wrong devices by accident.
Also add the AV/C software version ID to the match flags for
completeness; specifier ID and software only make sense as a pair.
Mon, 29 Sep 2008 19:18:30 +0200 (CEST)
firedtv: use hpsb_node_read(), _write(), _lock()
because they are simpler and treat the node generation more correctly.
While we are at it, clean up and simplify surrounding code.
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/dvb/firesat/avc_api.c | 1074 | ||||
-rw-r--r-- | drivers/media/dvb/firesat/avc_api.h | 38 | ||||
-rw-r--r-- | drivers/media/dvb/firesat/cmp.c | 252 | ||||
-rw-r--r-- | drivers/media/dvb/firesat/cmp.h | 6 | ||||
-rw-r--r-- | drivers/media/dvb/firesat/firesat-ci.c | 244 | ||||
-rw-r--r-- | drivers/media/dvb/firesat/firesat-ci.h | 2 | ||||
-rw-r--r-- | drivers/media/dvb/firesat/firesat-rc.c | 42 | ||||
-rw-r--r-- | drivers/media/dvb/firesat/firesat-rc.h | 9 | ||||
-rw-r--r-- | drivers/media/dvb/firesat/firesat.h | 68 | ||||
-rw-r--r-- | drivers/media/dvb/firesat/firesat_1394.c | 301 | ||||
-rw-r--r-- | drivers/media/dvb/firesat/firesat_dvb.c | 178 | ||||
-rw-r--r-- | drivers/media/dvb/firesat/firesat_fe.c | 223 | ||||
-rw-r--r-- | drivers/media/dvb/firesat/firesat_iso.c | 11 |
13 files changed, 964 insertions, 1484 deletions
diff --git a/drivers/media/dvb/firesat/avc_api.c b/drivers/media/dvb/firesat/avc_api.c index 6337f9f..56911f3 100644 --- a/drivers/media/dvb/firesat/avc_api.c +++ b/drivers/media/dvb/firesat/avc_api.c @@ -11,14 +11,16 @@ * the License, or (at your option) any later version. */ +#include <linux/bug.h> #include <linux/crc32.h> #include <linux/delay.h> +#include <linux/device.h> #include <linux/kernel.h> #include <linux/moduleparam.h> #include <linux/mutex.h> +#include <linux/string.h> #include <linux/wait.h> #include <linux/workqueue.h> -#include <asm/atomic.h> #include <ieee1394_transactions.h> #include <nodemgr.h> @@ -27,230 +29,61 @@ #include "firesat.h" #include "firesat-rc.h" -#define RESPONSE_REGISTER 0xFFFFF0000D00ULL -#define COMMAND_REGISTER 0xFFFFF0000B00ULL -#define PCR_BASE_ADDRESS 0xFFFFF0000900ULL +#define FCP_COMMAND_REGISTER 0xfffff0000b00ULL -static unsigned int avc_comm_debug = 0; -module_param(avc_comm_debug, int, 0644); -MODULE_PARM_DESC(avc_comm_debug, "debug logging level [0..2] of AV/C communication, default is 0 (no)"); - -/* Frees an allocated packet */ -static void avc_free_packet(struct hpsb_packet *packet) -{ - hpsb_free_tlabel(packet); - hpsb_free_packet(packet); -} - -static const char* get_ctype_string(__u8 ctype) -{ - switch(ctype) - { - case 0: - return "CONTROL"; - case 1: - return "STATUS"; - case 2: - return "SPECIFIC_INQUIRY"; - case 3: - return "NOTIFY"; - case 4: - return "GENERAL_INQUIRY"; - } - return "UNKNOWN"; -} - -static const char* get_resp_string(__u8 ctype) -{ - switch(ctype) - { - case 8: - return "NOT_IMPLEMENTED"; - case 9: - return "ACCEPTED"; - case 10: - return "REJECTED"; - case 11: - return "IN_TRANSITION"; - case 12: - return "IMPLEMENTED_STABLE"; - case 13: - return "CHANGED"; - case 15: - return "INTERIM"; - } - return "UNKNOWN"; -} - -static const char* get_subunit_address(__u8 subunit_id, __u8 subunit_type) -{ - if (subunit_id == 7 && subunit_type == 0x1F) - return "Unit"; - if (subunit_id == 0 && subunit_type == 0x05) - return "Tuner(0)"; - return "Unsupported"; -} - -static const char* get_opcode_string(__u8 opcode) -{ - switch(opcode) - { - case 0x02: - return "PlugInfo"; - case 0x08: - return "OpenDescriptor"; - case 0x09: - return "ReadDescriptor"; - case 0x18: - return "OutputPlugSignalFormat"; - case 0x31: - return "SubunitInfo"; - case 0x30: - return "UnitInfo"; - case 0xB2: - return "Power"; - case 0xC8: - return "DirectSelectInformationType"; - case 0xCB: - return "DirectSelectData"; - case 0x00: - return "Vendor"; - - } - return "Unknown"; -} - -static void log_command_frame(const AVCCmdFrm *CmdFrm) -{ - int k; - printk(KERN_INFO "AV/C Command Frame:\n"); - printk(KERN_INFO "CommandType=%s, Address=%s(0x%02X,0x%02X), " - "opcode=%s(0x%02X), length=%d\n", - get_ctype_string(CmdFrm->ctype), - get_subunit_address(CmdFrm->suid, CmdFrm->sutyp), - CmdFrm->suid, CmdFrm->sutyp, get_opcode_string(CmdFrm->opcode), - CmdFrm->opcode, CmdFrm->length); - if (avc_comm_debug > 1) { - for(k = 0; k < CmdFrm->length - 3; k++) { - if (k % 5 != 0) - printk(", "); - else if (k != 0) - printk("\n"); - printk(KERN_INFO "operand[%d] = %02X", k, - CmdFrm->operand[k]); - } - printk(KERN_INFO "\n"); - } -} - -static void log_response_frame(const AVCRspFrm *RspFrm) +static int __avc_write(struct firesat *firesat, + const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm) { - int k; - printk(KERN_INFO "AV/C Response Frame:\n"); - printk(KERN_INFO "Response=%s, Address=%s(0x%02X,0x%02X), " - "opcode=%s(0x%02X), length=%d\n", get_resp_string(RspFrm->resp), - get_subunit_address(RspFrm->suid, RspFrm->sutyp), - RspFrm->suid, RspFrm->sutyp, get_opcode_string(RspFrm->opcode), - RspFrm->opcode, RspFrm->length); - if (avc_comm_debug > 1) { - for(k = 0; k < RspFrm->length - 3; k++) { - if (k % 5 != 0) - printk(KERN_INFO ", "); - else if (k != 0) - printk(KERN_INFO "\n"); - printk(KERN_INFO "operand[%d] = %02X", k, - RspFrm->operand[k]); + int err, retry; + + if (RspFrm) + firesat->avc_reply_received = false; + + for (retry = 0; retry < 6; retry++) { + err = hpsb_node_write(firesat->ud->ne, FCP_COMMAND_REGISTER, + (quadlet_t *)CmdFrm, CmdFrm->length); + if (err) { + firesat->avc_reply_received = true; + dev_err(&firesat->ud->device, + "FCP command write failed\n"); + return err; } - printk(KERN_INFO "\n"); - } -} - -static int __AVCWrite(struct firesat *firesat, const AVCCmdFrm *CmdFrm, - AVCRspFrm *RspFrm) { - struct hpsb_packet *packet; - struct node_entry *ne; - int num_tries = 0; - int packet_ok = 0; - - ne = firesat->nodeentry; - if(!ne) { - printk(KERN_ERR "%s: lost node!\n",__func__); - return -EIO; - } - - /* need all input data */ - if(!firesat || !ne || !CmdFrm) { - printk(KERN_ERR "%s: missing input data!\n",__func__); - return -EINVAL; - } - if (avc_comm_debug > 0) { - log_command_frame(CmdFrm); - } + if (!RspFrm) + return 0; - if(RspFrm) - atomic_set(&firesat->avc_reply_received, 0); - - while (packet_ok == 0 && num_tries < 6) { - num_tries++; - packet_ok = 1; - packet = hpsb_make_writepacket(ne->host, ne->nodeid, - COMMAND_REGISTER, - (quadlet_t*)CmdFrm, - CmdFrm->length); - hpsb_set_packet_complete_task(packet, - (void (*)(void*))avc_free_packet, - packet); - hpsb_node_fill_packet(ne, packet); - - if (hpsb_send_packet(packet) < 0) { - avc_free_packet(packet); - atomic_set(&firesat->avc_reply_received, 1); - printk(KERN_ERR "%s: send failed!\n",__func__); - return -EIO; - } + /* + * AV/C specs say that answers should be sent within 150 ms. + * Time out after 200 ms. + */ + if (wait_event_timeout(firesat->avc_wait, + firesat->avc_reply_received, + HZ / 5) != 0) { + memcpy(RspFrm, firesat->respfrm, firesat->resp_length); + RspFrm->length = firesat->resp_length; - if(RspFrm) { - // AV/C specs say that answers should be send within - // 150 ms so let's time out after 200 ms - if (wait_event_timeout(firesat->avc_wait, - atomic_read(&firesat->avc_reply_received) == 1, - HZ / 5) == 0) { - packet_ok = 0; - } - else { - memcpy(RspFrm, firesat->respfrm, - firesat->resp_length); - RspFrm->length = firesat->resp_length; - if (avc_comm_debug > 0) { - log_response_frame(RspFrm); - } - } + return 0; } } - if (packet_ok == 0) { - printk(KERN_ERR "%s: AV/C response timed out 6 times.\n", - __func__); - return -ETIMEDOUT; - } - - return 0; + dev_err(&firesat->ud->device, "FCP response timed out\n"); + return -ETIMEDOUT; } -int AVCWrite(struct firesat*firesat, const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm) +static int avc_write(struct firesat *firesat, + const AVCCmdFrm *CmdFrm, AVCRspFrm *RspFrm) { int ret; if (mutex_lock_interruptible(&firesat->avc_mutex)) return -EINTR; - ret = __AVCWrite(firesat, CmdFrm, RspFrm); + ret = __avc_write(firesat, CmdFrm, RspFrm); mutex_unlock(&firesat->avc_mutex); return ret; } -int AVCRecv(struct firesat *firesat, u8 *data, size_t length) +int avc_recv(struct firesat *firesat, u8 *data, size_t length) { AVCRspFrm *RspFrm = (AVCRspFrm *)data; @@ -260,87 +93,64 @@ int AVCRecv(struct firesat *firesat, u8 *data, size_t length) RspFrm->operand[2] == SFE_VENDOR_DE_COMPANYID_2 && RspFrm->operand[3] == SFE_VENDOR_OPCODE_REGISTER_REMOTE_CONTROL) { if (RspFrm->resp == CHANGED) { - firesat_handle_rc(RspFrm->operand[4] << 8 | - RspFrm->operand[5]); + firesat_handle_rc(firesat, + RspFrm->operand[4] << 8 | RspFrm->operand[5]); schedule_work(&firesat->remote_ctrl_work); } else if (RspFrm->resp != INTERIM) { - printk(KERN_INFO "firedtv: remote control result = " - "%d\n", RspFrm->resp); + dev_info(&firesat->ud->device, + "remote control result = %d\n", RspFrm->resp); } return 0; } - if(atomic_read(&firesat->avc_reply_received) == 1) { - printk(KERN_ERR "%s: received out-of-order AVC response, " - "ignored\n",__func__); - return -EINVAL; + if (firesat->avc_reply_received) { + dev_err(&firesat->ud->device, + "received out-of-order AVC response, ignored\n"); + return -EIO; } -// AVCRspFrm *resp=(AVCRspFrm *)data; -// int k; - -// printk(KERN_INFO "resp=0x%x\n",resp->resp); -// printk(KERN_INFO "cts=0x%x\n",resp->cts); -// printk(KERN_INFO "suid=0x%x\n",resp->suid); -// printk(KERN_INFO "sutyp=0x%x\n",resp->sutyp); -// printk(KERN_INFO "opcode=0x%x\n",resp->opcode); -// printk(KERN_INFO "length=%d\n",resp->length); -// for(k=0;k<2;k++) -// printk(KERN_INFO "operand[%d]=%02x\n",k,resp->operand[k]); + memcpy(firesat->respfrm, data, length); + firesat->resp_length = length; - memcpy(firesat->respfrm,data,length); - firesat->resp_length=length; - - atomic_set(&firesat->avc_reply_received, 1); + firesat->avc_reply_received = true; wake_up(&firesat->avc_wait); return 0; } -// tuning command for setting the relative LNB frequency (not supported by the AVC standard) -static void AVCTuner_tuneQPSK(struct firesat *firesat, struct dvb_frontend_parameters *params, AVCCmdFrm *CmdFrm) { - - memset(CmdFrm, 0, sizeof(AVCCmdFrm)); - - CmdFrm->cts = AVC; - CmdFrm->ctype = CONTROL; - CmdFrm->sutyp = 0x5; - CmdFrm->suid = firesat->subunit; +/* + * tuning command for setting the relative LNB frequency + * (not supported by the AVC standard) + */ +static void avc_tuner_tuneqpsk(struct firesat *firesat, + struct dvb_frontend_parameters *params, AVCCmdFrm *CmdFrm) +{ CmdFrm->opcode = VENDOR; - CmdFrm->operand[0]=SFE_VENDOR_DE_COMPANYID_0; - CmdFrm->operand[1]=SFE_VENDOR_DE_COMPANYID_1; - CmdFrm->operand[2]=SFE_VENDOR_DE_COMPANYID_2; - CmdFrm->operand[3]=SFE_VENDOR_OPCODE_TUNE_QPSK; - - printk(KERN_INFO "%s: tuning to frequency %u\n",__func__,params->frequency); - - CmdFrm->operand[4] = (params->frequency >> 24) & 0xFF; - CmdFrm->operand[5] = (params->frequency >> 16) & 0xFF; - CmdFrm->operand[6] = (params->frequency >> 8) & 0xFF; - CmdFrm->operand[7] = params->frequency & 0xFF; + CmdFrm->operand[0] = SFE_VENDOR_DE_COMPANYID_0; + CmdFrm->operand[1] = SFE_VENDOR_DE_COMPANYID_1; + CmdFrm->operand[2] = SFE_VENDOR_DE_COMPANYID_2; + CmdFrm->operand[3] = SFE_VENDOR_OPCODE_TUNE_QPSK; - printk(KERN_INFO "%s: symbol rate = %uBd\n",__func__,params->u.qpsk.symbol_rate); + CmdFrm->operand[4] = (params->frequency >> 24) & 0xff; + CmdFrm->operand[5] = (params->frequency >> 16) & 0xff; + CmdFrm->operand[6] = (params->frequency >> 8) & 0xff; + CmdFrm->operand[7] = params->frequency & 0xff; - CmdFrm->operand[8] = ((params->u.qpsk.symbol_rate/1000) >> 8) & 0xFF; - CmdFrm->operand[9] = (params->u.qpsk.symbol_rate/1000) & 0xFF; + CmdFrm->operand[8] = ((params->u.qpsk.symbol_rate / 1000) >> 8) & 0xff; + CmdFrm->operand[9] = (params->u.qpsk.symbol_rate / 1000) & 0xff; switch(params->u.qpsk.fec_inner) { case FEC_1_2: - CmdFrm->operand[10] = 0x1; - break; + CmdFrm->operand[10] = 0x1; break; case FEC_2_3: - CmdFrm->operand[10] = 0x2; - break; + CmdFrm->operand[10] = 0x2; break; case FEC_3_4: - CmdFrm->operand[10] = 0x3; - break; + CmdFrm->operand[10] = 0x3; break; case FEC_5_6: - CmdFrm->operand[10] = 0x4; - break; + CmdFrm->operand[10] = 0x4; break; case FEC_7_8: - CmdFrm->operand[10] = 0x5; - break; + CmdFrm->operand[10] = 0x5; break; case FEC_4_5: case FEC_8_9: case FEC_AUTO: @@ -348,278 +158,287 @@ static void AVCTuner_tuneQPSK(struct firesat *firesat, struct dvb_frontend_param CmdFrm->operand[10] = 0x0; } - if(firesat->voltage == 0xff) + if (firesat->voltage == 0xff) CmdFrm->operand[11] = 0xff; + else if (firesat->voltage == SEC_VOLTAGE_18) /* polarisation */ + CmdFrm->operand[11] = 0; else - CmdFrm->operand[11] = (firesat->voltage==SEC_VOLTAGE_18)?0:1; // polarisation - if(firesat->tone == 0xff) + CmdFrm->operand[11] = 1; + + if (firesat->tone == 0xff) CmdFrm->operand[12] = 0xff; + else if (firesat->tone == SEC_TONE_ON) /* band */ + CmdFrm->operand[12] = 1; else - CmdFrm->operand[12] = (firesat->tone==SEC_TONE_ON)?1:0; // band + CmdFrm->operand[12] = 0; if (firesat->type == FireSAT_DVB_S2) { CmdFrm->operand[13] = 0x1; - CmdFrm->operand[14] = 0xFF; - CmdFrm->operand[15] = 0xFF; + CmdFrm->operand[14] = 0xff; + CmdFrm->operand[15] = 0xff; + CmdFrm->length = 20; + } else { + CmdFrm->length = 16; } +} + +static void avc_tuner_dsd_dvb_c(struct dvb_frontend_parameters *params, + AVCCmdFrm *CmdFrm) +{ + M_VALID_FLAGS flags; - CmdFrm->length = 16; + flags.Bits.Modulation = params->u.qam.modulation != QAM_AUTO; + flags.Bits.FEC_inner = params->u.qam.fec_inner != FEC_AUTO; + flags.Bits.FEC_outer = 0; + flags.Bits.Symbol_Rate = 1; + flags.Bits.Frequency = 1; + flags.Bits.Orbital_Pos = 0; + flags.Bits.Polarisation = 0; + flags.Bits.reserved_fields = 0; + flags.Bits.reserved1 = 0; + flags.Bits.Network_ID = 0; + + CmdFrm->opcode = DSD; + + CmdFrm->operand[0] = 0; /* source plug */ + CmdFrm->operand[1] = 0xd2; /* subfunction replace */ + CmdFrm->operand[2] = 0x20; /* system id = DVB */ + CmdFrm->operand[3] = 0x00; /* antenna number */ + /* system_specific_multiplex selection_length */ + CmdFrm->operand[4] = 0x11; + CmdFrm->operand[5] = flags.Valid_Word.ByteHi; /* valid_flags [0] */ + CmdFrm->operand[6] = flags.Valid_Word.ByteLo; /* valid_flags [1] */ + CmdFrm->operand[7] = 0x00; + CmdFrm->operand[8] = 0x00; + CmdFrm->operand[9] = 0x00; + CmdFrm->operand[10] = 0x00; + + CmdFrm->operand[11] = + (((params->frequency / 4000) >> 16) & 0xff) | (2 << 6); + CmdFrm->operand[12] = + ((params->frequency / 4000) >> 8) & 0xff; + CmdFrm->operand[13] = (params->frequency / 4000) & 0xff; + CmdFrm->operand[14] = + ((params->u.qpsk.symbol_rate / 1000) >> 12) & 0xff; + CmdFrm->operand[15] = + ((params->u.qpsk.symbol_rate / 1000) >> 4) & 0xff; + CmdFrm->operand[16] = + ((params->u.qpsk.symbol_rate / 1000) << 4) & 0xf0; + CmdFrm->operand[17] = 0x00; + + switch (params->u.qpsk.fec_inner) { + case FEC_1_2: + CmdFrm->operand[18] = 0x1; break; + case FEC_2_3: + CmdFrm->operand[18] = 0x2; break; + case FEC_3_4: + CmdFrm->operand[18] = 0x3; break; + case FEC_5_6: + CmdFrm->operand[18] = 0x4; break; + case FEC_7_8: + CmdFrm->operand[18] = 0x5; break; + case FEC_8_9: + CmdFrm->operand[18] = 0x6; break; + case FEC_4_5: + CmdFrm->operand[18] = 0x8; break; + case FEC_AUTO: + default: + CmdFrm->operand[18] = 0x0; + } + switch (params->u.qam.modulation) { + case QAM_16: + CmdFrm->operand[19] = 0x08; break; + case QAM_32: + CmdFrm->operand[19] = 0x10; break; + case QAM_64: + CmdFrm->operand[19] = 0x18; break; + case QAM_128: + CmdFrm->operand[19] = 0x20; break; + case QAM_256: + CmdFrm->operand[19] = 0x28; break; + case QAM_AUTO: + default: + CmdFrm->operand[19] = 0x00; + } + CmdFrm->operand[20] = 0x00; + CmdFrm->operand[21] = 0x00; + /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */ + CmdFrm->operand[22] = 0x00; + + CmdFrm->length = 28; } -int AVCTuner_DSD(struct firesat *firesat, struct dvb_frontend_parameters *params, __u8 *status) { +static void avc_tuner_dsd_dvb_t(struct dvb_frontend_parameters *params, + AVCCmdFrm *CmdFrm) +{ + M_VALID_FLAGS flags; + + flags.Bits_T.GuardInterval = + params->u.ofdm.guard_interval != GUARD_INTERVAL_AUTO; + flags.Bits_T.CodeRateLPStream = + params->u.ofdm.code_rate_LP != FEC_AUTO; + flags.Bits_T.CodeRateHPStream = + params->u.ofdm.code_rate_HP != FEC_AUTO; + flags.Bits_T.HierarchyInfo = + params->u.ofdm.hierarchy_information != HIERARCHY_AUTO; + flags.Bits_T.Constellation = + params->u.ofdm.constellation != QAM_AUTO; + flags.Bits_T.Bandwidth = + params->u.ofdm.bandwidth != BANDWIDTH_AUTO; + flags.Bits_T.CenterFrequency = 1; + flags.Bits_T.reserved1 = 0; + flags.Bits_T.reserved2 = 0; + flags.Bits_T.OtherFrequencyFlag = 0; + flags.Bits_T.TransmissionMode = + params->u.ofdm.transmission_mode != TRANSMISSION_MODE_AUTO; + flags.Bits_T.NetworkId = 0; + + CmdFrm->opcode = DSD; + + CmdFrm->operand[0] = 0; /* source plug */ + CmdFrm->operand[1] = 0xd2; /* subfunction replace */ + CmdFrm->operand[2] = 0x20; /* system id = DVB */ + CmdFrm->operand[3] = 0x00; /* antenna number */ + /* system_specific_multiplex selection_length */ + CmdFrm->operand[4] = 0x0c; + CmdFrm->operand[5] = flags.Valid_Word.ByteHi; /* valid_flags [0] */ + CmdFrm->operand[6] = flags.Valid_Word.ByteLo; /* valid_flags [1] */ + CmdFrm->operand[7] = 0x0; + CmdFrm->operand[8] = (params->frequency / 10) >> 24; + CmdFrm->operand[9] = ((params->frequency / 10) >> 16) & 0xff; + CmdFrm->operand[10] = ((params->frequency / 10) >> 8) & 0xff; + CmdFrm->operand[11] = (params->frequency / 10) & 0xff; + + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_7_MHZ: + CmdFrm->operand[12] = 0x20; break; + case BANDWIDTH_8_MHZ: + case BANDWIDTH_6_MHZ: /* not defined by AVC spec */ + case BANDWIDTH_AUTO: + default: + CmdFrm->operand[12] = 0x00; + } + switch (params->u.ofdm.constellation) { + case QAM_16: + CmdFrm->operand[13] = 1 << 6; break; + case QAM_64: + CmdFrm->operand[13] = 2 << 6; break; + case QPSK: + default: + CmdFrm->operand[13] = 0x00; + } + switch (params->u.ofdm.hierarchy_information) { + case HIERARCHY_1: + CmdFrm->operand[13] |= 1 << 3; break; + case HIERARCHY_2: + CmdFrm->operand[13] |= 2 << 3; break; + case HIERARCHY_4: + CmdFrm->operand[13] |= 3 << 3; break; + case HIERARCHY_AUTO: + case HIERARCHY_NONE: + default: + break; + } + switch (params->u.ofdm.code_rate_HP) { + case FEC_2_3: + CmdFrm->operand[13] |= 1; break; + case FEC_3_4: + CmdFrm->operand[13] |= 2; break; + case FEC_5_6: + CmdFrm->operand[13] |= 3; break; + case FEC_7_8: + CmdFrm->operand[13] |= 4; break; + case FEC_1_2: + default: + break; + } + switch (params->u.ofdm.code_rate_LP) { + case FEC_2_3: + CmdFrm->operand[14] = 1 << 5; break; + case FEC_3_4: + CmdFrm->operand[14] = 2 << 5; break; + case FEC_5_6: + CmdFrm->operand[14] = 3 << 5; break; + case FEC_7_8: + CmdFrm->operand[14] = 4 << 5; break; + case FEC_1_2: + default: + CmdFrm->operand[14] = 0x00; break; + } + switch (params->u.ofdm.guard_interval) { + case GUARD_INTERVAL_1_16: + CmdFrm->operand[14] |= 1 << 3; break; + case GUARD_INTERVAL_1_8: + CmdFrm->operand[14] |= 2 << 3; break; + case GUARD_INTERVAL_1_4: + CmdFrm->operand[14] |= 3 << 3; break; + case GUARD_INTERVAL_1_32: + case GUARD_INTERVAL_AUTO: + default: + break; + } + switch (params->u.ofdm.transmission_mode) { + case TRANSMISSION_MODE_8K: + CmdFrm->operand[14] |= 1 << 1; break; + case TRANSMISSION_MODE_2K: + case TRANSMISSION_MODE_AUTO: + default: + break; + } + + CmdFrm->operand[15] = 0x00; /* network_ID[0] */ + CmdFrm->operand[16] = 0x00; /* network_ID[1] */ + /* Nr_of_dsd_sel_specs = 0 -> no PIDs are transmitted */ + CmdFrm->operand[17] = 0x00; + + CmdFrm->length = 24; +} + +int avc_tuner_dsd(struct firesat *firesat, + struct dvb_frontend_parameters *params) +{ AVCCmdFrm CmdFrm; AVCRspFrm RspFrm; - M_VALID_FLAGS flags; - int k; - -// printk(KERN_INFO "%s\n", __func__); - - if (firesat->type == FireSAT_DVB_S || firesat->type == FireSAT_DVB_S2) - AVCTuner_tuneQPSK(firesat, params, &CmdFrm); - else { - if(firesat->type == FireSAT_DVB_T) { - flags.Bits_T.GuardInterval = (params->u.ofdm.guard_interval != GUARD_INTERVAL_AUTO); - flags.Bits_T.CodeRateLPStream = (params->u.ofdm.code_rate_LP != FEC_AUTO); - flags.Bits_T.CodeRateHPStream = (params->u.ofdm.code_rate_HP != FEC_AUTO); - flags.Bits_T.HierarchyInfo = (params->u.ofdm.hierarchy_information != HIERARCHY_AUTO); - flags.Bits_T.Constellation = (params->u.ofdm.constellation != QAM_AUTO); - flags.Bits_T.Bandwidth = (params->u.ofdm.bandwidth != BANDWIDTH_AUTO); - flags.Bits_T.CenterFrequency = 1; - flags.Bits_T.reserved1 = 0; - flags.Bits_T.reserved2 = 0; - flags.Bits_T.OtherFrequencyFlag = 0; - flags.Bits_T.TransmissionMode = (params->u.ofdm.transmission_mode != TRANSMISSION_MODE_AUTO); - flags.Bits_T.NetworkId = 0; - } else { - flags.Bits.Modulation = - (params->u.qam.modulation != QAM_AUTO); - flags.Bits.FEC_inner = - (params->u.qam.fec_inner != FEC_AUTO); - flags.Bits.FEC_outer = 0; - flags.Bits.Symbol_Rate = 1; - flags.Bits.Frequency = 1; - flags.Bits.Orbital_Pos = 0; - flags.Bits.Polarisation = 0; - flags.Bits.reserved_fields = 0; - flags.Bits.reserved1 = 0; - flags.Bits.Network_ID = 0; - } - memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); - - CmdFrm.cts = AVC; - CmdFrm.ctype = CONTROL; - CmdFrm.sutyp = 0x5; - CmdFrm.suid = firesat->subunit; - CmdFrm.opcode = DSD; - - CmdFrm.operand[0] = 0; // source plug - CmdFrm.operand[1] = 0xD2; // subfunction replace - CmdFrm.operand[2] = 0x20; // system id = DVB - CmdFrm.operand[3] = 0x00; // antenna number - // system_specific_multiplex selection_length - CmdFrm.operand[4] = (firesat->type == FireSAT_DVB_T)?0x0c:0x11; - CmdFrm.operand[5] = flags.Valid_Word.ByteHi; // valid_flags [0] - CmdFrm.operand[6] = flags.Valid_Word.ByteLo; // valid_flags [1] - - if(firesat->type == FireSAT_DVB_T) { - CmdFrm.operand[7] = 0x0; - CmdFrm.operand[8] = (params->frequency/10) >> 24; - CmdFrm.operand[9] = - ((params->frequency/10) >> 16) & 0xFF; - CmdFrm.operand[10] = - ((params->frequency/10) >> 8) & 0xFF; - CmdFrm.operand[11] = (params->frequency/10) & 0xFF; - switch(params->u.ofdm.bandwidth) { - case BANDWIDTH_7_MHZ: - CmdFrm.operand[12] = 0x20; - break; - case BANDWIDTH_8_MHZ: - case BANDWIDTH_6_MHZ: // not defined by AVC spec - case BANDWIDTH_AUTO: - default: - CmdFrm.operand[12] = 0x00; - } - switch(params->u.ofdm.constellation) { - case QAM_16: - CmdFrm.operand[13] = 1 << 6; - break; - case QAM_64: - CmdFrm.operand[13] = 2 << 6; - break; - case QPSK: - default: - CmdFrm.operand[13] = 0x00; - } - switch(params->u.ofdm.hierarchy_information) { - case HIERARCHY_1: - CmdFrm.operand[13] |= 1 << 3; - break; - case HIERARCHY_2: - CmdFrm.operand[13] |= 2 << 3; - break; - case HIERARCHY_4: - CmdFrm.operand[13] |= 3 << 3; - break; - case HIERARCHY_AUTO: - case HIERARCHY_NONE: - default: - break; - } - switch(params->u.ofdm.code_rate_HP) { - case FEC_2_3: - CmdFrm.operand[13] |= 1; - break; - case FEC_3_4: - CmdFrm.operand[13] |= 2; - break; - case FEC_5_6: - CmdFrm.operand[13] |= 3; - break; - case FEC_7_8: - CmdFrm.operand[13] |= 4; - break; - case FEC_1_2: - default: - break; - } - switch(params->u.ofdm.code_rate_LP) { - case FEC_2_3: - CmdFrm.operand[14] = 1 << 5; - break; - case FEC_3_4: - CmdFrm.operand[14] = 2 << 5; - break; - case FEC_5_6: - CmdFrm.operand[14] = 3 << 5; - break; - case FEC_7_8: - CmdFrm.operand[14] = 4 << 5; - break; - case FEC_1_2: - default: - CmdFrm.operand[14] = 0x00; - break; - } - switch(params->u.ofdm.guard_interval) { - case GUARD_INTERVAL_1_16: - CmdFrm.operand[14] |= 1 << 3; - break; - case GUARD_INTERVAL_1_8: - CmdFrm.operand[14] |= 2 << 3; - break; - case GUARD_INTERVAL_1_4: - CmdFrm.operand[14] |= 3 << 3; - break; - case GUARD_INTERVAL_1_32: - case GUARD_INTERVAL_AUTO: - default: - break; - } - switch(params->u.ofdm.transmission_mode) { - case TRANSMISSION_MODE_8K: - CmdFrm.operand[14] |= 1 << 1; - break; - case TRANSMISSION_MODE_2K: - case TRANSMISSION_MODE_AUTO: - default: - break; - } - - CmdFrm.operand[15] = 0x00; // network_ID[0] - CmdFrm.operand[16] = 0x00; // network_ID[1] - CmdFrm.operand[17] = 0x00; // Nr_of_dsd_sel_specs = 0 - > No PIDs are transmitted - - CmdFrm.length = 24; - } else { - CmdFrm.operand[7] = 0x00; - CmdFrm.operand[8] = 0x00; - CmdFrm.operand[9] = 0x00; - CmdFrm.operand[10] = 0x00; - - CmdFrm.operand[11] = - (((params->frequency/4000) >> 16) & 0xFF) | (2 << 6); - CmdFrm.operand[12] = - ((params->frequency/4000) >> 8) & 0xFF; - CmdFrm.operand[13] = (params->frequency/4000) & 0xFF; - CmdFrm.operand[14] = - ((params->u.qpsk.symbol_rate/1000) >> 12) & 0xFF; - CmdFrm.operand[15] = - ((params->u.qpsk.symbol_rate/1000) >> 4) & 0xFF; - CmdFrm.operand[16] = - ((params->u.qpsk.symbol_rate/1000) << 4) & 0xF0; - CmdFrm.operand[17] = 0x00; - switch(params->u.qpsk.fec_inner) { - case FEC_1_2: - CmdFrm.operand[18] = 0x1; - break; - case FEC_2_3: - CmdFrm.operand[18] = 0x2; - break; - case FEC_3_4: - CmdFrm.operand[18] = 0x3; - break; - case FEC_5_6: - CmdFrm.operand[18] = 0x4; - break; - case FEC_7_8: - CmdFrm.operand[18] = 0x5; - break; - case FEC_8_9: - CmdFrm.operand[18] = 0x6; - break; - case FEC_4_5: - CmdFrm.operand[18] = 0x8; - break; - case FEC_AUTO: - default: - CmdFrm.operand[18] = 0x0; - } - switch(params->u.qam.modulation) { - case QAM_16: - CmdFrm.operand[19] = 0x08; // modulation - break; - case QAM_32: - CmdFrm.operand[19] = 0x10; // modulation - break; - case QAM_64: - CmdFrm.operand[19] = 0x18; // modulation - break; - case QAM_128: - CmdFrm.operand[19] = 0x20; // modulation - break; - case QAM_256: - CmdFrm.operand[19] = 0x28; // modulation - break; - case QAM_AUTO: - default: - CmdFrm.operand[19] = 0x00; // modulation - } - CmdFrm.operand[20] = 0x00; - CmdFrm.operand[21] = 0x00; - CmdFrm.operand[22] = 0x00; // Nr_of_dsd_sel_specs = 0 - > No PIDs are transmitted - - CmdFrm.length=28; - } - } // AVCTuner_DSD_direct + memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); - if((k=AVCWrite(firesat,&CmdFrm,&RspFrm))) - return k; + CmdFrm.cts = AVC; + CmdFrm.ctype = CONTROL; + CmdFrm.sutyp = 0x5; + CmdFrm.suid = firesat->subunit; - mdelay(500); + switch (firesat->type) { + case FireSAT_DVB_S: + case FireSAT_DVB_S2: + avc_tuner_tuneqpsk(firesat, params, &CmdFrm); break; + case FireSAT_DVB_C: + avc_tuner_dsd_dvb_c(params, &CmdFrm); break; + case FireSAT_DVB_T: + avc_tuner_dsd_dvb_t(params, &CmdFrm); break; + default: + BUG(); + } + if (avc_write(firesat, &CmdFrm, &RspFrm) < 0) + return -EIO; + + msleep(500); +#if 0 + /* FIXME: */ + /* u8 *status was an out-parameter of avc_tuner_dsd, unused by caller */ if(status) *status=RspFrm.operand[2]; +#endif return 0; } -int AVCTuner_SetPIDs(struct firesat *firesat, unsigned char pidc, u16 pid[]) +int avc_tuner_set_pids(struct firesat *firesat, unsigned char pidc, u16 pid[]) { AVCCmdFrm CmdFrm; AVCRspFrm RspFrm; - int pos,k; + int pos, k; - if(pidc > 16 && pidc != 0xFF) + if (pidc > 16 && pidc != 0xff) return -EINVAL; memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); @@ -637,9 +456,9 @@ int AVCTuner_SetPIDs(struct firesat *firesat, unsigned char pidc, u16 pid[]) CmdFrm.operand[4] = 0x00; // system_specific_multiplex selection_length CmdFrm.operand[5] = pidc; // Nr_of_dsd_sel_specs - pos=6; - if(pidc != 0xFF) { - for(k=0;k<pidc;k++) { + pos = 6; + if (pidc != 0xff) + for (k = 0; k < pidc; k++) { CmdFrm.operand[pos++] = 0x13; // flowfunction relay CmdFrm.operand[pos++] = 0x80; // dsd_sel_spec_valid_flags -> PID CmdFrm.operand[pos++] = (pid[k] >> 8) & 0x1F; @@ -647,25 +466,20 @@ int AVCTuner_SetPIDs(struct firesat *firesat, unsigned char pidc, u16 pid[]) CmdFrm.operand[pos++] = 0x00; // tableID CmdFrm.operand[pos++] = 0x00; // filter_length } - } - CmdFrm.length = pos+3; - if((pos+3)%4) - CmdFrm.length += 4 - ((pos+3)%4); + CmdFrm.length = ALIGN(3 + pos, 4); - if((k=AVCWrite(firesat,&CmdFrm,&RspFrm))) - return k; + if (avc_write(firesat, &CmdFrm, &RspFrm) < 0) + return -EIO; - mdelay(50); + msleep(50); return 0; } -int AVCTuner_GetTS(struct firesat *firesat){ +int avc_tuner_get_ts(struct firesat *firesat) +{ AVCCmdFrm CmdFrm; AVCRspFrm RspFrm; - int k; - - //printk(KERN_INFO "%s\n", __func__); memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); @@ -688,14 +502,14 @@ int AVCTuner_GetTS(struct firesat *firesat){ CmdFrm.length = (firesat->type == FireSAT_DVB_T)?24:28; - if ((k=AVCWrite(firesat, &CmdFrm, &RspFrm))) - return k; + if (avc_write(firesat, &CmdFrm, &RspFrm) < 0) + return -EIO; - mdelay(250); + msleep(250); return 0; } -int AVCIdentifySubunit(struct firesat *firesat) +int avc_identify_subunit(struct firesat *firesat) { AVCCmdFrm CmdFrm; AVCRspFrm RspFrm; @@ -718,22 +532,21 @@ int AVCIdentifySubunit(struct firesat *firesat) CmdFrm.length=12; - if(AVCWrite(firesat,&CmdFrm,&RspFrm)<0) + if (avc_write(firesat, &CmdFrm, &RspFrm) < 0) return -EIO; - if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) { - printk(KERN_ERR "%s: AVCWrite returned error code %d\n", - __func__, RspFrm.resp); - return -EINVAL; - } - if(((RspFrm.operand[3] << 8) + RspFrm.operand[4]) != 8) { - printk(KERN_ERR "%s: Invalid response length\n", __func__); + if ((RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) || + (RspFrm.operand[3] << 8) + RspFrm.operand[4] != 8) { + dev_err(&firesat->ud->device, + "cannot read subunit identifier\n"); return -EINVAL; } return 0; } -int AVCTunerStatus(struct firesat *firesat, ANTENNA_INPUT_INFO *antenna_input_info) { +int avc_tuner_status(struct firesat *firesat, + ANTENNA_INPUT_INFO *antenna_input_info) +{ AVCCmdFrm CmdFrm; AVCRspFrm RspFrm; int length; @@ -754,37 +567,32 @@ int AVCTunerStatus(struct firesat *firesat, ANTENNA_INPUT_INFO *antenna_input_in CmdFrm.operand[5]=0x00; CmdFrm.operand[6]=0x00; CmdFrm.length=12; - if (AVCWrite(firesat,&CmdFrm,&RspFrm) < 0) + + if (avc_write(firesat, &CmdFrm, &RspFrm) < 0) return -EIO; - if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) { - printk(KERN_ERR "%s: AVCWrite returned code %d\n", - __func__, RspFrm.resp); + if (RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) { + dev_err(&firesat->ud->device, "cannot read tuner status\n"); return -EINVAL; } length = RspFrm.operand[9]; - if(RspFrm.operand[1] == 0x10 && length == sizeof(ANTENNA_INPUT_INFO)) - { - memcpy(antenna_input_info, &RspFrm.operand[10], - sizeof(ANTENNA_INPUT_INFO)); - return 0; + if (RspFrm.operand[1] != 0x10 || length != sizeof(ANTENNA_INPUT_INFO)) { + dev_err(&firesat->ud->device, "got invalid tuner status\n"); + return -EINVAL; } - printk(KERN_ERR "%s: invalid tuner status (op=%d,length=%d) returned " - "from AVC\n", __func__, RspFrm.operand[1], length); - return -EINVAL; + + memcpy(antenna_input_info, &RspFrm.operand[10], length); + return 0; } -int AVCLNBControl(struct firesat *firesat, char voltage, char burst, - char conttone, char nrdiseq, - struct dvb_diseqc_master_cmd *diseqcmd) +int avc_lnb_control(struct firesat *firesat, char voltage, char burst, + char conttone, char nrdiseq, + struct dvb_diseqc_master_cmd *diseqcmd) { AVCCmdFrm CmdFrm; AVCRspFrm RspFrm; - int i,j; - - printk(KERN_INFO "%s: voltage = %x, burst = %x, conttone = %x\n", - __func__, voltage, burst, conttone); + int i, j, k; memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); @@ -804,85 +612,33 @@ int AVCLNBControl(struct firesat *firesat, char voltage, char burst, i=6; - for(j=0;j<nrdiseq;j++) { - int k; - printk(KERN_INFO "%s: diseq %d len %x\n", - __func__, j, diseqcmd[j].msg_len); - CmdFrm.operand[i++]=diseqcmd[j].msg_len; + for (j = 0; j < nrdiseq; j++) { + CmdFrm.operand[i++] = diseqcmd[j].msg_len; - for(k=0;k<diseqcmd[j].msg_len;k++) { - printk(KERN_INFO "%s: diseq %d msg[%d] = %x\n", - __func__, j, k, diseqcmd[j].msg[k]); - CmdFrm.operand[i++]=diseqcmd[j].msg[k]; - } + for (k = 0; k < diseqcmd[j].msg_len; k++) + CmdFrm.operand[i++] = diseqcmd[j].msg[k]; } CmdFrm.operand[i++]=burst; CmdFrm.operand[i++]=conttone; - CmdFrm.length=i+3; - if((i+3)%4) - CmdFrm.length += 4 - ((i+3)%4); + CmdFrm.length = ALIGN(3 + i, 4); -/* for(j=0;j<CmdFrm.length;j++) - printk(KERN_INFO "%s: CmdFrm.operand[%d]=0x%x\n",__func__,j,CmdFrm.operand[j]); - - printk(KERN_INFO "%s: cmdfrm.length = %u\n",__func__,CmdFrm.length); - */ - if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0) + if (avc_write(firesat, &CmdFrm, &RspFrm) < 0) return -EIO; - if(RspFrm.resp != ACCEPTED) { - printk(KERN_ERR "%s: AVCWrite returned code %d\n", - __func__, RspFrm.resp); - return -EINVAL; - } - - return 0; -} - -int AVCSubUnitInfo(struct firesat *firesat, char *subunitcount) -{ - AVCCmdFrm CmdFrm; - AVCRspFrm RspFrm; - - memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); - - CmdFrm.cts = AVC; - CmdFrm.ctype = STATUS; - CmdFrm.sutyp = 0x1f; - CmdFrm.suid = 0x7; - CmdFrm.opcode = SUBUNIT_Info; - - CmdFrm.operand[0] = 0x07; - CmdFrm.operand[1] = 0xff; - CmdFrm.operand[2] = 0xff; - CmdFrm.operand[3] = 0xff; - CmdFrm.operand[4] = 0xff; - - CmdFrm.length = 8; - - if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0) - return -EIO; - - if(RspFrm.resp != STABLE) { - printk(KERN_ERR "%s: AVCWrite returned code %d\n", - __func__, RspFrm.resp); + if (RspFrm.resp != ACCEPTED) { + dev_err(&firesat->ud->device, "LNB control failed\n"); return -EINVAL; } - if(subunitcount) - *subunitcount = (RspFrm.operand[1] & 0x7) + 1; - return 0; } -int AVCRegisterRemoteControl(struct firesat *firesat) +int avc_register_remote_control(struct firesat *firesat) { AVCCmdFrm CmdFrm; -// printk(KERN_INFO "%s\n",__func__); - memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); CmdFrm.cts = AVC; @@ -898,7 +654,7 @@ int AVCRegisterRemoteControl(struct firesat *firesat) CmdFrm.length = 8; - return AVCWrite(firesat, &CmdFrm, NULL); + return avc_write(firesat, &CmdFrm, NULL); } void avc_remote_ctrl_work(struct work_struct *work) @@ -907,12 +663,12 @@ void avc_remote_ctrl_work(struct work_struct *work) container_of(work, struct firesat, remote_ctrl_work); /* Should it be rescheduled in failure cases? */ - AVCRegisterRemoteControl(firesat); + avc_register_remote_control(firesat); } -int AVCTuner_Host2Ca(struct firesat *firesat) +#if 0 /* FIXME: unused */ +int avc_tuner_host2ca(struct firesat *firesat) { - AVCCmdFrm CmdFrm; AVCRspFrm RspFrm; @@ -933,37 +689,39 @@ int AVCTuner_Host2Ca(struct firesat *firesat) CmdFrm.operand[7] = 0; // length CmdFrm.length = 12; - if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0) + if (avc_write(firesat, &CmdFrm, &RspFrm) < 0) return -EIO; return 0; } +#endif static int get_ca_object_pos(AVCRspFrm *RspFrm) { int length = 1; - // Check length of length field + /* Check length of length field */ if (RspFrm->operand[7] & 0x80) - length = (RspFrm->operand[7] & 0x7F) + 1; + length = (RspFrm->operand[7] & 0x7f) + 1; return length + 7; } static int get_ca_object_length(AVCRspFrm *RspFrm) { +#if 0 /* FIXME: unused */ int size = 0; int i; - if (RspFrm->operand[7] & 0x80) { - for (i = 0; i < (RspFrm->operand[7] & 0x7F); i++) { + if (RspFrm->operand[7] & 0x80) + for (i = 0; i < (RspFrm->operand[7] & 0x7f); i++) { size <<= 8; size += RspFrm->operand[8 + i]; } - } +#endif return RspFrm->operand[7]; } -int avc_ca_app_info(struct firesat *firesat, char *app_info, int *length) +int avc_ca_app_info(struct firesat *firesat, char *app_info, unsigned int *len) { AVCCmdFrm CmdFrm; AVCRspFrm RspFrm; @@ -984,9 +742,10 @@ int avc_ca_app_info(struct firesat *firesat, char *app_info, int *length) CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag CmdFrm.length = 12; - if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0) + if (avc_write(firesat, &CmdFrm, &RspFrm) < 0) return -EIO; + /* FIXME: check response code and validate response data */ pos = get_ca_object_pos(&RspFrm); app_info[0] = (TAG_APP_INFO >> 16) & 0xFF; @@ -995,16 +754,16 @@ int avc_ca_app_info(struct firesat *firesat, char *app_info, int *length) app_info[3] = 6 + RspFrm.operand[pos + 4]; app_info[4] = 0x01; memcpy(&app_info[5], &RspFrm.operand[pos], 5 + RspFrm.operand[pos + 4]); - *length = app_info[3] + 4; + *len = app_info[3] + 4; return 0; } -int avc_ca_info(struct firesat *firesat, char *app_info, int *length) +int avc_ca_info(struct firesat *firesat, char *app_info, unsigned int *len) { AVCCmdFrm CmdFrm; AVCRspFrm RspFrm; - int pos; + /* int pos; FIXME: unused */ memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); CmdFrm.cts = AVC; @@ -1021,17 +780,17 @@ int avc_ca_info(struct firesat *firesat, char *app_info, int *length) CmdFrm.operand[5] = SFE_VENDOR_TAG_CA_APPLICATION_INFO; // ca tag CmdFrm.length = 12; - if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0) + if (avc_write(firesat, &CmdFrm, &RspFrm) < 0) return -EIO; - pos = get_ca_object_pos(&RspFrm); + /* pos = get_ca_object_pos(&RspFrm); FIXME: unused */ app_info[0] = (TAG_CA_INFO >> 16) & 0xFF; app_info[1] = (TAG_CA_INFO >> 8) & 0xFF; app_info[2] = (TAG_CA_INFO >> 0) & 0xFF; app_info[3] = 2; app_info[4] = app_info[5]; app_info[5] = app_info[6]; - *length = app_info[3] + 4; + *len = app_info[3] + 4; return 0; } @@ -1059,7 +818,7 @@ int avc_ca_reset(struct firesat *firesat) CmdFrm.operand[8] = 0; // force hardware reset CmdFrm.length = 12; - if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0) + if (avc_write(firesat, &CmdFrm, &RspFrm) < 0) return -EIO; return 0; @@ -1085,9 +844,8 @@ int avc_ca_pmt(struct firesat *firesat, char *msg, int length) CmdFrm.opcode = VENDOR; if (msg[0] != LIST_MANAGEMENT_ONLY) { - printk(KERN_INFO "%s: list_management %d not support. " - "Forcing list_management to \"only\" (3). \n", - __func__, msg[0]); + dev_info(&firesat->ud->device, + "forcing list_management to ONLY\n"); msg[0] = LIST_MANAGEMENT_ONLY; } // We take the cmd_id from the programme level only! @@ -1134,20 +892,17 @@ int avc_ca_pmt(struct firesat *firesat, char *msg, int length) read_pos = 6; write_pos = 22; if (program_info_length > 0) { -/* printk(KERN_INFO "Copying descriptors at programme level.\n"); */ pmt_cmd_id = msg[read_pos++]; - if (pmt_cmd_id != 1 && pmt_cmd_id !=4) { - printk(KERN_ERR "Invalid pmt_cmd_id=%d.\n", - pmt_cmd_id); - } + if (pmt_cmd_id != 1 && pmt_cmd_id != 4) + dev_err(&firesat->ud->device, + "invalid pmt_cmd_id %d\n", pmt_cmd_id); + memcpy(&CmdFrm.operand[write_pos], &msg[read_pos], program_info_length); read_pos += program_info_length; write_pos += program_info_length; } while (read_pos < length) { -/* printk(KERN_INFO "Copying descriptors at stream level for " */ -/* "stream type %d.\n", msg[read_pos]); */ CmdFrm.operand[write_pos++] = msg[read_pos++]; CmdFrm.operand[write_pos++] = msg[read_pos++]; CmdFrm.operand[write_pos++] = msg[read_pos++]; @@ -1160,10 +915,11 @@ int avc_ca_pmt(struct firesat *firesat, char *msg, int length) CmdFrm.operand[write_pos++] = es_info_length & 0xFF; if (es_info_length > 0) { pmt_cmd_id = msg[read_pos++]; - if (pmt_cmd_id != 1 && pmt_cmd_id !=4) { - printk(KERN_ERR "Invalid pmt_cmd_id=%d at " - "stream level.\n", pmt_cmd_id); - } + if (pmt_cmd_id != 1 && pmt_cmd_id != 4) + dev_err(&firesat->ud->device, + "invalid pmt_cmd_id %d " + "at stream level\n", pmt_cmd_id); + memcpy(&CmdFrm.operand[write_pos], &msg[read_pos], es_info_length); read_pos += es_info_length; @@ -1187,20 +943,18 @@ int avc_ca_pmt(struct firesat *firesat, char *msg, int length) CmdFrm.operand[write_pos - 2] = (crc32_csum >> 8) & 0xFF; CmdFrm.operand[write_pos - 1] = (crc32_csum >> 0) & 0xFF; - CmdFrm.length = write_pos + 3; - if ((write_pos + 3) % 4) - CmdFrm.length += 4 - ((write_pos + 3) % 4); + CmdFrm.length = ALIGN(3 + write_pos, 4); - if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0) + if (avc_write(firesat, &CmdFrm, &RspFrm) < 0) return -EIO; if (RspFrm.resp != ACCEPTED) { - printk(KERN_ERR "Answer to CA PMT was %d\n", RspFrm.resp); + dev_err(&firesat->ud->device, + "CA PMT failed with response 0x%x\n", RspFrm.resp); return -EFAULT; } return 0; - } int avc_ca_get_time_date(struct firesat *firesat, int *interval) @@ -1225,9 +979,11 @@ int avc_ca_get_time_date(struct firesat *firesat, int *interval) CmdFrm.operand[7] = 0; // length CmdFrm.length = 12; - if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0) + if (avc_write(firesat, &CmdFrm, &RspFrm) < 0) return -EIO; + /* FIXME: check response code and validate response data */ + *interval = RspFrm.operand[get_ca_object_pos(&RspFrm)]; return 0; @@ -1255,13 +1011,13 @@ int avc_ca_enter_menu(struct firesat *firesat) CmdFrm.operand[7] = 0; // length CmdFrm.length = 12; - if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0) + if (avc_write(firesat, &CmdFrm, &RspFrm) < 0) return -EIO; return 0; } -int avc_ca_get_mmi(struct firesat *firesat, char *mmi_object, int *length) +int avc_ca_get_mmi(struct firesat *firesat, char *mmi_object, unsigned int *len) { AVCCmdFrm CmdFrm; AVCRspFrm RspFrm; @@ -1283,11 +1039,13 @@ int avc_ca_get_mmi(struct firesat *firesat, char *mmi_object, int *length) CmdFrm.operand[7] = 0; // length CmdFrm.length = 12; - if(AVCWrite(firesat,&CmdFrm,&RspFrm) < 0) + if (avc_write(firesat, &CmdFrm, &RspFrm) < 0) return -EIO; - *length = get_ca_object_length(&RspFrm); - memcpy(mmi_object, &RspFrm.operand[get_ca_object_pos(&RspFrm)], *length); + /* FIXME: check response code and validate response data */ + + *len = get_ca_object_length(&RspFrm); + memcpy(mmi_object, &RspFrm.operand[get_ca_object_pos(&RspFrm)], *len); return 0; } diff --git a/drivers/media/dvb/firesat/avc_api.h b/drivers/media/dvb/firesat/avc_api.h index 66f419a..9d2efd8 100644 --- a/drivers/media/dvb/firesat/avc_api.h +++ b/drivers/media/dvb/firesat/avc_api.h @@ -26,15 +26,6 @@ **************************************************************/ #define LIST_MANAGEMENT_ONLY 0x03 -/************************************************************* - FCP Address range -**************************************************************/ - -#define RESPONSE_REGISTER 0xFFFFF0000D00ULL -#define COMMAND_REGISTER 0xFFFFF0000B00ULL -#define PCR_BASE_ADDRESS 0xFFFFF0000900ULL - - /************************************************************ definition of structures *************************************************************/ @@ -413,34 +404,29 @@ struct dvb_diseqc_master_cmd; struct dvb_frontend_parameters; struct firesat; -int AVCWrite(struct firesat *firesat, const AVCCmdFrm *CmdFrm, - AVCRspFrm *RspFrm); -int AVCRecv(struct firesat *firesat, u8 *data, size_t length); +int avc_recv(struct firesat *firesat, u8 *data, size_t length); int AVCTuner_DSIT(struct firesat *firesat, int Source_Plug, struct dvb_frontend_parameters *params, __u8 *status); -int AVCTunerStatus(struct firesat *firesat, +int avc_tuner_status(struct firesat *firesat, ANTENNA_INPUT_INFO *antenna_input_info); -int AVCTuner_DSD(struct firesat *firesat, - struct dvb_frontend_parameters *params, __u8 *status); -int AVCTuner_SetPIDs(struct firesat *firesat, unsigned char pidc, u16 pid[]); -int AVCTuner_GetTS(struct firesat *firesat); - -int AVCIdentifySubunit(struct firesat *firesat); -int AVCLNBControl(struct firesat *firesat, char voltage, char burst, +int avc_tuner_dsd(struct firesat *firesat, + struct dvb_frontend_parameters *params); +int avc_tuner_set_pids(struct firesat *firesat, unsigned char pidc, u16 pid[]); +int avc_tuner_get_ts(struct firesat *firesat); +int avc_identify_subunit(struct firesat *firesat); +int avc_lnb_control(struct firesat *firesat, char voltage, char burst, char conttone, char nrdiseq, struct dvb_diseqc_master_cmd *diseqcmd); -int AVCSubUnitInfo(struct firesat *firesat, char *subunitcount); void avc_remote_ctrl_work(struct work_struct *work); -int AVCRegisterRemoteControl(struct firesat *firesat); -int AVCTuner_Host2Ca(struct firesat *firesat); -int avc_ca_app_info(struct firesat *firesat, char *app_info, int *length); -int avc_ca_info(struct firesat *firesat, char *app_info, int *length); +int avc_register_remote_control(struct firesat *firesat); +int avc_ca_app_info(struct firesat *firesat, char *app_info, unsigned int *len); +int avc_ca_info(struct firesat *firesat, char *app_info, unsigned int *len); int avc_ca_reset(struct firesat *firesat); int avc_ca_pmt(struct firesat *firesat, char *app_info, int length); int avc_ca_get_time_date(struct firesat *firesat, int *interval); int avc_ca_enter_menu(struct firesat *firesat); -int avc_ca_get_mmi(struct firesat *firesat, char *mmi_object, int *length); +int avc_ca_get_mmi(struct firesat *firesat, char *mmi_object, unsigned int *len); #endif /* _AVC_API_H */ diff --git a/drivers/media/dvb/firesat/cmp.c b/drivers/media/dvb/firesat/cmp.c index d1bafba..8e98b81 100644 --- a/drivers/media/dvb/firesat/cmp.c +++ b/drivers/media/dvb/firesat/cmp.c @@ -10,37 +10,21 @@ * the License, or (at your option) any later version. */ +#include <linux/device.h> #include <linux/kernel.h> #include <linux/mutex.h> #include <linux/types.h> -#include <hosts.h> +#include <asm/byteorder.h> + #include <ieee1394.h> -#include <ieee1394_core.h> -#include <ieee1394_transactions.h> #include <nodemgr.h> #include "avc_api.h" #include "cmp.h" #include "firesat.h" -typedef struct _OPCR -{ - __u8 PTPConnCount : 6 ; // Point to point connect. counter - __u8 BrConnCount : 1 ; // Broadcast connection counter - __u8 OnLine : 1 ; // On Line - - __u8 ChNr : 6 ; // Channel number - __u8 Res : 2 ; // Reserved - - __u8 PayloadHi : 2 ; // Payoad high bits - __u8 OvhdID : 4 ; // Overhead ID - __u8 DataRate : 2 ; // Data Rate - - __u8 PayloadLo ; // Payoad low byte -} OPCR ; - -#define FIRESAT_SPEED IEEE1394_SPEED_400 +#define CMP_OUTPUT_PLUG_CONTROL_REG_0 0xfffff0000904ULL static int cmp_read(struct firesat *firesat, void *buf, u64 addr, size_t len) { @@ -49,151 +33,139 @@ static int cmp_read(struct firesat *firesat, void *buf, u64 addr, size_t len) if (mutex_lock_interruptible(&firesat->avc_mutex)) return -EINTR; - ret = hpsb_read(firesat->host, firesat->nodeentry->nodeid, - firesat->nodeentry->generation, addr, buf, len); + ret = hpsb_node_read(firesat->ud->ne, addr, buf, len); + if (ret < 0) + dev_err(&firesat->ud->device, "CMP: read I/O error\n"); mutex_unlock(&firesat->avc_mutex); return ret; } -static int cmp_lock(struct firesat *firesat, quadlet_t *data, u64 addr, - quadlet_t arg, int ext_tcode) +static int cmp_lock(struct firesat *firesat, void *data, u64 addr, __be32 arg, + int ext_tcode) { int ret; if (mutex_lock_interruptible(&firesat->avc_mutex)) return -EINTR; - ret = hpsb_lock(firesat->host, firesat->nodeentry->nodeid, - firesat->nodeentry->generation, - addr, ext_tcode, data, arg); + ret = hpsb_node_lock(firesat->ud->ne, addr, ext_tcode, data, + (__force quadlet_t)arg); + if (ret < 0) + dev_err(&firesat->ud->device, "CMP: lock I/O error\n"); mutex_unlock(&firesat->avc_mutex); return ret; } -//try establishing a point-to-point connection (may be interrupted by a busreset -int try_CMPEstablishPPconnection(struct firesat *firesat, int output_plug, int iso_channel) { - unsigned int BWU; //bandwidth to allocate +static inline u32 get_opcr(__be32 opcr, u32 mask, u32 shift) +{ + return (be32_to_cpu(opcr) >> shift) & mask; +} + +static inline void set_opcr(__be32 *opcr, u32 value, u32 mask, u32 shift) +{ + *opcr &= ~cpu_to_be32(mask << shift); + *opcr |= cpu_to_be32((value & mask) << shift); +} - quadlet_t old_oPCR,test_oPCR = 0x0; - u64 oPCR_address=0xfffff0000904ull+(output_plug << 2); - int result=cmp_read(firesat, &test_oPCR, oPCR_address, 4); +#define get_opcr_online(v) get_opcr((v), 0x1, 31) +#define get_opcr_p2p_connections(v) get_opcr((v), 0x3f, 24) +#define get_opcr_channel(v) get_opcr((v), 0x3f, 16) -/* printk(KERN_INFO "%s: nodeid = %d\n",__func__,firesat->nodeentry->nodeid); */ +#define set_opcr_p2p_connections(p, v) set_opcr((p), (v), 0x3f, 24) +#define set_opcr_channel(p, v) set_opcr((p), (v), 0x3f, 16) +#define set_opcr_data_rate(p, v) set_opcr((p), (v), 0x3, 14) +#define set_opcr_overhead_id(p, v) set_opcr((p), (v), 0xf, 10) - if (result < 0) { - printk("%s: cannot read oPCR\n", __func__); - return result; - } else { -/* printk(KERN_INFO "%s: oPCR = %08x\n",__func__,test_oPCR); */ - do { - OPCR *hilf= (OPCR*) &test_oPCR; - - if (!hilf->OnLine) { - printk("%s: Output offline; oPCR: %08x\n", __func__, test_oPCR); - return -EBUSY; - } else { - quadlet_t new_oPCR; - - old_oPCR=test_oPCR; - if (hilf->PTPConnCount) { - if (hilf->ChNr != iso_channel) { - printk("%s: Output plug has already connection on channel %u; cannot change it to channel %u\n",__func__,hilf->ChNr,iso_channel); - return -EBUSY; - } else - printk(KERN_INFO "%s: Overlaying existing connection; connection counter was: %u\n",__func__, hilf->PTPConnCount); - BWU=0; //we allocate no bandwidth (is this necessary?) - } else { - hilf->ChNr=iso_channel; - hilf->DataRate=FIRESAT_SPEED; - - hilf->OvhdID=0; //FIXME: that is for worst case -> optimize - BWU=hilf->OvhdID?hilf->OvhdID*32:512; - BWU += (hilf->PayloadLo + (hilf->PayloadHi << 8) +3) * (2 << (3-hilf->DataRate)); -/* if (allocate_1394_resources(iso_channel,BWU)) - { - cout << "Allocation of resources failed\n"; - return -2; - }*/ - } - - hilf->PTPConnCount++; - new_oPCR=test_oPCR; -/* printk(KERN_INFO "%s: trying compare_swap...\n",__func__); */ -/* printk(KERN_INFO "%s: oPCR_old: %08x, oPCR_new: %08x\n",__func__, old_oPCR, new_oPCR); */ - result=cmp_lock(firesat, &test_oPCR, oPCR_address, old_oPCR, 2); - - if (result < 0) { - printk("%s: cannot compare_swap oPCR\n",__func__); - return result; - } - if ((old_oPCR != test_oPCR) && (!((OPCR*) &old_oPCR)->PTPConnCount)) - { - printk("%s: change of oPCR failed -> freeing resources\n",__func__); -// hilf= (OPCR*) &new_oPCR; -// unsigned int BWU=hilf->OvhdID?hilf->OvhdID*32:512; -// BWU += (hilf->Payload+3) * (2 << (3-hilf->DataRate)); -/* if (deallocate_1394_resources(iso_channel,BWU)) - { - - cout << "Deallocation of resources failed\n"; - return -3; - }*/ - } - } +int cmp_establish_pp_connection(struct firesat *firesat, int plug, int channel) +{ + __be32 old_opcr, opcr; + u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2); + int attempts = 0; + int ret; + + ret = cmp_read(firesat, &opcr, opcr_address, 4); + if (ret < 0) + return ret; + +repeat: + if (!get_opcr_online(opcr)) { + dev_err(&firesat->ud->device, "CMP: output offline\n"); + return -EBUSY; + } + + old_opcr = opcr; + + if (get_opcr_p2p_connections(opcr)) { + if (get_opcr_channel(opcr) != channel) { + dev_err(&firesat->ud->device, + "CMP: cannot change channel\n"); + return -EBUSY; } - while (old_oPCR != test_oPCR); + dev_info(&firesat->ud->device, + "CMP: overlaying existing connection\n"); + + /* We don't allocate isochronous resources. */ + } else { + set_opcr_channel(&opcr, channel); + set_opcr_data_rate(&opcr, IEEE1394_SPEED_400); + + /* FIXME: this is for the worst case - optimize */ + set_opcr_overhead_id(&opcr, 0); + + /* FIXME: allocate isochronous channel and bandwidth at IRM */ } + + set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) + 1); + + ret = cmp_lock(firesat, &opcr, opcr_address, old_opcr, 2); + if (ret < 0) + return ret; + + if (old_opcr != opcr) { + /* + * FIXME: if old_opcr.P2P_Connections > 0, + * deallocate isochronous channel and bandwidth at IRM + */ + + if (++attempts < 6) /* arbitrary limit */ + goto repeat; + return -EBUSY; + } + return 0; } -//try breaking a point-to-point connection (may be interrupted by a busreset -int try_CMPBreakPPconnection(struct firesat *firesat, int output_plug,int iso_channel) { - quadlet_t old_oPCR,test_oPCR; +void cmp_break_pp_connection(struct firesat *firesat, int plug, int channel) +{ + __be32 old_opcr, opcr; + u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2); + int attempts = 0; + + if (cmp_read(firesat, &opcr, opcr_address, 4) < 0) + return; + +repeat: + if (!get_opcr_online(opcr) || !get_opcr_p2p_connections(opcr) || + get_opcr_channel(opcr) != channel) { + dev_err(&firesat->ud->device, "CMP: no connection to break\n"); + return; + } + + old_opcr = opcr; + set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) - 1); - u64 oPCR_address=0xfffff0000904ull+(output_plug << 2); - int result=cmp_read(firesat, &test_oPCR, oPCR_address, 4); + if (cmp_lock(firesat, &opcr, opcr_address, old_opcr, 2) < 0) + return; -/* printk(KERN_INFO "%s\n",__func__); */ + if (old_opcr != opcr) { + /* + * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last + * owner, deallocate isochronous channel and bandwidth at IRM + */ - if (result < 0) { - printk("%s: cannot read oPCR\n", __func__); - return result; - } else { - do { - OPCR *hilf= (OPCR*) &test_oPCR; - - if (!hilf->OnLine || !hilf->PTPConnCount || hilf->ChNr != iso_channel) { - printk("%s: Output plug does not have PtP-connection on that channel; oPCR: %08x\n", __func__, test_oPCR); - return -EINVAL; - } else { - quadlet_t new_oPCR; - old_oPCR=test_oPCR; - hilf->PTPConnCount--; - new_oPCR=test_oPCR; - -// printk(KERN_INFO "%s: trying compare_swap...\n", __func__); - result=cmp_lock(firesat, &test_oPCR, oPCR_address, old_oPCR, 2); - if (result < 0) { - printk("%s: cannot compare_swap oPCR\n",__func__); - return result; - } - } - - } while (old_oPCR != test_oPCR); - -/* hilf = (OPCR*) &old_oPCR; - if (hilf->PTPConnCount == 1) { // if we were the last owner of this connection - cout << "deallocating 1394 resources\n"; - unsigned int BWU=hilf->OvhdID?hilf->OvhdID*32:512; - BWU += (hilf->PayloadLo + (hilf->PayloadHi << 8) +3) * (2 << (3-hilf->DataRate)); - if (deallocate_1394_resources(iso_channel,BWU)) - { - cout << "Deallocation of resources failed\n"; - return -3; - } - }*/ - } - return 0; + if (++attempts < 6) /* arbitrary limit */ + goto repeat; + } } diff --git a/drivers/media/dvb/firesat/cmp.h b/drivers/media/dvb/firesat/cmp.h index 600d578..d92f6c7 100644 --- a/drivers/media/dvb/firesat/cmp.h +++ b/drivers/media/dvb/firesat/cmp.h @@ -3,9 +3,7 @@ struct firesat; -int try_CMPEstablishPPconnection(struct firesat *firesat, int output_plug, - int iso_channel); -int try_CMPBreakPPconnection(struct firesat *firesat, int output_plug, - int iso_channel); +int cmp_establish_pp_connection(struct firesat *firesat, int plug, int channel); +void cmp_break_pp_connection(struct firesat *firesat, int plug, int channel); #endif /* _CMP_H */ diff --git a/drivers/media/dvb/firesat/firesat-ci.c b/drivers/media/dvb/firesat/firesat-ci.c index 3ef25cc..0deb47e 100644 --- a/drivers/media/dvb/firesat/firesat-ci.c +++ b/drivers/media/dvb/firesat/firesat-ci.c @@ -20,29 +20,18 @@ #include "firesat.h" #include "firesat-ci.h" -static unsigned int ca_debug = 0; -module_param(ca_debug, int, 0644); -MODULE_PARM_DESC(ca_debug, "debug logging of ca system, default is 0 (no)"); - static int firesat_ca_ready(ANTENNA_INPUT_INFO *info) { - if (ca_debug != 0) - printk("%s: CaMmi=%d, CaInit=%d, CaError=%d, CaDvb=%d, " - "CaModule=%d, CaAppInfo=%d, CaDateTime=%d, " - "CaPmt=%d\n", __func__, info->CaMmi, - info->CaInitializationStatus, info->CaErrorFlag, - info->CaDvbFlag, info->CaModulePresentStatus, - info->CaApplicationInfo, - info->CaDateTimeRequest, info->CaPmtReply); return info->CaInitializationStatus == 1 && - info->CaErrorFlag == 0 && - info->CaDvbFlag == 1 && - info->CaModulePresentStatus == 1; + info->CaErrorFlag == 0 && + info->CaDvbFlag == 1 && + info->CaModulePresentStatus == 1; } static int firesat_get_ca_flags(ANTENNA_INPUT_INFO *info) { int flags = 0; + if (info->CaModulePresentStatus == 1) flags |= CA_CI_MODULE_PRESENT; if (info->CaInitializationStatus == 1 && @@ -54,103 +43,63 @@ static int firesat_get_ca_flags(ANTENNA_INPUT_INFO *info) static int firesat_ca_reset(struct firesat *firesat) { - if (ca_debug) - printk(KERN_INFO "%s: ioctl CA_RESET\n", __func__); - if (avc_ca_reset(firesat)) - return -EFAULT; - return 0; + return avc_ca_reset(firesat) ? -EFAULT : 0; } -static int firesat_ca_get_caps(struct firesat *firesat, void *arg) +static int firesat_ca_get_caps(void *arg) { - struct ca_caps *cap_p = (struct ca_caps*)arg; - int err = 0; - - cap_p->slot_num = 1; - cap_p->slot_type = CA_CI; - cap_p->descr_num = 1; - cap_p->descr_type = CA_ECD; - if (ca_debug) - printk(KERN_INFO "%s: ioctl CA_GET_CAP\n", __func__); - return err; + struct ca_caps *cap = arg; + + cap->slot_num = 1; + cap->slot_type = CA_CI; + cap->descr_num = 1; + cap->descr_type = CA_ECD; + return 0; } static int firesat_ca_get_slot_info(struct firesat *firesat, void *arg) { ANTENNA_INPUT_INFO info; - struct ca_slot_info *slot_p = (struct ca_slot_info*)arg; + struct ca_slot_info *slot = arg; - if (ca_debug) - printk(KERN_INFO "%s: ioctl CA_GET_SLOT_INFO on slot %d.\n", - __func__, slot_p->num); - if (AVCTunerStatus(firesat, &info)) + if (avc_tuner_status(firesat, &info)) return -EFAULT; - if (slot_p->num == 0) { - slot_p->type = CA_CI; - slot_p->flags = firesat_get_ca_flags(&info); - } - else { + if (slot->num != 0) return -EFAULT; - } + + slot->type = CA_CI; + slot->flags = firesat_get_ca_flags(&info); return 0; } static int firesat_ca_app_info(struct firesat *firesat, void *arg) { - struct ca_msg *reply_p = (struct ca_msg*)arg; - int i; + struct ca_msg *reply = arg; - if (avc_ca_app_info(firesat, reply_p->msg, &reply_p->length)) - return -EFAULT; - if (ca_debug) { - printk(KERN_INFO "%s: Creating TAG_APP_INFO message:", - __func__); - for (i = 0; i < reply_p->length; i++) - printk("0x%02X, ", (unsigned char)reply_p->msg[i]); - printk("\n"); - } - return 0; + return + avc_ca_app_info(firesat, reply->msg, &reply->length) ? -EFAULT : 0; } static int firesat_ca_info(struct firesat *firesat, void *arg) { - struct ca_msg *reply_p = (struct ca_msg*)arg; - int i; + struct ca_msg *reply = arg; - if (avc_ca_info(firesat, reply_p->msg, &reply_p->length)) - return -EFAULT; - if (ca_debug) { - printk(KERN_INFO "%s: Creating TAG_CA_INFO message:", - __func__); - for (i = 0; i < reply_p->length; i++) - printk("0x%02X, ", (unsigned char)reply_p->msg[i]); - printk("\n"); - } - return 0; + return avc_ca_info(firesat, reply->msg, &reply->length) ? -EFAULT : 0; } static int firesat_ca_get_mmi(struct firesat *firesat, void *arg) { - struct ca_msg *reply_p = (struct ca_msg*)arg; - int i; + struct ca_msg *reply = arg; - if (avc_ca_get_mmi(firesat, reply_p->msg, &reply_p->length)) - return -EFAULT; - if (ca_debug) { - printk(KERN_INFO "%s: Creating MMI reply INFO message:", - __func__); - for (i = 0; i < reply_p->length; i++) - printk("0x%02X, ", (unsigned char)reply_p->msg[i]); - printk("\n"); - } - return 0; + return + avc_ca_get_mmi(firesat, reply->msg, &reply->length) ? -EFAULT : 0; } static int firesat_ca_get_msg(struct firesat *firesat, void *arg) { - int err; ANTENNA_INPUT_INFO info; + int err; switch (firesat->ca_last_command) { case TAG_APP_INFO_ENQUIRY: @@ -160,11 +109,10 @@ static int firesat_ca_get_msg(struct firesat *firesat, void *arg) err = firesat_ca_info(firesat, arg); break; default: - if (AVCTunerStatus(firesat, &info)) + if (avc_tuner_status(firesat, &info)) err = -EFAULT; - else if (info.CaMmi == 1) { + else if (info.CaMmi == 1) err = firesat_ca_get_mmi(firesat, arg); - } else { printk(KERN_INFO "%s: Unhandled message 0x%08X\n", __func__, firesat->ca_last_command); @@ -177,51 +125,39 @@ static int firesat_ca_get_msg(struct firesat *firesat, void *arg) static int firesat_ca_pmt(struct firesat *firesat, void *arg) { - struct ca_msg *msg_p = (struct ca_msg*)arg; + struct ca_msg *msg = arg; int data_pos; - if (msg_p->msg[3] & 0x80) - data_pos = (msg_p->msg[4] && 0x7F) + 4; + if (msg->msg[3] & 0x80) + data_pos = (msg->msg[4] && 0x7F) + 4; else data_pos = 4; - if (avc_ca_pmt(firesat, &msg_p->msg[data_pos], - msg_p->length - data_pos)) - return -EFAULT; - return 0; + + return avc_ca_pmt(firesat, &msg->msg[data_pos], + msg->length - data_pos) ? -EFAULT : 0; } static int firesat_ca_send_msg(struct firesat *firesat, void *arg) { + struct ca_msg *msg = arg; int err; - struct ca_msg *msg_p = (struct ca_msg*)arg; - // Do we need a semaphore for this? + /* Do we need a semaphore for this? */ firesat->ca_last_command = - (msg_p->msg[0] << 16) + (msg_p->msg[1] << 8) + msg_p->msg[2]; + (msg->msg[0] << 16) + (msg->msg[1] << 8) + msg->msg[2]; switch (firesat->ca_last_command) { case TAG_CA_PMT: - if (ca_debug != 0) - printk(KERN_INFO "%s: Message received: TAG_CA_PMT\n", - __func__); err = firesat_ca_pmt(firesat, arg); break; case TAG_APP_INFO_ENQUIRY: - // This is all handled in ca_get_msg - if (ca_debug != 0) - printk(KERN_INFO "%s: Message received: " - "TAG_APP_INFO_ENQUIRY\n", __func__); + /* handled in ca_get_msg */ err = 0; break; case TAG_CA_INFO_ENQUIRY: - // This is all handled in ca_get_msg - if (ca_debug != 0) - printk(KERN_INFO "%s: Message received: " - "TAG_CA_APP_INFO_ENQUIRY\n", __func__); + /* handled in ca_get_msg */ err = 0; break; case TAG_ENTER_MENU: - if (ca_debug != 0) - printk(KERN_INFO "%s: Entering CA menu.\n", __func__); err = avc_ca_enter_menu(firesat); break; default: @@ -235,17 +171,17 @@ static int firesat_ca_send_msg(struct firesat *firesat, void *arg) static int firesat_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { - struct dvb_device* dvbdev = (struct dvb_device*) file->private_data; + struct dvb_device *dvbdev = file->private_data; struct firesat *firesat = dvbdev->priv; - int err; ANTENNA_INPUT_INFO info; + int err; switch(cmd) { case CA_RESET: err = firesat_ca_reset(firesat); break; case CA_GET_CAP: - err = firesat_ca_get_caps(firesat, arg); + err = firesat_ca_get_caps(arg); break; case CA_GET_SLOT_INFO: err = firesat_ca_get_slot_info(firesat, arg); @@ -262,90 +198,52 @@ static int firesat_ca_ioctl(struct inode *inode, struct file *file, err = -EOPNOTSUPP; } - if (AVCTunerStatus(firesat, &info)) - return err; - - firesat_ca_ready(&info); + /* FIXME Is this necessary? */ + avc_tuner_status(firesat, &info); return err; } -static int firesat_get_date_time_request(struct firesat *firesat) -{ - if (ca_debug) - printk(KERN_INFO "%s: Retrieving Time/Date request\n", - __func__); - if (avc_ca_get_time_date(firesat, &firesat->ca_time_interval)) - return -EFAULT; - if (ca_debug) - printk(KERN_INFO "%s: Time/Date interval is %d\n", - __func__, firesat->ca_time_interval); - - return 0; -} - -static int firesat_ca_io_open(struct inode *inode, struct file *file) -{ - if (ca_debug != 0) - printk(KERN_INFO "%s\n",__func__); - return dvb_generic_open(inode, file); -} - -static int firesat_ca_io_release(struct inode *inode, struct file *file) -{ - if (ca_debug != 0) - printk(KERN_INFO "%s\n",__func__); - return dvb_generic_release(inode, file); -} - static unsigned int firesat_ca_io_poll(struct file *file, poll_table *wait) { - if (ca_debug != 0) - printk(KERN_INFO "%s\n",__func__); return POLLIN; } static struct file_operations firesat_ca_fops = { - .owner = THIS_MODULE, - .read = NULL, // There is no low level read anymore - .write = NULL, // There is no low level write anymore - .ioctl = dvb_generic_ioctl, - .open = firesat_ca_io_open, - .release = firesat_ca_io_release, - .poll = firesat_ca_io_poll, + .owner = THIS_MODULE, + .ioctl = dvb_generic_ioctl, + .open = dvb_generic_open, + .release = dvb_generic_release, + .poll = firesat_ca_io_poll, }; static struct dvb_device firesat_ca = { - .priv = NULL, - .users = 1, - .readers = 1, - .writers = 1, - .fops = &firesat_ca_fops, - .kernel_ioctl = firesat_ca_ioctl, + .users = 1, + .readers = 1, + .writers = 1, + .fops = &firesat_ca_fops, + .kernel_ioctl = firesat_ca_ioctl, }; -int firesat_ca_init(struct firesat *firesat) +int firesat_ca_register(struct firesat *firesat) { - int err; ANTENNA_INPUT_INFO info; + int err; - if (AVCTunerStatus(firesat, &info)) + if (avc_tuner_status(firesat, &info)) return -EINVAL; - if (firesat_ca_ready(&info)) { - err = dvb_register_device(firesat->adapter, - &firesat->cadev, - &firesat_ca, firesat, - DVB_DEVICE_CA); - - if (info.CaApplicationInfo == 0) - printk(KERN_ERR "%s: CaApplicationInfo is not set.\n", - __func__); - if (info.CaDateTimeRequest == 1) - firesat_get_date_time_request(firesat); - } - else - err = -EFAULT; + if (!firesat_ca_ready(&info)) + return -EFAULT; + + err = dvb_register_device(&firesat->adapter, &firesat->cadev, + &firesat_ca, firesat, DVB_DEVICE_CA); + + if (info.CaApplicationInfo == 0) + printk(KERN_ERR "%s: CaApplicationInfo is not set.\n", + __func__); + if (info.CaDateTimeRequest == 1) + avc_ca_get_time_date(firesat, &firesat->ca_time_interval); return err; } @@ -353,5 +251,5 @@ int firesat_ca_init(struct firesat *firesat) void firesat_ca_release(struct firesat *firesat) { if (firesat->cadev) - dvb_unregister_device(firesat->cadev); + dvb_unregister_device(firesat->cadev); } diff --git a/drivers/media/dvb/firesat/firesat-ci.h b/drivers/media/dvb/firesat/firesat-ci.h index 04fe406..9c68cd2 100644 --- a/drivers/media/dvb/firesat/firesat-ci.h +++ b/drivers/media/dvb/firesat/firesat-ci.h @@ -3,7 +3,7 @@ struct firesat; -int firesat_ca_init(struct firesat *firesat); +int firesat_ca_register(struct firesat *firesat); void firesat_ca_release(struct firesat *firesat); #endif /* _FIREDTV_CI_H */ diff --git a/drivers/media/dvb/firesat/firesat-rc.c b/drivers/media/dvb/firesat/firesat-rc.c index d3e08f9..5f9de14 100644 --- a/drivers/media/dvb/firesat/firesat-rc.c +++ b/drivers/media/dvb/firesat/firesat-rc.c @@ -12,9 +12,11 @@ #include <linux/bitops.h> #include <linux/input.h> #include <linux/kernel.h> +#include <linux/string.h> #include <linux/types.h> #include "firesat-rc.h" +#include "firesat.h" /* fixed table with older keycodes, geared towards MythTV */ const static u16 oldtable[] = { @@ -61,7 +63,7 @@ const static u16 oldtable[] = { }; /* user-modifiable table for a remote as sold in 2008 */ -static u16 keytable[] = { +const static u16 keytable[] = { /* code from device: 0x0300...0x031f */ @@ -123,19 +125,24 @@ static u16 keytable[] = { [0x34] = KEY_EXIT, }; -static struct input_dev *idev; - -int firesat_register_rc(void) +int firesat_register_rc(struct firesat *firesat, struct device *dev) { + struct input_dev *idev; int i, err; idev = input_allocate_device(); if (!idev) return -ENOMEM; + firesat->remote_ctrl_dev = idev; idev->name = "FireDTV remote control"; + idev->dev.parent = dev; idev->evbit[0] = BIT_MASK(EV_KEY); - idev->keycode = keytable; + idev->keycode = kmemdup(keytable, sizeof(keytable), GFP_KERNEL); + if (!idev->keycode) { + err = -ENOMEM; + goto fail; + } idev->keycodesize = sizeof(keytable[0]); idev->keycodemax = ARRAY_SIZE(keytable); @@ -144,22 +151,31 @@ int firesat_register_rc(void) err = input_register_device(idev); if (err) - input_free_device(idev); + goto fail_free_keymap; + return 0; + +fail_free_keymap: + kfree(idev->keycode); +fail: + input_free_device(idev); return err; } -void firesat_unregister_rc(void) +void firesat_unregister_rc(struct firesat *firesat) { - input_unregister_device(idev); + kfree(firesat->remote_ctrl_dev->keycode); + input_unregister_device(firesat->remote_ctrl_dev); } -void firesat_handle_rc(unsigned int code) +void firesat_handle_rc(struct firesat *firesat, unsigned int code) { + u16 *keycode = firesat->remote_ctrl_dev->keycode; + if (code >= 0x0300 && code <= 0x031f) - code = keytable[code - 0x0300]; + code = keycode[code - 0x0300]; else if (code >= 0x0340 && code <= 0x0354) - code = keytable[code - 0x0320]; + code = keycode[code - 0x0320]; else if (code >= 0x4501 && code <= 0x451f) code = oldtable[code - 0x4501]; else if (code >= 0x4540 && code <= 0x4542) @@ -170,6 +186,6 @@ void firesat_handle_rc(unsigned int code) return; } - input_report_key(idev, code, 1); - input_report_key(idev, code, 0); + input_report_key(firesat->remote_ctrl_dev, code, 1); + input_report_key(firesat->remote_ctrl_dev, code, 0); } diff --git a/drivers/media/dvb/firesat/firesat-rc.h b/drivers/media/dvb/firesat/firesat-rc.h index 81f4fde..12c1c5c 100644 --- a/drivers/media/dvb/firesat/firesat-rc.h +++ b/drivers/media/dvb/firesat/firesat-rc.h @@ -1,8 +1,11 @@ #ifndef _FIREDTV_RC_H #define _FIREDTV_RC_H -int firesat_register_rc(void); -void firesat_unregister_rc(void); -void firesat_handle_rc(unsigned int code); +struct firesat; +struct device; + +int firesat_register_rc(struct firesat *firesat, struct device *dev); +void firesat_unregister_rc(struct firesat *firesat); +void firesat_handle_rc(struct firesat *firesat, unsigned int code); #endif /* _FIREDTV_RC_H */ diff --git a/drivers/media/dvb/firesat/firesat.h b/drivers/media/dvb/firesat/firesat.h index 5f0de88..51f64c0 100644 --- a/drivers/media/dvb/firesat/firesat.h +++ b/drivers/media/dvb/firesat/firesat.h @@ -21,11 +21,11 @@ #include <linux/types.h> #include <linux/wait.h> #include <linux/workqueue.h> -#include <asm/atomic.h> #include <demux.h> #include <dmxdev.h> #include <dvb_demux.h> +#include <dvb_frontend.h> #include <dvb_net.h> #include <dvbdev.h> @@ -127,50 +127,35 @@ enum model_type { FireSAT_DVB_S2 = 4, }; -struct hpsb_host; +struct input_dev; struct hpsb_iso; -struct node_entry; +struct unit_directory; struct firesat { - struct dvb_demux dvb_demux; - - /* DVB bits */ - struct dvb_adapter *adapter; - struct dmxdev dmxdev; - struct dvb_demux demux; - struct dmx_frontend frontend; - struct dvb_net dvbnet; - struct dvb_frontend_info *frontend_info; - struct dvb_frontend *fe; - - struct dvb_device *cadev; - int ca_last_command; - int ca_time_interval; - - struct mutex avc_mutex; - wait_queue_head_t avc_wait; - atomic_t avc_reply_received; - struct work_struct remote_ctrl_work; + struct dvb_adapter adapter; + struct dmxdev dmxdev; + struct dvb_demux demux; + struct dmx_frontend frontend; + struct dvb_net dvbnet; + struct dvb_frontend fe; + + struct dvb_device *cadev; + int ca_last_command; + int ca_time_interval; + + struct mutex avc_mutex; + wait_queue_head_t avc_wait; + bool avc_reply_received; + struct work_struct remote_ctrl_work; + struct input_dev *remote_ctrl_dev; struct firesat_channel { - struct firesat *firesat; - struct dvb_demux_feed *dvbdmxfeed; - - int active; - int id; + bool active; int pid; - int type; /* 1 - TS, 2 - Filter */ } channel[16]; - struct mutex demux_mutex; - - /* needed by avc_api */ - void *respfrm; - int resp_length; + struct mutex demux_mutex; - struct hpsb_host *host; - u64 guid; /* GUID of this node */ - u32 guid_vendor_id; /* Top 24bits of guid */ - struct node_entry *nodeentry; + struct unit_directory *ud; enum model_type type; char subunit; @@ -181,6 +166,10 @@ struct firesat { struct hpsb_iso *iso_handle; struct list_head list; + + /* needed by avc_api */ + int resp_length; + u8 respfrm[512]; }; struct firewireheader { @@ -226,11 +215,10 @@ struct device; /* firesat_dvb.c */ int firesat_start_feed(struct dvb_demux_feed *dvbdmxfeed); int firesat_stop_feed(struct dvb_demux_feed *dvbdmxfeed); -int firesat_dvbdev_init(struct firesat *firesat, struct device *dev, - struct dvb_frontend *fe); +int firesat_dvbdev_init(struct firesat *firesat, struct device *dev); /* firesat_fe.c */ -int firesat_frontend_attach(struct firesat *firesat, struct dvb_frontend *fe); +void firesat_frontend_init(struct firesat *firesat); /* firesat_iso.c */ int setup_iso_channel(struct firesat *firesat); diff --git a/drivers/media/dvb/firesat/firesat_1394.c b/drivers/media/dvb/firesat/firesat_1394.c index a13fbe6..82bd978 100644 --- a/drivers/media/dvb/firesat/firesat_1394.c +++ b/drivers/media/dvb/firesat/firesat_1394.c @@ -21,7 +21,6 @@ #include <linux/spinlock.h> #include <linux/string.h> #include <linux/types.h> -#include <asm/atomic.h> #include <dmxdev.h> #include <dvb_demux.h> @@ -40,40 +39,54 @@ #include "firesat-ci.h" #include "firesat-rc.h" -#define FIRESAT_Vendor_ID 0x001287 +#define MATCH_FLAGS IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \ + IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION +#define DIGITAL_EVERYWHERE_OUI 0x001287 static struct ieee1394_device_id firesat_id_table[] = { { /* FloppyDTV S/CI and FloppyDTV S2 */ - .match_flags = IEEE1394_MATCH_MODEL_ID | IEEE1394_MATCH_SPECIFIER_ID, - .model_id = 0x000024, - .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, + .match_flags = MATCH_FLAGS, + .vendor_id = DIGITAL_EVERYWHERE_OUI, + .model_id = 0x000024, + .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, + .version = AVC_SW_VERSION_ENTRY, },{ /* FloppyDTV T/CI */ - .match_flags = IEEE1394_MATCH_MODEL_ID | IEEE1394_MATCH_SPECIFIER_ID, - .model_id = 0x000025, - .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, + .match_flags = MATCH_FLAGS, + .vendor_id = DIGITAL_EVERYWHERE_OUI, + .model_id = 0x000025, + .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, + .version = AVC_SW_VERSION_ENTRY, },{ /* FloppyDTV C/CI */ - .match_flags = IEEE1394_MATCH_MODEL_ID | IEEE1394_MATCH_SPECIFIER_ID, - .model_id = 0x000026, - .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, + .match_flags = MATCH_FLAGS, + .vendor_id = DIGITAL_EVERYWHERE_OUI, + .model_id = 0x000026, + .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, + .version = AVC_SW_VERSION_ENTRY, },{ /* FireDTV S/CI and FloppyDTV S2 */ - .match_flags = IEEE1394_MATCH_MODEL_ID | IEEE1394_MATCH_SPECIFIER_ID, - .model_id = 0x000034, - .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, + .match_flags = MATCH_FLAGS, + .vendor_id = DIGITAL_EVERYWHERE_OUI, + .model_id = 0x000034, + .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, + .version = AVC_SW_VERSION_ENTRY, },{ /* FireDTV T/CI */ - .match_flags = IEEE1394_MATCH_MODEL_ID | IEEE1394_MATCH_SPECIFIER_ID, - .model_id = 0x000035, - .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, + .match_flags = MATCH_FLAGS, + .vendor_id = DIGITAL_EVERYWHERE_OUI, + .model_id = 0x000035, + .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, + .version = AVC_SW_VERSION_ENTRY, },{ /* FireDTV C/CI */ - .match_flags = IEEE1394_MATCH_MODEL_ID | IEEE1394_MATCH_SPECIFIER_ID, - .model_id = 0x000036, - .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, + .match_flags = MATCH_FLAGS, + .vendor_id = DIGITAL_EVERYWHERE_OUI, + .model_id = 0x000036, + .specifier_id = AVC_UNIT_SPEC_ID_ENTRY, + .version = AVC_SW_VERSION_ENTRY, }, { } }; @@ -98,8 +111,8 @@ static void fcp_request(struct hpsb_host *host, spin_lock_irqsave(&firesat_list_lock, flags); list_for_each_entry(firesat_entry,&firesat_list,list) { - if (firesat_entry->host == host && - firesat_entry->nodeentry->nodeid == nodeid && + if (firesat_entry->ud->ne->host == host && + firesat_entry->ud->ne->nodeid == nodeid && (firesat_entry->subunit == (data[1]&0x7) || (firesat_entry->subunit == 0 && (data[1]&0x7) == 0x7))) { @@ -110,12 +123,8 @@ static void fcp_request(struct hpsb_host *host, spin_unlock_irqrestore(&firesat_list_lock, flags); if (firesat) - AVCRecv(firesat,data,length); - else - printk("%s: received fcp request from unknown source, ignored\n", __func__); + avc_recv(firesat, data, length); } - else - printk("%s: received invalid fcp request, ignored\n", __func__); } const char *firedtv_model_names[] = { @@ -128,175 +137,108 @@ const char *firedtv_model_names[] = { static int firesat_probe(struct device *dev) { - struct unit_directory *ud = container_of(dev, struct unit_directory, device); + struct unit_directory *ud = + container_of(dev, struct unit_directory, device); struct firesat *firesat; - struct dvb_frontend *fe; unsigned long flags; - unsigned char subunitcount = 0xff, subunit; - struct firesat **firesats = kmalloc(sizeof (void*) * 2,GFP_KERNEL); int kv_len; + void *kv_str; int i; - char *kv_buf; + int err = -ENOMEM; - if (!firesats) { - printk("%s: couldn't allocate memory.\n", __func__); + firesat = kzalloc(sizeof(*firesat), GFP_KERNEL); + if (!firesat) return -ENOMEM; - } - -// printk(KERN_INFO "FireSAT: Detected device with GUID %08lx%04lx%04lx\n",(unsigned long)((ud->ne->guid)>>32),(unsigned long)(ud->ne->guid & 0xFFFF),(unsigned long)ud->ne->guid_vendor_id); - printk(KERN_INFO "%s: loading device\n", __func__); - - firesats[0] = NULL; - firesats[1] = NULL; - - ud->device.driver_data = firesats; - - for (subunit = 0; subunit < subunitcount; subunit++) { - - if (!(firesat = kmalloc(sizeof (struct firesat), GFP_KERNEL)) || - !(fe = kmalloc(sizeof (struct dvb_frontend), GFP_KERNEL))) { - - printk("%s: couldn't allocate memory.\n", __func__); - kfree(firesats); - return -ENOMEM; - } - - memset(firesat, 0, sizeof (struct firesat)); - - firesat->host = ud->ne->host; - firesat->guid = ud->ne->guid; - firesat->guid_vendor_id = ud->ne->guid_vendor_id; - firesat->nodeentry = ud->ne; - firesat->isochannel = -1; - firesat->tone = 0xff; - firesat->voltage = 0xff; - firesat->fe = fe; - - if (!(firesat->respfrm = kmalloc(sizeof (AVCRspFrm), GFP_KERNEL))) { - printk("%s: couldn't allocate memory.\n", __func__); - kfree(firesat); - return -ENOMEM; - } - - mutex_init(&firesat->avc_mutex); - init_waitqueue_head(&firesat->avc_wait); - atomic_set(&firesat->avc_reply_received, 1); - mutex_init(&firesat->demux_mutex); - INIT_WORK(&firesat->remote_ctrl_work, avc_remote_ctrl_work); - - spin_lock_irqsave(&firesat_list_lock, flags); - INIT_LIST_HEAD(&firesat->list); - list_add_tail(&firesat->list, &firesat_list); - spin_unlock_irqrestore(&firesat_list_lock, flags); - - if (subunit == 0) { - firesat->subunit = 0x7; // 0x7 = don't care - if (AVCSubUnitInfo(firesat, &subunitcount)) { - printk("%s: AVC subunit info command failed.\n",__func__); - spin_lock_irqsave(&firesat_list_lock, flags); - list_del(&firesat->list); - spin_unlock_irqrestore(&firesat_list_lock, flags); - kfree(firesat); - return -EIO; - } - } - - printk(KERN_INFO "%s: subunit count = %d\n", __func__, subunitcount); - - firesat->subunit = subunit; - - /* Reading device model from ROM */ - kv_len = (ud->model_name_kv->value.leaf.len - 2) * - sizeof(quadlet_t); - kv_buf = kmalloc((sizeof(quadlet_t) * kv_len), GFP_KERNEL); - memcpy(kv_buf, - CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv), - kv_len); - while ((kv_buf + kv_len - 1) == '\0') kv_len--; - kv_buf[kv_len++] = '\0'; - for (i = ARRAY_SIZE(firedtv_model_names); --i;) - if (strcmp(kv_buf, firedtv_model_names[i]) == 0) - break; - firesat->type = i; - kfree(kv_buf); - - if (AVCIdentifySubunit(firesat)) { - printk("%s: cannot identify subunit %d\n", __func__, subunit); - spin_lock_irqsave(&firesat_list_lock, flags); - list_del(&firesat->list); - spin_unlock_irqrestore(&firesat_list_lock, flags); - kfree(firesat); - continue; - } + dev->driver_data = firesat; + firesat->ud = ud; + firesat->subunit = 0; + firesat->isochannel = -1; + firesat->tone = 0xff; + firesat->voltage = 0xff; + + mutex_init(&firesat->avc_mutex); + init_waitqueue_head(&firesat->avc_wait); + firesat->avc_reply_received = true; + mutex_init(&firesat->demux_mutex); + INIT_WORK(&firesat->remote_ctrl_work, avc_remote_ctrl_work); + + /* Reading device model from ROM */ + kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t); + kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv); + for (i = ARRAY_SIZE(firedtv_model_names); --i;) + if (strlen(firedtv_model_names[i]) <= kv_len && + strncmp(kv_str, firedtv_model_names[i], kv_len) == 0) + break; + firesat->type = i; + + /* + * Work around a bug in udev's path_id script: Use the fw-host's dev + * instead of the unit directory's dev as parent of the input device. + */ + err = firesat_register_rc(firesat, dev->parent->parent); + if (err) + goto fail_free; + + INIT_LIST_HEAD(&firesat->list); + spin_lock_irqsave(&firesat_list_lock, flags); + list_add_tail(&firesat->list, &firesat_list); + spin_unlock_irqrestore(&firesat_list_lock, flags); + + err = avc_identify_subunit(firesat); + if (err) + goto fail; -// ---- - /* FIXME: check for error return */ - firesat_dvbdev_init(firesat, dev, fe); -// ---- - firesats[subunit] = firesat; - } // loop for all tuners + err = firesat_dvbdev_init(firesat, dev); + if (err) + goto fail; - if (firesats[0]) - AVCRegisterRemoteControl(firesats[0]); + avc_register_remote_control(firesat); + return 0; - return 0; +fail: + spin_lock_irqsave(&firesat_list_lock, flags); + list_del(&firesat->list); + spin_unlock_irqrestore(&firesat_list_lock, flags); + firesat_unregister_rc(firesat); +fail_free: + kfree(firesat); + return err; } static int firesat_remove(struct device *dev) { - struct unit_directory *ud = container_of(dev, struct unit_directory, device); - struct firesat **firesats = ud->device.driver_data; - int k; + struct firesat *firesat = dev->driver_data; unsigned long flags; - if (firesats) { - for (k = 0; k < 2; k++) - if (firesats[k]) { - firesat_ca_release(firesats[k]); - - dvb_unregister_frontend(firesats[k]->fe); - dvb_net_release(&firesats[k]->dvbnet); - firesats[k]->demux.dmx.close(&firesats[k]->demux.dmx); - firesats[k]->demux.dmx.remove_frontend(&firesats[k]->demux.dmx, &firesats[k]->frontend); - dvb_dmxdev_release(&firesats[k]->dmxdev); - dvb_dmx_release(&firesats[k]->demux); - dvb_unregister_adapter(firesats[k]->adapter); - - spin_lock_irqsave(&firesat_list_lock, flags); - list_del(&firesats[k]->list); - spin_unlock_irqrestore(&firesat_list_lock, flags); - - cancel_work_sync(&firesats[k]->remote_ctrl_work); - - kfree(firesats[k]->fe); - kfree(firesats[k]->adapter); - kfree(firesats[k]->respfrm); - kfree(firesats[k]); - } - kfree(firesats); - } else - printk("%s: can't get firesat handle\n", __func__); + firesat_ca_release(firesat); + dvb_unregister_frontend(&firesat->fe); + dvb_net_release(&firesat->dvbnet); + firesat->demux.dmx.close(&firesat->demux.dmx); + firesat->demux.dmx.remove_frontend(&firesat->demux.dmx, + &firesat->frontend); + dvb_dmxdev_release(&firesat->dmxdev); + dvb_dmx_release(&firesat->demux); + dvb_unregister_adapter(&firesat->adapter); + + spin_lock_irqsave(&firesat_list_lock, flags); + list_del(&firesat->list); + spin_unlock_irqrestore(&firesat_list_lock, flags); - printk(KERN_INFO "FireSAT: Removing device with vendor id 0x%x, model id 0x%x.\n",ud->vendor_id,ud->model_id); + cancel_work_sync(&firesat->remote_ctrl_work); + firesat_unregister_rc(firesat); + kfree(firesat); return 0; } static int firesat_update(struct unit_directory *ud) { - struct firesat **firesats = ud->device.driver_data; - int k; - // loop over subunits - - for (k = 0; k < 2; k++) - if (firesats[k]) { - firesats[k]->nodeentry = ud->ne; - - if (firesats[k]->isochannel >= 0) - try_CMPEstablishPPconnection(firesats[k], firesats[k]->subunit, firesats[k]->isochannel); - } + struct firesat *firesat = ud->device.driver_data; + if (firesat->isochannel >= 0) + cmp_establish_pp_connection(firesat, firesat->subunit, + firesat->isochannel); return 0; } @@ -328,26 +270,13 @@ static int __init firesat_init(void) ret = hpsb_register_protocol(&firesat_driver); if (ret) { printk(KERN_ERR "firedtv: failed to register protocol\n"); - goto fail; - } - - ret = firesat_register_rc(); - if (ret) { - printk(KERN_ERR "firedtv: failed to register input device\n"); - goto fail_rc; + hpsb_unregister_highlevel(&firesat_highlevel); } - - return 0; -fail_rc: - hpsb_unregister_protocol(&firesat_driver); -fail: - hpsb_unregister_highlevel(&firesat_highlevel); return ret; } static void __exit firesat_exit(void) { - firesat_unregister_rc(); hpsb_unregister_protocol(&firesat_driver); hpsb_unregister_highlevel(&firesat_highlevel); } diff --git a/drivers/media/dvb/firesat/firesat_dvb.c b/drivers/media/dvb/firesat/firesat_dvb.c index e944cee..cfa3a2e 100644 --- a/drivers/media/dvb/firesat/firesat_dvb.c +++ b/drivers/media/dvb/firesat/firesat_dvb.c @@ -34,8 +34,8 @@ static struct firesat_channel *firesat_channel_allocate(struct firesat *firesat) return NULL; for (k = 0; k < 16; k++) - if (firesat->channel[k].active == 0) { - firesat->channel[k].active = 1; + if (!firesat->channel[k].active) { + firesat->channel[k].active = true; c = &firesat->channel[k]; break; } @@ -52,7 +52,7 @@ static int firesat_channel_collect(struct firesat *firesat, int *pidc, u16 pid[] return -EINTR; for (k = 0; k < 16; k++) - if (firesat->channel[k].active == 1) + if (firesat->channel[k].active) pid[l++] = firesat->channel[k].pid; mutex_unlock(&firesat->demux_mutex); @@ -68,7 +68,7 @@ static int firesat_channel_release(struct firesat *firesat, if (mutex_lock_interruptible(&firesat->demux_mutex)) return -EINTR; - channel->active = 0; + channel->active = false; mutex_unlock(&firesat->demux_mutex); return 0; @@ -81,8 +81,6 @@ int firesat_start_feed(struct dvb_demux_feed *dvbdmxfeed) int pidc,k; u16 pids[16]; -// printk(KERN_INFO "%s (pid %u)\n", __func__, dvbdmxfeed->pid); - switch (dvbdmxfeed->type) { case DMX_TYPE_TS: case DMX_TYPE_SEC: @@ -102,7 +100,7 @@ int firesat_start_feed(struct dvb_demux_feed *dvbdmxfeed) case DMX_TS_PES_OTHER: //Dirty fix to keep firesat->channel pid-list up to date for(k=0;k<16;k++){ - if(firesat->channel[k].active == 0) + if (!firesat->channel[k].active) firesat->channel[k].pid = dvbdmxfeed->pid; break; @@ -124,11 +122,7 @@ int firesat_start_feed(struct dvb_demux_feed *dvbdmxfeed) } dvbdmxfeed->priv = channel; - - channel->dvbdmxfeed = dvbdmxfeed; channel->pid = dvbdmxfeed->pid; - channel->type = dvbdmxfeed->type; - channel->firesat = firesat; if (firesat_channel_collect(firesat, &pidc, pids)) { firesat_channel_release(firesat, channel); @@ -136,16 +130,17 @@ int firesat_start_feed(struct dvb_demux_feed *dvbdmxfeed) return -EINTR; } - if(dvbdmxfeed->pid == 8192) { - if((k = AVCTuner_GetTS(firesat))) { + if (dvbdmxfeed->pid == 8192) { + k = avc_tuner_get_ts(firesat); + if (k) { firesat_channel_release(firesat, channel); printk("%s: AVCTuner_GetTS failed with error %d\n", __func__, k); return k; } - } - else { - if((k = AVCTuner_SetPIDs(firesat, pidc, pids))) { + } else { + k = avc_tuner_set_pids(firesat, pidc, pids); + if (k) { firesat_channel_release(firesat, channel); printk("%s: AVCTuner_SetPIDs failed with error %d\n", __func__, k); @@ -164,8 +159,6 @@ int firesat_stop_feed(struct dvb_demux_feed *dvbdmxfeed) int k, l; u16 pids[16]; - //printk(KERN_INFO "%s (pid %u)\n", __func__, dvbdmxfeed->pid); - if (dvbdmxfeed->type == DMX_TYPE_TS && !((dvbdmxfeed->ts_type & TS_PACKET) && (demux->dmx.frontend->source != DMX_MEMORY_FE))) { @@ -177,7 +170,7 @@ int firesat_stop_feed(struct dvb_demux_feed *dvbdmxfeed) return -EINVAL; demux->pids[dvbdmxfeed->pes_type] |= 0x8000; - demux->pesfilter[dvbdmxfeed->pes_type] = 0; + demux->pesfilter[dvbdmxfeed->pes_type] = NULL; } if (!(dvbdmxfeed->ts_type & TS_DECODER && @@ -191,118 +184,93 @@ int firesat_stop_feed(struct dvb_demux_feed *dvbdmxfeed) /* list except channel to be removed */ for (k = 0, l = 0; k < 16; k++) - if (firesat->channel[k].active == 1) { + if (firesat->channel[k].active) { if (&firesat->channel[k] != c) pids[l++] = firesat->channel[k].pid; else - firesat->channel[k].active = 0; + firesat->channel[k].active = false; } - k = AVCTuner_SetPIDs(firesat, l, pids); + k = avc_tuner_set_pids(firesat, l, pids); if (!k) - c->active = 0; + c->active = false; mutex_unlock(&firesat->demux_mutex); return k; } -int firesat_dvbdev_init(struct firesat *firesat, - struct device *dev, - struct dvb_frontend *fe) +int firesat_dvbdev_init(struct firesat *firesat, struct device *dev) { - int result; - - firesat->adapter = kmalloc(sizeof(*firesat->adapter), GFP_KERNEL); - if (!firesat->adapter) { - printk(KERN_ERR "firedtv: couldn't allocate memory\n"); - return -ENOMEM; - } - - result = DVB_REGISTER_ADAPTER(firesat->adapter, - firedtv_model_names[firesat->type], - THIS_MODULE, dev, adapter_nr); - if (result < 0) { - printk(KERN_ERR "firedtv: dvb_register_adapter failed\n"); - kfree(firesat->adapter); - return result; - } - - memset(&firesat->demux, 0, sizeof(struct dvb_demux)); - firesat->demux.dmx.capabilities = 0/*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/; - - firesat->demux.priv = (void *)firesat; - firesat->demux.filternum = 16; - firesat->demux.feednum = 16; - firesat->demux.start_feed = firesat_start_feed; - firesat->demux.stop_feed = firesat_stop_feed; - firesat->demux.write_to_decoder = NULL; + int err; - if ((result = dvb_dmx_init(&firesat->demux)) < 0) { - printk("%s: dvb_dmx_init failed: error %d\n", __func__, - result); + err = DVB_REGISTER_ADAPTER(&firesat->adapter, + firedtv_model_names[firesat->type], + THIS_MODULE, dev, adapter_nr); + if (err) + goto fail_log; - dvb_unregister_adapter(firesat->adapter); + /*DMX_TS_FILTERING | DMX_SECTION_FILTERING*/ + firesat->demux.dmx.capabilities = 0; - return result; - } - - firesat->dmxdev.filternum = 16; - firesat->dmxdev.demux = &firesat->demux.dmx; - firesat->dmxdev.capabilities = 0; - - if ((result = dvb_dmxdev_init(&firesat->dmxdev, firesat->adapter)) < 0) { - printk("%s: dvb_dmxdev_init failed: error %d\n", - __func__, result); + firesat->demux.priv = (void *)firesat; + firesat->demux.filternum = 16; + firesat->demux.feednum = 16; + firesat->demux.start_feed = firesat_start_feed; + firesat->demux.stop_feed = firesat_stop_feed; + firesat->demux.write_to_decoder = NULL; - dvb_dmx_release(&firesat->demux); - dvb_unregister_adapter(firesat->adapter); + err = dvb_dmx_init(&firesat->demux); + if (err) + goto fail_unreg_adapter; - return result; - } + firesat->dmxdev.filternum = 16; + firesat->dmxdev.demux = &firesat->demux.dmx; + firesat->dmxdev.capabilities = 0; - firesat->frontend.source = DMX_FRONTEND_0; + err = dvb_dmxdev_init(&firesat->dmxdev, &firesat->adapter); + if (err) + goto fail_dmx_release; - if ((result = firesat->demux.dmx.add_frontend(&firesat->demux.dmx, - &firesat->frontend)) < 0) { - printk("%s: dvb_dmx_init failed: error %d\n", __func__, - result); + firesat->frontend.source = DMX_FRONTEND_0; - dvb_dmxdev_release(&firesat->dmxdev); - dvb_dmx_release(&firesat->demux); - dvb_unregister_adapter(firesat->adapter); + err = firesat->demux.dmx.add_frontend(&firesat->demux.dmx, + &firesat->frontend); + if (err) + goto fail_dmxdev_release; - return result; - } + err = firesat->demux.dmx.connect_frontend(&firesat->demux.dmx, + &firesat->frontend); + if (err) + goto fail_rem_frontend; - if ((result = firesat->demux.dmx.connect_frontend(&firesat->demux.dmx, - &firesat->frontend)) < 0) { - printk("%s: dvb_dmx_init failed: error %d\n", __func__, - result); + dvb_net_init(&firesat->adapter, &firesat->dvbnet, &firesat->demux.dmx); - firesat->demux.dmx.remove_frontend(&firesat->demux.dmx, &firesat->frontend); - dvb_dmxdev_release(&firesat->dmxdev); - dvb_dmx_release(&firesat->demux); - dvb_unregister_adapter(firesat->adapter); + firesat_frontend_init(firesat); + err = dvb_register_frontend(&firesat->adapter, &firesat->fe); + if (err) + goto fail_net_release; - return result; - } + err = firesat_ca_register(firesat); + if (err) + dev_info(dev, "Conditional Access Module not enabled\n"); - dvb_net_init(firesat->adapter, &firesat->dvbnet, &firesat->demux.dmx); - -// fe->ops = firesat_ops; -// fe->dvb = firesat->adapter; - firesat_frontend_attach(firesat, fe); - - fe->sec_priv = firesat; //IMPORTANT, functions depend on this!!! - if ((result= dvb_register_frontend(firesat->adapter, fe)) < 0) { - printk("%s: dvb_register_frontend_new failed: error %d\n", __func__, result); - /* ### cleanup */ - return result; - } - - firesat_ca_init(firesat); + return 0; - return 0; +fail_net_release: + dvb_net_release(&firesat->dvbnet); + firesat->demux.dmx.close(&firesat->demux.dmx); +fail_rem_frontend: + firesat->demux.dmx.remove_frontend(&firesat->demux.dmx, + &firesat->frontend); +fail_dmxdev_release: + dvb_dmxdev_release(&firesat->dmxdev); +fail_dmx_release: + dvb_dmx_release(&firesat->demux); +fail_unreg_adapter: + dvb_unregister_adapter(&firesat->adapter); +fail_log: + dev_err(dev, "DVB initialization failed\n"); + return err; } diff --git a/drivers/media/dvb/firesat/firesat_fe.c b/drivers/media/dvb/firesat/firesat_fe.c index ec614ea..1ed972b 100644 --- a/drivers/media/dvb/firesat/firesat_fe.c +++ b/drivers/media/dvb/firesat/firesat_fe.c @@ -12,6 +12,7 @@ #include <linux/errno.h> #include <linux/kernel.h> +#include <linux/string.h> #include <linux/types.h> #include <dvb_frontend.h> @@ -22,22 +23,21 @@ static int firesat_dvb_init(struct dvb_frontend *fe) { - int result; struct firesat *firesat = fe->sec_priv; -// printk("fdi: 1\n"); - firesat->isochannel = firesat->adapter->num; //<< 1 | (firesat->subunit & 0x1); // ### ask IRM -// printk("fdi: 2\n"); - result = try_CMPEstablishPPconnection(firesat, firesat->subunit, firesat->isochannel); - if (result != 0) { + int err; + + /* FIXME - allocate free channel at IRM */ + firesat->isochannel = firesat->adapter.num; + + err = cmp_establish_pp_connection(firesat, firesat->subunit, + firesat->isochannel); + if (err) { printk(KERN_ERR "Could not establish point to point " "connection.\n"); - return -1; + return err; } -// printk("fdi: 3\n"); - result = setup_iso_channel(firesat); -// printk("fdi: 4. Result was %d\n", result); - return result; + return setup_iso_channel(firesat); } static int firesat_sleep(struct dvb_frontend *fe) @@ -45,7 +45,7 @@ static int firesat_sleep(struct dvb_frontend *fe) struct firesat *firesat = fe->sec_priv; tear_down_iso_channel(firesat); - try_CMPBreakPPconnection(firesat, firesat->subunit, firesat->isochannel); + cmp_break_pp_connection(firesat, firesat->subunit, firesat->isochannel); firesat->isochannel = -1; return 0; } @@ -55,8 +55,8 @@ static int firesat_diseqc_send_master_cmd(struct dvb_frontend *fe, { struct firesat *firesat = fe->sec_priv; - return AVCLNBControl(firesat, LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE, - LNBCONTROL_DONTCARE, 1, cmd); + return avc_lnb_control(firesat, LNBCONTROL_DONTCARE, + LNBCONTROL_DONTCARE, LNBCONTROL_DONTCARE, 1, cmd); } static int firesat_diseqc_send_burst(struct dvb_frontend *fe, @@ -82,24 +82,19 @@ static int firesat_set_voltage(struct dvb_frontend *fe, return 0; } -static int firesat_read_status (struct dvb_frontend *fe, fe_status_t *status) +static int firesat_read_status(struct dvb_frontend *fe, fe_status_t *status) { struct firesat *firesat = fe->sec_priv; ANTENNA_INPUT_INFO info; - if (AVCTunerStatus(firesat, &info)) + if (avc_tuner_status(firesat, &info)) return -EINVAL; - if (info.NoRF) { + if (info.NoRF) *status = 0; - } else { - *status = FE_HAS_SIGNAL | - FE_HAS_VITERBI | - FE_HAS_SYNC | - FE_HAS_CARRIER | - FE_HAS_LOCK; - } - + else + *status = FE_HAS_SIGNAL | FE_HAS_VITERBI | FE_HAS_SYNC | + FE_HAS_CARRIER | FE_HAS_LOCK; return 0; } @@ -108,14 +103,11 @@ static int firesat_read_ber(struct dvb_frontend *fe, u32 *ber) struct firesat *firesat = fe->sec_priv; ANTENNA_INPUT_INFO info; - if (AVCTunerStatus(firesat, &info)) + if (avc_tuner_status(firesat, &info)) return -EINVAL; - *ber = (info.BER[0] << 24) | - (info.BER[1] << 16) | - (info.BER[2] << 8) | - info.BER[3]; - + *ber = info.BER[0] << 24 | info.BER[1] << 16 | + info.BER[2] << 8 | info.BER[3]; return 0; } @@ -124,11 +116,10 @@ static int firesat_read_signal_strength (struct dvb_frontend *fe, u16 *strength) struct firesat *firesat = fe->sec_priv; ANTENNA_INPUT_INFO info; - if (AVCTunerStatus(firesat, &info)) + if (avc_tuner_status(firesat, &info)) return -EINVAL; *strength = info.SignalStrength << 8; - return 0; } @@ -137,14 +128,12 @@ static int firesat_read_snr(struct dvb_frontend *fe, u16 *snr) struct firesat *firesat = fe->sec_priv; ANTENNA_INPUT_INFO info; - if (AVCTunerStatus(firesat, &info)) + if (avc_tuner_status(firesat, &info)) return -EINVAL; - *snr = (info.CarrierNoiseRatio[0] << 8) + - info.CarrierNoiseRatio[1]; + /* C/N[dB] = -10 * log10(snr / 65535) */ + *snr = (info.CarrierNoiseRatio[0] << 8) + info.CarrierNoiseRatio[1]; *snr *= 257; - // C/N[dB] = -10 * log10(snr / 65535) - return 0; } @@ -158,10 +147,11 @@ static int firesat_set_frontend(struct dvb_frontend *fe, { struct firesat *firesat = fe->sec_priv; - if (AVCTuner_DSD(firesat, params, NULL) != ACCEPTED) + /* FIXME: avc_tuner_dsd never returns ACCEPTED. Check status? */ + if (avc_tuner_dsd(firesat, params) != ACCEPTED) return -EINVAL; else - return 0; //not sure of this... + return 0; /* not sure of this... */ } static int firesat_get_frontend(struct dvb_frontend *fe, @@ -170,107 +160,86 @@ static int firesat_get_frontend(struct dvb_frontend *fe, return -EOPNOTSUPP; } -static struct dvb_frontend_info firesat_S_frontend_info; -static struct dvb_frontend_info firesat_C_frontend_info; -static struct dvb_frontend_info firesat_T_frontend_info; - -static struct dvb_frontend_ops firesat_ops = { +void firesat_frontend_init(struct firesat *firesat) +{ + struct dvb_frontend_ops *ops = &firesat->fe.ops; + struct dvb_frontend_info *fi = &ops->info; - .init = firesat_dvb_init, - .sleep = firesat_sleep, + ops->init = firesat_dvb_init; + ops->sleep = firesat_sleep; - .set_frontend = firesat_set_frontend, - .get_frontend = firesat_get_frontend, + ops->set_frontend = firesat_set_frontend; + ops->get_frontend = firesat_get_frontend; - .read_status = firesat_read_status, - .read_ber = firesat_read_ber, - .read_signal_strength = firesat_read_signal_strength, - .read_snr = firesat_read_snr, - .read_ucblocks = firesat_read_uncorrected_blocks, + ops->read_status = firesat_read_status; + ops->read_ber = firesat_read_ber; + ops->read_signal_strength = firesat_read_signal_strength; + ops->read_snr = firesat_read_snr; + ops->read_ucblocks = firesat_read_uncorrected_blocks; - .diseqc_send_master_cmd = firesat_diseqc_send_master_cmd, - .diseqc_send_burst = firesat_diseqc_send_burst, - .set_tone = firesat_set_tone, - .set_voltage = firesat_set_voltage, -}; + ops->diseqc_send_master_cmd = firesat_diseqc_send_master_cmd; + ops->diseqc_send_burst = firesat_diseqc_send_burst; + ops->set_tone = firesat_set_tone; + ops->set_voltage = firesat_set_voltage; -int firesat_frontend_attach(struct firesat *firesat, struct dvb_frontend *fe) -{ switch (firesat->type) { case FireSAT_DVB_S: - firesat->frontend_info = &firesat_S_frontend_info; + fi->type = FE_QPSK; + + fi->frequency_min = 950000; + fi->frequency_max = 2150000; + fi->frequency_stepsize = 125; + fi->symbol_rate_min = 1000000; + fi->symbol_rate_max = 40000000; + + fi->caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | + FE_CAN_FEC_2_3 | + FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | + FE_CAN_FEC_7_8 | + FE_CAN_FEC_AUTO | + FE_CAN_QPSK; break; + case FireSAT_DVB_C: - firesat->frontend_info = &firesat_C_frontend_info; + fi->type = FE_QAM; + + fi->frequency_min = 47000000; + fi->frequency_max = 866000000; + fi->frequency_stepsize = 62500; + fi->symbol_rate_min = 870000; + fi->symbol_rate_max = 6900000; + + fi->caps = FE_CAN_INVERSION_AUTO | + FE_CAN_QAM_16 | + FE_CAN_QAM_32 | + FE_CAN_QAM_64 | + FE_CAN_QAM_128 | + FE_CAN_QAM_256 | + FE_CAN_QAM_AUTO; break; + case FireSAT_DVB_T: - firesat->frontend_info = &firesat_T_frontend_info; + fi->type = FE_OFDM; + + fi->frequency_min = 49000000; + fi->frequency_max = 861000000; + fi->frequency_stepsize = 62500; + + fi->caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_2_3 | + FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | + FE_CAN_HIERARCHY_AUTO; break; + default: - printk(KERN_ERR "firedtv: no frontend for model type 0x%x\n", + printk(KERN_ERR "FireDTV: no frontend for model type %d\n", firesat->type); - firesat->frontend_info = NULL; } - fe->ops = firesat_ops; - fe->ops.info = *(firesat->frontend_info); - fe->dvb = firesat->adapter; + strcpy(fi->name, firedtv_model_names[firesat->type]); - return 0; + firesat->fe.dvb = &firesat->adapter; + firesat->fe.sec_priv = firesat; } - -static struct dvb_frontend_info firesat_S_frontend_info = { - - .name = "FireDTV DVB-S Frontend", - .type = FE_QPSK, - - .frequency_min = 950000, - .frequency_max = 2150000, - .frequency_stepsize = 125, - .symbol_rate_min = 1000000, - .symbol_rate_max = 40000000, - - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_1_2 | - FE_CAN_FEC_2_3 | - FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | - FE_CAN_FEC_7_8 | - FE_CAN_FEC_AUTO | - FE_CAN_QPSK, -}; - -static struct dvb_frontend_info firesat_C_frontend_info = { - - .name = "FireDTV DVB-C Frontend", - .type = FE_QAM, - - .frequency_min = 47000000, - .frequency_max = 866000000, - .frequency_stepsize = 62500, - .symbol_rate_min = 870000, - .symbol_rate_max = 6900000, - - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_QAM_16 | - FE_CAN_QAM_32 | - FE_CAN_QAM_64 | - FE_CAN_QAM_128 | - FE_CAN_QAM_256 | - FE_CAN_QAM_AUTO, -}; - -static struct dvb_frontend_info firesat_T_frontend_info = { - - .name = "FireDTV DVB-T Frontend", - .type = FE_OFDM, - - .frequency_min = 49000000, - .frequency_max = 861000000, - .frequency_stepsize = 62500, - - .caps = FE_CAN_INVERSION_AUTO | - FE_CAN_FEC_2_3 | - FE_CAN_TRANSMISSION_MODE_AUTO | - FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO, -}; diff --git a/drivers/media/dvb/firesat/firesat_iso.c b/drivers/media/dvb/firesat/firesat_iso.c index bc94afe..b3c61f9 100644 --- a/drivers/media/dvb/firesat/firesat_iso.c +++ b/drivers/media/dvb/firesat/firesat_iso.c @@ -18,6 +18,7 @@ #include <dma.h> #include <iso.h> +#include <nodemgr.h> #include "firesat.h" @@ -36,7 +37,7 @@ int setup_iso_channel(struct firesat *firesat) { int result; firesat->iso_handle = - hpsb_iso_recv_init(firesat->host, + hpsb_iso_recv_init(firesat->ud->ne->host, 256 * 200, //data_buf_size, 256, //buf_packets, firesat->isochannel, @@ -59,7 +60,6 @@ static void rawiso_activity_cb(struct hpsb_iso *iso) { unsigned int num; unsigned int i; -/* unsigned int j; */ unsigned int packet; unsigned long flags; struct firesat *firesat = NULL; @@ -88,12 +88,7 @@ static void rawiso_activity_cb(struct hpsb_iso *iso) (188 + sizeof(struct firewireheader)); if (iso->infos[packet].len <= sizeof(struct CIPHeader)) continue; // ignore empty packet -/* printk("%s: Handling packets (%d): ", __func__, */ -/* iso->infos[packet].len); */ -/* for (j = 0; j < iso->infos[packet].len - */ -/* sizeof(struct CIPHeader); j++) */ -/* printk("%02X,", buf[j]); */ -/* printk("\n"); */ + while (count --) { if (buf[sizeof(struct firewireheader)] == 0x47) dvb_dmx_swfilter_packets(&firesat->demux, |