I have TT Budget-S1500 + CI addon, and have many CAM blocks. So i start to test all of them on such card. And have found that some amount of cam blocks not working on it. I know that such card give full hw access to CAM blocks registerm and ram. So i start to search where is problem (write small app for test and turn on debug of dvb_core.ko in part of cam_debug=1. I found that such CAM modules not respond on first open command Open Transport Connection in my test app. And not answer becouse sys function write return error with errno=EIO. So i start to debug dvb_core.ko the write part to CAM module and detekt that function dvb_ca_en50221_write_data in dvb_ca_en50221.c all time return in this part: /* check if interface is still free */ if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) goto exit; if (!(status & STATUSREG_FR)) { /* it wasn't free => try again later */ status = -EAGAIN; goto exit; } so module do not setup flag that it ready to receive new data. But "string dvb_ca adapter 0: DVB CAM detected and initialised successfully" all times present in dmesg. I start to read EN50221 standart in part of how init CAM and exchange data with it and found intresting logical bug in dvb_ca_en50221.c. So step by step: From standart: Neither host nor module may use the interface for transferring data until this protocol has completed. The host starts the negotiation by writing a '1' to the SR bit in the Control Register, waiting for the DA bit to be set and then reading the buffer size by a module to host transfer operation as described below. At the end of the transfer operation the host resets the SR bit to '0'. The data returned will be 2 bytes with the most significant byte first. Modules shall support a minimum buffer size of 16 bytes. The maximum is set by the limitation of the Size Register (65535 bytes). Similarly the host may have a buffer size limitation that it imposes. The host shall support a minimum buffer size of 256 bytes but it can be up to 65535 bytes. After reading the buffer size the module can support, the host takes the lower of its own buffer size and the module buffer size. This will be the buffer size used for all subsequent data transfers between host and module. The host now tells the module to use this buffer size by writing a ?1? to the SW bit in the Command Register, waiting until the FR bit is set and then writing the size as 2 bytes of data, most significant byte first, using the host to module transfer operation described below. At the end of the transfer the host sets the SW bit to '0'. Host to Module Transfers: if (Status_Reg & 0x80) /* go to module-to-host transfer (see below) */ Command_Reg = 0x01; if (Status_Reg & 0x40) { Size_Reg[0] = bsize & 0xFF; Size_Reg[1] = bsize >> 8; for (i=0; i<bsize; i++) Data_Reg = write_buf[i]; } Command_Reg = 0x00; Module to Host Transfers: if (Status_Reg & 0x80) { bsize = Size_Reg[0] | Size_Reg[1] << 8; for (i=0; i<bsize; i++) read_buf[i] = Data_Reg; } I have found that in dvb_ca_en50221.c function dvb_ca_en50221_link_init it do like it write in standart but with some small logical bug. in this part /* write the buffer size to the CAM */ if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SW)) != 0) return ret; if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10)) != 0) return ret; if ((ret = dvb_ca_en50221_write_data(ca, slot, buf, 2)) != 2) return -EIO; if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) return ret; it setup SW bit like in standart wait untill FR is set and call write_data but inside of dvb_ca_en50221_write_data COMMAND register setuped to (IRQEN | CMDREG_HC) and bit SW now is 0 but by standart it must be holded 1 untill full end of setup buffer size operation. So module on next try of write to it not setup FR flag bit becouse it wait till finishing of init part. So i make dublicate of dvb_ca_en50221_write_data and call it static int dvb_ca_en50221_write_data_with_flag(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount,u8 AddFlag); it have parameter AddFlag witch used in write data to COMMAND register (IRQEN | CMDREG_HC | AddFlag) and call this function inside of dvb_ca_en50221_link_init insted of dvb_ca_en50221_write_data not it looks: if ((ret = dvb_ca_en50221_write_data_with_flag(ca, slot, buf, 2,CMDREG_SW)) != 2) return -EIO; So most of modules start to work with such modification buta few modules still not return that it ready to recive data in write function after dvb_ca_en50221_link_init. I start to search meaning of IRQEN by definition inside of dvb_ca_en50221.c it is 7 and 6 bit but in standart this bits is reserved and must by in 0. So i modiffy more dvb_ca_en50221_link_init and dvb_ca_en50221_write_data_with_flag and disable from it IRQEN. and only setup it at end of init sequence. After this modification it start ti work with all CAM modules that i have. So i have question: what is meaning IRQEN bits? As i understand enable some interrupt request on send & receive but in EN50221 modules do not use interrupts in must be only polled for new data present by DA bit in STATUS register. diff file of modification: --- dvb_ca_en50221.c 2007-07-19 17:10:18.000000000 +0300 +++ dvb_ca_en50221.c 2007-07-19 08:29:49.000000000 +0300 @@ -1,6 +1,9 @@ /* * dvb_ca.c: generic DVB functions for EN50221 CAM interfaces * + * + * Copyright (C) 2007 Evgen Bendyak (modification of cam initialization in part of write host buffer size) + * * Copyright (C) 2004 Andrew de Quincey * * Parts of this file were based on sources as follows: @@ -164,6 +167,7 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca); static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount); static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount); +static int dvb_ca_en50221_write_data_with_flag(struct dvb_ca_private *ca, int slot, u8 * ebuf, int ecount,u8 AddFlag); /** @@ -313,17 +317,18 @@ ca->slot_info[slot].link_buf_size = 2; /* read the buffer size from the CAM */ - if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0) + if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, CMDREG_SR)) != 0) return ret; if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ / 10)) != 0) return ret; if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2) return -EIO; - if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) + if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, 0)) != 0) return ret; /* store it, and choose the minimum of our buffer and the CAM's buffer size */ buf_size = (buf[0] << 8) | buf[1]; @@ -332,11 +337,11 @@ dprintk("Chosen link buffer size of %i\n", buf_size); /* write the buffer size to the CAM */ - if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SW)) != 0) + if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, CMDREG_SW)) != 0) return ret; if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_FR, HZ / 10)) != 0) return ret; - if ((ret = dvb_ca_en50221_write_data(ca, slot, buf, 2)) != 2) + if ((ret = dvb_ca_en50221_write_data_with_flag(ca, slot, buf, 2,CMDREG_SW)) != 2) return -EIO; if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN)) != 0) return ret; @@ -775,6 +780,87 @@ exitnowrite: return status; } + +/** + * This function talks to an EN50221 CAM control interface (but with some additional + * bits setuped in CTRLIF_COMMAND register and without IRQEN). Used in setup exchange + * buffer size sequence + * It writes a buffer of data to a CAM. + * + * @param ca CA instance. + * @param slot Slot to write to. + * @param ebuf The data in this buffer is treated as a complete link-level packet to + * be written. + * @param count Size of ebuf. + * + * @return Number of bytes written, or < 0 on error. + */ +static int dvb_ca_en50221_write_data_with_flag(struct dvb_ca_private *ca, int slot, u8 * buf, int bytes_write,u8 AddFlags) +{ + int status; + int i; + + dprintk("%s\n", __FUNCTION__); + + + // sanity check + if (bytes_write > ca->slot_info[slot].link_buf_size) + return -EINVAL; + + /* check if interface is actually waiting for us to read from it, or if a read is in progress */ + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) + goto exitnowrite; + if (status & (STATUSREG_DA | STATUSREG_RE)) { + status = -EAGAIN; + goto exitnowrite; + } + + /* OK, set HC bit */ + if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, + CMDREG_HC | AddFlags)) != 0) + goto exit; + + /* check if interface is still free */ + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) + goto exit; + if (!(status & STATUSREG_FR)) { + /* it wasn't free => try again later */ + status = -EAGAIN; + goto exit; + } + + /* send the amount of data */ + if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH, bytes_write >> 8)) != 0) + goto exit; + if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW, + bytes_write & 0xff)) != 0) + goto exit; + + /* send the buffer */ + for (i = 0; i < bytes_write; i++) { + if ((status = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_DATA, buf[i])) != 0) + goto exit; + } + + /* check for write error (WE should now be 0) */ + if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) + goto exit; + if (status & STATUSREG_WE) { + ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; + status = -EIO; + goto exit; + } + status = bytes_write; + + dprintk("Wrote CA packet for slot %i, connection id 0x%x last_frag:%i size:0x%x\n", slot, + buf[0], (buf[1] & 0x80) == 0, bytes_write); + +exit: + ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, AddFlags); + +exitnowrite: + return status; +} EXPORT_SYMBOL(dvb_ca_en50221_camchange_irq); Evgen Bendyak Kiev. Ukraine. _______________________________________________ linux-dvb mailing list linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb