linprocfs - Introduce /proc/mounts
[dragonfly.git] / sys / dev / netif / acx / acxcmd.c
blobdc948014504bea5d55d599b7749fdd0240aa5fe2
1 /*
2 * Copyright (c) 2006 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Sepherosa Ziehau <sepherosa@gmail.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
34 * $DragonFly: src/sys/dev/netif/acx/acxcmd.c,v 1.11 2008/06/01 03:58:38 sephe Exp $
37 #include <sys/param.h>
38 #include <sys/bus.h>
39 #include <sys/endian.h>
40 #include <sys/kernel.h>
41 #include <sys/rman.h>
42 #include <sys/socket.h>
43 #include <sys/sysctl.h>
45 #include <net/if.h>
46 #include <net/if_arp.h>
47 #include <net/if_media.h>
49 #include <netproto/802_11/ieee80211_var.h>
50 #include <netproto/802_11/ieee80211_radiotap.h>
51 #include <netproto/802_11/wlan_ratectl/amrr/ieee80211_amrr_param.h>
52 #include <netproto/802_11/wlan_ratectl/onoe/ieee80211_onoe_param.h>
54 #define ACX_DEBUG
56 #include <dev/netif/acx/if_acxreg.h>
57 #include <dev/netif/acx/if_acxvar.h>
58 #include <dev/netif/acx/acxcmd.h>
60 #define CMDPRM_WRITE_REGION_1(sc, r, rlen) \
61 bus_space_write_region_1((sc)->sc_mem2_bt, \
62 (sc)->sc_mem2_bh, \
63 (sc)->sc_cmd_param, \
64 (const uint8_t *)(r), (rlen))
66 #define CMDPRM_READ_REGION_1(sc, r, rlen) \
67 bus_space_read_region_1((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, \
68 (sc)->sc_cmd_param, (uint8_t *)(r), (rlen))
71 * This will clear previous command's
72 * execution status too
74 #define CMD_WRITE_4(sc, val) \
75 bus_space_write_4((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, \
76 (sc)->sc_cmd, (val))
77 #define CMD_READ_4(sc) \
78 bus_space_read_4((sc)->sc_mem2_bt, (sc)->sc_mem2_bh, (sc)->sc_cmd)
81 * acx command register layerout:
82 * upper 16bits are command execution status
83 * lower 16bits are command to be executed
85 #define ACX_CMD_STATUS_SHIFT 16
86 #define ACX_CMD_STATUS_OK 1
88 struct radio_init {
89 uint32_t radio_ofs; /* radio firmware offset */
90 uint32_t radio_len; /* radio firmware length */
91 } __packed;
93 struct bss_join_hdr {
94 uint8_t bssid[IEEE80211_ADDR_LEN];
95 uint16_t beacon_intvl;
96 uint8_t chip_spec[3];
97 uint8_t ndata_txrate; /* see ACX_NDATA_TXRATE_ */
98 uint8_t ndata_txopt; /* see ACX_NDATA_TXOPT_ */
99 uint8_t mode; /* see ACX_MODE_ */
100 uint8_t channel;
101 uint8_t esslen;
102 char essid[1];
103 } __packed;
106 * non-data frame tx rate
108 #define ACX_NDATA_TXRATE_1 10 /* 1Mbits/s */
109 #define ACX_NDATA_TXRATE_2 20 /* 2Mbits/s */
112 * non-data frame tx options
114 #define ACX_NDATA_TXOPT_PBCC 0x40
115 #define ACX_NDATA_TXOPT_OFDM 0x20
116 #define ACX_NDATA_TXOPT_SHORT_PREAMBLE 0x10
118 #define BSS_JOIN_BUFLEN \
119 (sizeof(struct bss_join_hdr) + IEEE80211_NWID_LEN)
120 #define BSS_JOIN_PARAM_SIZE(bj) \
121 (sizeof(struct bss_join_hdr) + (bj)->esslen)
123 void
124 acx_init_cmd_reg(struct acx_softc *sc)
126 sc->sc_cmd = CSR_READ_4(sc, ACXREG_CMD_REG_OFFSET);
127 sc->sc_cmd_param = sc->sc_cmd + ACX_CMD_REG_SIZE;
129 /* Clear command & status */
130 CMD_WRITE_4(sc, 0);
134 acx_join_bss(struct acx_softc *sc, uint8_t mode, struct ieee80211_node *ni,
135 struct ieee80211_channel *c)
137 uint8_t bj_buf[BSS_JOIN_BUFLEN];
138 struct ieee80211com *ic = &sc->sc_ic;
139 struct bss_join_hdr *bj;
140 int i;
142 bzero(bj_buf, sizeof(bj_buf));
143 bj = (struct bss_join_hdr *)bj_buf;
145 for (i = 0; i < IEEE80211_ADDR_LEN; ++i)
146 bj->bssid[i] = ni->ni_bssid[IEEE80211_ADDR_LEN - i - 1];
148 bj->beacon_intvl = htole16(ni->ni_intval);
150 sc->chip_set_bss_join_param(sc, bj->chip_spec, ic->ic_dtim_period);
152 bj->ndata_txrate = ACX_NDATA_TXRATE_1;
153 bj->ndata_txopt = 0;
154 bj->mode = mode;
155 bj->channel = ieee80211_chan2ieee(ic, c);
156 bj->esslen = ni->ni_esslen;
157 bcopy(ni->ni_essid, bj->essid, ni->ni_esslen);
159 DPRINTF((&ic->ic_if, "join BSS/IBSS on channel %d\n", bj->channel));
160 return acx_exec_command(sc, ACXCMD_JOIN_BSS,
161 bj, BSS_JOIN_PARAM_SIZE(bj), NULL, 0);
165 acx_enable_txchan(struct acx_softc *sc, uint8_t chan)
167 return acx_exec_command(sc, ACXCMD_ENABLE_TXCHAN, &chan, sizeof(chan),
168 NULL, 0);
172 acx_enable_rxchan(struct acx_softc *sc, uint8_t chan)
174 return acx_exec_command(sc, ACXCMD_ENABLE_RXCHAN, &chan, sizeof(chan),
175 NULL, 0);
179 acx_get_conf(struct acx_softc *sc, uint16_t conf_id, void *conf,
180 uint16_t conf_len)
182 struct acx_conf *confcom;
184 if (conf_len < sizeof(*confcom)) {
185 if_printf(&sc->sc_ic.ic_if, "%s configure data is too short\n",
186 __func__);
187 return 1;
190 confcom = conf;
191 confcom->conf_id = htole16(conf_id);
192 confcom->conf_data_len = htole16(conf_len - sizeof(*confcom));
194 return acx_exec_command(sc, ACXCMD_GET_CONF, confcom, sizeof(*confcom),
195 conf, conf_len);
199 acx_set_conf(struct acx_softc *sc, uint16_t conf_id, void *conf,
200 uint16_t conf_len)
202 struct acx_conf *confcom;
204 if (conf_len < sizeof(*confcom)) {
205 if_printf(&sc->sc_ic.ic_if, "%s configure data is too short\n",
206 __func__);
207 return 1;
210 confcom = conf;
211 confcom->conf_id = htole16(conf_id);
212 confcom->conf_data_len = htole16(conf_len - sizeof(*confcom));
214 return acx_exec_command(sc, ACXCMD_SET_CONF, conf, conf_len, NULL, 0);
218 acx_set_tmplt(struct acx_softc *sc, uint16_t cmd, void *tmplt,
219 uint16_t tmplt_len)
221 uint16_t *size;
223 if (tmplt_len < sizeof(*size)) {
224 if_printf(&sc->sc_ic.ic_if, "%s template is too short\n",
225 __func__);
226 return 1;
229 size = tmplt;
230 *size = htole16(tmplt_len - sizeof(*size));
232 return acx_exec_command(sc, cmd, tmplt, tmplt_len, NULL, 0);
236 acx_init_radio(struct acx_softc *sc, uint32_t radio_ofs, uint32_t radio_len)
238 struct radio_init r;
240 r.radio_ofs = htole32(radio_ofs);
241 r.radio_len = htole32(radio_len);
242 return acx_exec_command(sc, ACXCMD_INIT_RADIO, &r, sizeof(r), NULL, 0);
246 acx_exec_command(struct acx_softc *sc, uint16_t cmd, void *param,
247 uint16_t param_len, void *result, uint16_t result_len)
249 uint16_t status;
250 int i, ret;
252 ASSERT_SERIALIZED(sc->sc_ic.ic_if.if_serializer);
254 if ((sc->sc_flags & ACX_FLAG_FW_LOADED) == 0) {
255 if_printf(&sc->sc_ic.ic_if, "cmd 0x%04x failed (base firmware "
256 "not loaded)", cmd);
257 return 1;
260 ret = 0;
262 if (param != NULL && param_len != 0) {
263 /* Set command param */
264 CMDPRM_WRITE_REGION_1(sc, param, param_len);
267 /* Set command */
268 CMD_WRITE_4(sc, cmd);
270 /* Exec command */
271 CSR_WRITE_2(sc, ACXREG_INTR_TRIG, ACXRV_TRIG_CMD_FINI);
272 DELAY(50); /* XXX maybe 100 */
274 /* Wait for command to complete */
275 if (cmd == ACXCMD_INIT_RADIO) {
276 /* XXX radio initialization is extremely long */
277 tsleep(&cmd, 0, "rdinit", (150 * hz) / 1000); /* 150ms */
280 #define CMDWAIT_RETRY_MAX 1000
281 for (i = 0; i < CMDWAIT_RETRY_MAX; ++i) {
282 uint16_t reg;
284 reg = CSR_READ_2(sc, ACXREG_INTR_STATUS);
285 if (reg & ACXRV_INTR_CMD_FINI) {
286 CSR_WRITE_2(sc, ACXREG_INTR_ACK, ACXRV_INTR_CMD_FINI);
287 break;
289 DELAY(50);
291 if (i == CMDWAIT_RETRY_MAX) {
292 if_printf(&sc->sc_ic.ic_if, "cmd %04x failed (timeout)\n", cmd);
293 ret = 1;
294 goto back;
296 #undef CMDWAIT_RETRY_MAX
298 /* Get command exec status */
299 status = (CMD_READ_4(sc) >> ACX_CMD_STATUS_SHIFT);
300 if (status != ACX_CMD_STATUS_OK) {
301 if_printf(&sc->sc_ic.ic_if, "cmd %04x failed\n", cmd);
302 ret = 1;
303 goto back;
306 if (result != NULL && result_len != 0) {
307 /* Get command result */
308 CMDPRM_READ_REGION_1(sc, result, result_len);
311 back:
312 CMD_WRITE_4(sc, 0);
313 return ret;