Ejemplo n.º 1
0
static int ks7010_sdio_data_compare(struct ks_wlan_private *priv, u32 address,
				    unsigned char *data, unsigned int size)
{
	int ret;
	unsigned char *read_buf;

	read_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL);
	if (!read_buf)
		return -ENOMEM;

	ret = ks7010_sdio_read(priv, address, read_buf, size);
	if (ret)
		goto err_free_read_buf;

	if (memcmp(data, read_buf, size) != 0) {
		ret = -EIO;
		DPRINTK(0, "data compare error (%d)\n", ret);
		goto err_free_read_buf;
	}

	return 0;

err_free_read_buf:
	kfree(read_buf);

	return ret;
}
Ejemplo n.º 2
0
static int ks7010_sdio_data_compare(struct ks_wlan_private *priv, u32 address,
				    unsigned char *data, unsigned int size)
{
	int rc = 0;
	int retval;
	unsigned char *read_buf;
	read_buf = NULL;
	read_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL);
	if (!read_buf) {
		rc = 1;
		goto error_out;
	}
	retval = ks7010_sdio_read(priv, address, read_buf, size);
	if (retval) {
		rc = 2;
		goto error_out;
	}
	retval = memcmp(data, read_buf, size);

	if (retval) {
		DPRINTK(0, "data compare error (%d) \n", retval);
		rc = 3;
		goto error_out;
	}
 error_out:
	if (read_buf)
		kfree(read_buf);
	return rc;
}
Ejemplo n.º 3
0
static void ks_wlan_hw_rx(struct ks_wlan_private *priv, uint16_t size)
{
	int ret;
	struct rx_device_buffer *rx_buffer;
	struct hostif_hdr *hdr;
	unsigned short event = 0;

	DPRINTK(4, "\n");

	/* receive data */
	if (cnt_rxqbody(priv) >= (RX_DEVICE_BUFF_SIZE - 1)) {
		DPRINTK(1, "rx buffer overflow\n");
		return;
	}
	rx_buffer = &priv->rx_dev.rx_dev_buff[priv->rx_dev.qtail];

	ret = ks7010_sdio_read(priv, DATA_WINDOW, &rx_buffer->data[0],
			       hif_align_size(size));
	if (ret)
		return;

	/* length check */
	if (size > 2046 || size == 0) {
#ifdef KS_WLAN_DEBUG
		if (KS_WLAN_DEBUG > 5)
			print_hex_dump_bytes("INVALID DATA dump: ",
					     DUMP_PREFIX_OFFSET,
					     rx_buffer->data, 32);
#endif
		ret = ks7010_sdio_writeb(priv, READ_STATUS, REG_STATUS_IDLE);
		if (ret)
			DPRINTK(1, " error : READ_STATUS\n");

		/* length check fail */
		return;
	}

	hdr = (struct hostif_hdr *)&rx_buffer->data[0];
	rx_buffer->size = le16_to_cpu(hdr->size) + sizeof(hdr->size);
	event = le16_to_cpu(hdr->event);
	inc_rxqtail(priv);

	ret = ks7010_sdio_writeb(priv, READ_STATUS, REG_STATUS_IDLE);
	if (ret)
		DPRINTK(1, " error : READ_STATUS\n");

	if (atomic_read(&priv->psstatus.confirm_wait)) {
		if (IS_HIF_CONF(event)) {
			DPRINTK(4, "IS_HIF_CONF true !!\n");
			atomic_dec(&priv->psstatus.confirm_wait);
		}
	}

	tasklet_schedule(&priv->rx_bh_task);
}
Ejemplo n.º 4
0
static int ks7010_upload_firmware(struct ks_wlan_private *priv,
				  struct ks_sdio_card *card)
{
	unsigned int size, offset, n = 0;
	unsigned char *rom_buf;
	unsigned char rw_data = 0;
	int retval, rc = 0;
	int length;
	const struct firmware *fw_entry = NULL;

	rom_buf = NULL;

	/* buffer allocate */
	rom_buf = kmalloc(ROM_BUFF_SIZE, GFP_KERNEL);
	if (!rom_buf) {
		rc = 3;
		goto error_out0;
	}

	sdio_claim_host(card->func);

	/* Firmware running ? */
	retval = ks7010_sdio_read(priv, GCR_A, &rw_data, sizeof(rw_data));
	if (rw_data == GCR_A_RUN) {
		DPRINTK(0, "MAC firmware running ...\n");
		rc = 0;
		goto error_out0;
	}

	retval = request_firmware(&fw_entry, ROM_FILE, &priv->ks_wlan_hw.sdio_card->func->dev);
	if (retval)
		return retval;

	length = fw_entry->size;

