/** * send test command to firmware * * @wl: wl struct * @buf: buffer containing the command, with all headers, must work with dma * @len: length of the buffer * @answer: is answer needed */ int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer) { int ret; wl1251_debug(DEBUG_CMD, "cmd test"); ret = wl1251_cmd_send(wl, CMD_TEST, buf, buf_len); if (ret < 0) { wl1251_warning("TEST command failed"); return ret; } if (answer) { struct wl1251_command *cmd_answer; /* * The test command got in, we can read the answer. * The answer would be a wl1251_command, where the * parameter array contains the actual answer. */ wl1251_mem_read(wl, wl->cmd_box_addr, buf, buf_len); cmd_answer = buf; if (cmd_answer->header.status != CMD_STATUS_SUCCESS) wl1251_error("TEST command answer error: %d", cmd_answer->header.status); } return 0; }
/** * read acx from firmware * * @wl: wl struct * @id: acx id * @buf: buffer for the response, including all headers, must work with dma * @len: length of buf */ int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len) { struct acx_header *acx = buf; int ret; wl1251_debug(DEBUG_CMD, "cmd interrogate"); acx->id = id; /* payload length, does not include any headers */ acx->len = len - sizeof(*acx); ret = wl1251_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx)); if (ret < 0) { wl1251_error("INTERROGATE command failed"); goto out; } /* the interrogate command got in, we can read the answer */ wl1251_mem_read(wl, wl->cmd_box_addr, buf, len); acx = buf; if (acx->cmd.status != CMD_STATUS_SUCCESS) wl1251_error("INTERROGATE command error: %d", acx->cmd.status); out: return ret; }
int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, struct ieee80211_channel *channels[], unsigned int n_channels, unsigned int n_probes) { struct wl1251_cmd_scan *cmd; int i, ret = 0; wl1251_debug(DEBUG_CMD, "cmd scan"); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) return -ENOMEM; cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); cmd->params.rx_filter_options = cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); cmd->params.scan_options = 0; cmd->params.num_channels = n_channels; cmd->params.num_probe_requests = n_probes; cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */ cmd->params.tid_trigger = 0; for (i = 0; i < n_channels; i++) { cmd->channels[i].min_duration = cpu_to_le32(WL1251_SCAN_MIN_DURATION); cmd->channels[i].max_duration = cpu_to_le32(WL1251_SCAN_MAX_DURATION); memset(&cmd->channels[i].bssid_lsb, 0xff, 4); memset(&cmd->channels[i].bssid_msb, 0xff, 2); cmd->channels[i].early_termination = 0; cmd->channels[i].tx_power_att = 0; cmd->channels[i].channel = channels[i]->hw_value; } cmd->params.ssid_len = ssid_len; if (ssid) memcpy(cmd->params.ssid, ssid, ssid_len); ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd)); if (ret < 0) { wl1251_error("cmd scan failed: %d", ret); goto out; } wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); if (cmd->header.status != CMD_STATUS_SUCCESS) { wl1251_error("cmd scan status wasn't success: %d", cmd->header.status); ret = -EIO; goto out; } out: kfree(cmd); return ret; }
static void wl1251_rx_header(struct wl1251 *wl, struct wl1251_rx_descriptor *desc) { u32 rx_packet_ring_addr; rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr; if (wl->rx_current_buffer) rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; wl1251_mem_read(wl, rx_packet_ring_addr, desc, sizeof(*desc)); }
static void wl1251_rx_body(struct wl1251 *wl, struct wl1251_rx_descriptor *desc) { struct sk_buff *skb; struct ieee80211_rx_status status; u8 *rx_buffer, beacon = 0; u16 length, *fc; u32 curr_id, last_id_inc, rx_packet_ring_addr; length = WL1251_RX_ALIGN(desc->length - PLCP_HEADER_LENGTH); curr_id = (desc->flags & RX_DESC_SEQNUM_MASK) >> RX_DESC_PACKETID_SHIFT; last_id_inc = (wl->rx_last_id + 1) % (RX_MAX_PACKET_ID + 1); if (last_id_inc != curr_id) { wl1251_warning("curr ID:%d, last ID inc:%d", curr_id, last_id_inc); wl->rx_last_id = curr_id; } else { wl->rx_last_id = last_id_inc; } rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr + sizeof(struct wl1251_rx_descriptor) + 20; if (wl->rx_current_buffer) rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; skb = __dev_alloc_skb(length, GFP_KERNEL); if (!skb) { wl1251_error("Couldn't allocate RX frame"); return; } rx_buffer = skb_put(skb, length); wl1251_mem_read(wl, rx_packet_ring_addr, rx_buffer, length); /* The actual length doesn't include the target's alignment */ skb_trim(skb, desc->length - PLCP_HEADER_LENGTH); fc = (u16 *)skb->data; if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) beacon = 1; wl1251_rx_status(wl, desc, &status, beacon); wl1251_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, beacon ? "beacon" : ""); memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); ieee80211_rx_ni(wl->hw, skb); wl1251_update_rate(wl, length); }
/* * Poll the mailbox event field until any of the bits in the mask is set or a * timeout occurs (WL1251_EVENT_TIMEOUT in msecs) */ int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms) { u32 events_vector, event; unsigned long timeout; timeout = jiffies + msecs_to_jiffies(timeout_ms); do { if (time_after(jiffies, timeout)) return -ETIMEDOUT; msleep(1); /* read from both event fields */ wl1251_mem_read(wl, wl->mbox_ptr[0], &events_vector, sizeof(events_vector)); event = events_vector & mask; wl1251_mem_read(wl, wl->mbox_ptr[1], &events_vector, sizeof(events_vector)); event |= events_vector & mask; } while (!event); return 0; }
int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer, size_t len) { struct cmd_read_write_memory *cmd; int ret = 0; wl1251_debug(DEBUG_CMD, "cmd read memory"); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } WARN_ON(len > MAX_READ_SIZE); len = min_t(size_t, len, MAX_READ_SIZE); cmd->addr = addr; cmd->size = len; ret = wl1251_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd)); if (ret < 0) { wl1251_error("read memory command failed: %d", ret); goto out; } /* the read command got in, we can now read the answer */ wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); if (cmd->header.status != CMD_STATUS_SUCCESS) wl1251_error("error in read command result: %d", cmd->header.status); memcpy(answer, cmd->value, len); out: kfree(cmd); return ret; }
int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num) { struct event_mailbox mbox; int ret; wl1251_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num); if (mbox_num > 1) return -EINVAL; /* first we read the mbox descriptor */ wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox, sizeof(struct event_mailbox)); /* process the descriptor */ ret = wl1251_event_process(wl, &mbox); if (ret < 0) return ret; /* then we let the firmware know it can go on...*/ wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); return 0; }