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; }
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; }
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); }
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; }
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; }
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; }
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; }
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; }