	/* Load Program */
	n = 0;
	do {
		if (length >= ROM_BUFF_SIZE) {
			size = ROM_BUFF_SIZE;
			length = length - ROM_BUFF_SIZE;
		} else {
			size = length;
			length = 0;
		}
		DPRINTK(4, "size = %d\n", size);
		if (size == 0)
			break;
		memcpy(rom_buf, fw_entry->data + n, size);
		/* Update write index */
		offset = n;
		retval =
		    ks7010_sdio_update_index(priv,
					     KS7010_IRAM_ADDRESS + offset);
		if (retval) {
			rc = 6;
			goto error_out1;
		}

		/* Write data */
		retval = ks7010_sdio_write(priv, DATA_WINDOW, rom_buf, size);
		if (retval) {
			rc = 8;
			goto error_out1;
		}

		/* compare */
		retval =
		    ks7010_sdio_data_compare(priv, DATA_WINDOW, rom_buf, size);
		if (retval) {
			rc = 9;
			goto error_out1;
		}
		n += size;

	} while (size);

	/* Remap request */
	rw_data = GCR_A_REMAP;
	retval = ks7010_sdio_write(priv, GCR_A, &rw_data, sizeof(rw_data));
	if (retval) {
		rc = 11;
		goto error_out1;
	}
	DPRINTK(4, " REMAP Request : GCR_A=%02X\n", rw_data);

	/* Firmware running check */
	for (n = 0; n < 50; ++n) {
		mdelay(10);	/* wait_ms(10); */
		retval =
		    ks7010_sdio_read(priv, GCR_A, &rw_data, sizeof(rw_data));
		if (retval) {
			rc = 11;
			goto error_out1;
		}
		if (rw_data == GCR_A_RUN)
			break;
	}
	DPRINTK(4, "firmware wakeup (%d)!!!!\n", n);
	if ((50) <= n) {
		DPRINTK(1, "firmware can't start\n");
		rc = 12;
		goto error_out1;
	}

	rc = 0;

 error_out1:
	release_firmware(fw_entry);
 error_out0:
	sdio_release_host(card->func);
	if (rom_buf)
		kfree(rom_buf);
	return rc;
}
Ejemplo n.º 5
0
static void ks_sdio_interrupt(struct sdio_func *func)
{
	int retval;
	struct ks_sdio_card *card;
	struct ks_wlan_private *priv;
	unsigned char status, rsize, rw_data;

	card = sdio_get_drvdata(func);
	priv = card->priv;
	DPRINTK(4, "\n");

	if (priv->dev_state >= DEVICE_STATE_BOOT) {
		retval =
		    ks7010_sdio_read(priv, INT_PENDING, &status,
				     sizeof(status));
		if (retval) {
			DPRINTK(1, "read INT_PENDING Failed!!(%d)\n", retval);
			goto intr_out;
		}
		DPRINTK(4, "INT_PENDING=%02X\n", rw_data);

		/* schedule task for interrupt status */
		/* bit7 -> Write General Communication B register */
		/* read (General Communication B register) */
		/* bit5 -> Write Status Idle */
		/* bit2 -> Read Status Busy  */
		if (status & INT_GCR_B
		    || atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
			retval =
			    ks7010_sdio_read(priv, GCR_B, &rw_data,
					     sizeof(rw_data));
			if (retval) {
				DPRINTK(1, " error : GCR_B=%02X\n", rw_data);
				goto intr_out;
			}
			/* DPRINTK(1, "GCR_B=%02X\n", rw_data); */
			if (rw_data == GCR_B_ACTIVE) {
				if (atomic_read(&priv->psstatus.status) ==
				    PS_SNOOZE) {
					atomic_set(&priv->psstatus.status,
						   PS_WAKEUP);
					priv->wakeup_count = 0;
				}
				complete(&priv->psstatus.wakeup_wait);
			}

		}

		do {
			/* read (WriteStatus/ReadDataSize FN1:00_0014) */
			retval =
			    ks7010_sdio_read(priv, WSTATUS_RSIZE, &rw_data,
					     sizeof(rw_data));
			if (retval) {
				DPRINTK(1, " error : WSTATUS_RSIZE=%02X\n",
					rw_data);
				goto intr_out;
			}
			DPRINTK(4, "WSTATUS_RSIZE=%02X\n", rw_data);
			rsize = rw_data & RSIZE_MASK;
			if (rsize) {	/* Read schedule */
				ks_wlan_hw_rx((void *)priv,
					      (uint16_t) (((rsize) << 4)));
			}
			if (rw_data & WSTATUS_MASK) {
#if 0
				if (status & INT_WRITE_STATUS
				    && !cnt_txqbody(priv)) {
					/* dummy write for interrupt clear */
					rw_data = 0;
					retval =
					    ks7010_sdio_write(priv, DATA_WINDOW,
							      &rw_data,
							      sizeof(rw_data));
					if (retval) {
						DPRINTK(1,
							"write DATA_WINDOW Failed!!(%d)\n",
							retval);
					}
					status &= ~INT_WRITE_STATUS;
				} else {
#endif
					if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
						if (cnt_txqbody(priv)) {
							ks_wlan_hw_wakeup_request(priv);
							queue_delayed_work
							    (priv->ks_wlan_hw.
							     ks7010sdio_wq,
							     &priv->ks_wlan_hw.
							     rw_wq, 1);
							return;
						}
					} else {
						tx_device_task((void *)priv);
					}
#if 0
				}
#endif
			}
		} while (rsize);
	}

 intr_out:
	queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
			   &priv->ks_wlan_hw.rw_wq, 0);
	return;
}
Ejemplo n.º 6
0
static void ks7010_rw_function(struct work_struct *work)
{
	struct hw_info_t *hw;
	struct ks_wlan_private *priv;
	unsigned char rw_data;
	int retval;

	hw = container_of(work, struct hw_info_t, rw_wq.work);
	priv = container_of(hw, struct ks_wlan_private, ks_wlan_hw);

	DPRINTK(4, "\n");

	/* wiat after DOZE */
	if (time_after(priv->last_doze + ((30 * HZ) / 1000), jiffies)) {
		DPRINTK(4, "wait after DOZE \n");
		queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
				   &priv->ks_wlan_hw.rw_wq, 1);
		return;
	}

	/* wiat after WAKEUP */
	while (time_after(priv->last_wakeup + ((30 * HZ) / 1000), jiffies)) {
		DPRINTK(4, "wait after WAKEUP \n");
/*		queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,&priv->ks_wlan_hw.rw_wq,
		(priv->last_wakeup + ((30*HZ)/1000) - jiffies));*/
		printk("wake: %lu %lu\n", priv->last_wakeup + (30 * HZ) / 1000,
		       jiffies);
		msleep(30);
	}

	sdio_claim_host(priv->ks_wlan_hw.sdio_card->func);

	/* power save wakeup */
	if (atomic_read(&priv->psstatus.status) == PS_SNOOZE) {
		if (cnt_txqbody(priv) > 0) {
			ks_wlan_hw_wakeup_request(priv);
			queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
					   &priv->ks_wlan_hw.rw_wq, 1);
		}
		goto err_out;
	}

	/* sleep mode doze */
	if (atomic_read(&priv->sleepstatus.doze_request) == 1) {
		ks_wlan_hw_sleep_doze_request(priv);
		goto err_out;
	}
	/* sleep mode wakeup */
	if (atomic_read(&priv->sleepstatus.wakeup_request) == 1) {
		ks_wlan_hw_sleep_wakeup_request(priv);
		goto err_out;
	}

	/* read (WriteStatus/ReadDataSize FN1:00_0014) */
	retval =
	    ks7010_sdio_read(priv, WSTATUS_RSIZE, &rw_data, sizeof(rw_data));
	if (retval) {
		DPRINTK(1, " error : WSTATUS_RSIZE=%02X psstatus=%d\n", rw_data,
			atomic_read(&priv->psstatus.status));
		goto err_out;
	}
	DPRINTK(4, "WSTATUS_RSIZE=%02X\n", rw_data);

	if (rw_data & RSIZE_MASK) {	/* Read schedule */
		ks_wlan_hw_rx((void *)priv,
			      (uint16_t) (((rw_data & RSIZE_MASK) << 4)));
	}
	if ((rw_data & WSTATUS_MASK)) {
		tx_device_task((void *)priv);
	}
	_ks_wlan_hw_power_save(priv);

 err_out:
	sdio_release_host(priv->ks_wlan_hw.sdio_card->func);

	return;
}
Ejemplo n.º 7
0
static void ks_wlan_hw_rx(void *dev, uint16_t size)
{
	struct ks_wlan_private *priv = (struct ks_wlan_private *)dev;
	int retval;
	struct rx_device_buffer *rx_buffer;
	struct hostif_hdr *hdr;
	unsigned char read_status;
	unsigned short event = 0;

	DPRINTK(4, "\n");

	/* receive data */
	if (cnt_rxqbody(priv) >= (RX_DEVICE_BUFF_SIZE - 1)) {
		/* in case of buffer overflow */
		DPRINTK(1, "rx buffer overflow \n");
		goto error_out;
	}
	rx_buffer = &priv->rx_dev.rx_dev_buff[priv->rx_dev.qtail];

	retval =
	    ks7010_sdio_read(priv, DATA_WINDOW, &rx_buffer->data[0],
			     hif_align_size(size));
	if (retval) {
		goto error_out;
	}

	/* length check */
	if (size > 2046 || size == 0) {
#ifdef KS_WLAN_DEBUG
		if (KS_WLAN_DEBUG > 5)
			print_hex_dump_bytes("INVALID DATA dump: ",
					     DUMP_PREFIX_OFFSET,
					     rx_buffer->data, 32);
#endif
		/* rx_status update */
		read_status = READ_STATUS_IDLE;
		retval =
		    ks7010_sdio_write(priv, READ_STATUS, &read_status,
				      sizeof(read_status));
		if (retval) {
			DPRINTK(1, " error : READ_STATUS=%02X\n", read_status);
		}
		goto error_out;
	}

	hdr = (struct hostif_hdr *)&rx_buffer->data[0];
	rx_buffer->size = le16_to_cpu(hdr->size) + sizeof(hdr->size);
	event = hdr->event;
	inc_rxqtail(priv);

	/* read status update */
	read_status = READ_STATUS_IDLE;
	retval =
	    ks7010_sdio_write(priv, READ_STATUS, &read_status,
			      sizeof(read_status));
	if (retval) {
		DPRINTK(1, " error : READ_STATUS=%02X\n", read_status);
	}
	DPRINTK(4, "READ_STATUS=%02X\n", read_status);

	if (atomic_read(&priv->psstatus.confirm_wait)) {
		if (IS_HIF_CONF(event)) {
			DPRINTK(4, "IS_HIF_CONF true !!\n");
			atomic_dec(&priv->psstatus.confirm_wait);
		}
	}

	/* rx_event_task((void *)priv); */
	tasklet_schedule(&priv->ks_wlan_hw.rx_bh_task);

 error_out:
	return;
}
Ejemplo n.º 8
0
int _ks_wlan_hw_power_save(struct ks_wlan_private *priv)
{
	int rc = 0;
	unsigned char rw_data;
	int retval;

	if (priv->reg.powermgt == POWMGT_ACTIVE_MODE)
		return rc;

	if (priv->reg.operation_mode == MODE_INFRASTRUCTURE &&
	    (priv->connect_status & CONNECT_STATUS_MASK) == CONNECT_STATUS) {

		//DPRINTK(1,"psstatus.status=%d\n",atomic_read(&priv->psstatus.status));
		if (priv->dev_state == DEVICE_STATE_SLEEP) {
			switch (atomic_read(&priv->psstatus.status)) {
			case PS_SNOOZE:	/* 4 */
				break;
			default:
				DPRINTK(5, "\npsstatus.status=%d\npsstatus.confirm_wait=%d\npsstatus.snooze_guard=%d\ncnt_txqbody=%d\n",
					atomic_read(&priv->psstatus.status),
					atomic_read(&priv->psstatus.confirm_wait),
					atomic_read(&priv->psstatus.snooze_guard),
					cnt_txqbody(priv));

				if (!atomic_read(&priv->psstatus.confirm_wait)
				    && !atomic_read(&priv->psstatus.snooze_guard)
				    && !cnt_txqbody(priv)) {
					retval =
					    ks7010_sdio_read(priv, INT_PENDING,
							     &rw_data,
							     sizeof(rw_data));
					if (retval) {
						DPRINTK(1,
							" error : INT_PENDING=%02X\n",
							rw_data);
						queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
								   &priv->ks_wlan_hw.rw_wq, 1);
						break;
					}
					if (!rw_data) {
						rw_data = GCR_B_DOZE;
						retval =
						    ks7010_sdio_write(priv,
								      GCR_B,
								      &rw_data,
								      sizeof(rw_data));
						if (retval) {
							DPRINTK(1,
								" error : GCR_B=%02X\n",
								rw_data);
							queue_delayed_work
							    (priv->ks_wlan_hw.ks7010sdio_wq,
							     &priv->ks_wlan_hw.rw_wq, 1);
							break;
						}
						DPRINTK(4,
							"PMG SET!! : GCR_B=%02X\n",
							rw_data);
						atomic_set(&priv->psstatus.
							   status, PS_SNOOZE);
						DPRINTK(3,
							"psstatus.status=PS_SNOOZE\n");
					} else {
						queue_delayed_work(priv->ks_wlan_hw.ks7010sdio_wq,
								   &priv->ks_wlan_hw.rw_wq, 1);
					}
				} else {
					queue_delayed_work(priv->ks_wlan_hw.
							   ks7010sdio_wq,
							   &priv->ks_wlan_hw.rw_wq,
							   0);
				}
				break;
			}
		}

	}

	return rc;
}