Do not use ShortGI and STBC with management frames; Atheros cards have problems with...
[ralink_drivers/rt2870_fbsd72.git] / rt2870_io.c
blobe3d3d27ed16c4a5583d79862e26b98b8578187c5
2 /*-
3 * Copyright (c) 2009-2010 Alexander Egorenkov <egorenar@gmail.com>
4 * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include "rt2870_io.h"
20 #include "rt2870_reg.h"
23 * Defines and macros
26 #define RT2870_IO_USB_REQ_MCU_CNTL 0x1
27 #define RT2870_IO_USB_REQ_MAC_WRITE_MULTI 0x2
28 #define RT2870_IO_USB_REQ_MAC_READ_MULTI 0x7
29 #define RT2870_IO_USB_REQ_EEPROM_READ_MULTI 0x9
31 #define RT2870_IO_USB_VALUE_MCU_RESET 0x1
32 #define RT2870_IO_USB_VALUE_MCU_RUN 0x8
34 #define RT2870_IO_BYTE_CRC16(byte, crc) \
35 ((uint16_t) (((crc) << 8) ^ rt2870_io_ccitt16[(((crc) >> 8) ^ (byte)) & 255]))
38 * Static function prototypes
41 static int rt2870_io_vendor_req(struct rt2870_softc *sc,
42 uint8_t reqtype, uint8_t req, uint16_t value, uint16_t index,
43 void *buf, uint16_t len);
45 static uint8_t rt2870_io_byte_rev(uint8_t byte);
48 * Static variables
51 static const uint16_t rt2870_io_ccitt16[] =
53 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
54 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
55 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
56 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
57 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
58 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
59 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
60 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
61 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
62 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
63 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
64 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
65 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
66 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
67 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
68 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
69 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
70 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
71 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
72 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
73 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
74 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
75 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
76 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
77 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
78 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
79 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
80 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
81 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
82 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
83 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
84 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
88 * rt2870_io_mac_read
90 uint32_t rt2870_io_mac_read(struct rt2870_softc *sc, uint16_t reg)
92 uint32_t val;
94 rt2870_io_mac_read_multi(sc, reg, &val, sizeof(val));
96 return le32toh(val);
100 * rt2870_io_mac_read_multi
102 void rt2870_io_mac_read_multi(struct rt2870_softc *sc,
103 uint16_t reg, void *buf, size_t len)
105 int error;
107 error = rt2870_io_vendor_req(sc, UT_READ_VENDOR_DEVICE,
108 RT2870_IO_USB_REQ_MAC_READ_MULTI, 0, reg, buf, len);
109 if (error != 0)
110 printf("%s: could not multi read MAC register: %s\n",
111 device_get_nameunit(sc->dev), usbd_errstr(error));
115 * rt2870_io_mac_write
117 void rt2870_io_mac_write(struct rt2870_softc *sc,
118 uint16_t reg, uint32_t val)
120 uint32_t tmp;
122 tmp = htole32(val);
124 rt2870_io_mac_write_multi(sc, reg, &tmp, sizeof(uint32_t));
128 * rt2870_io_mac_write_multi
130 void rt2870_io_mac_write_multi(struct rt2870_softc *sc,
131 uint16_t reg, const void *buf, size_t len)
133 const uint16_t *ptr;
134 int i, error;
136 len += len % sizeof(uint16_t);
137 ptr = buf;
139 i = 0;
143 error = rt2870_io_vendor_req(sc, UT_WRITE_VENDOR_DEVICE,
144 RT2870_IO_USB_REQ_MAC_WRITE_MULTI, *ptr++, reg + i, NULL, 0);
146 i += sizeof(uint16_t);
147 len -= sizeof(uint16_t);
148 } while (len > 0 && error == 0);
150 if (error != 0)
151 printf("%s: could not multi write MAC register: %s\n",
152 device_get_nameunit(sc->dev), usbd_errstr(error));
156 * rt2870_io_mac_set_region_4
158 void rt2870_io_mac_set_region_4(struct rt2870_softc *sc,
159 uint16_t reg, uint32_t val, size_t len)
161 int i;
163 for (i = 0; i < len; i += sizeof(uint32_t))
164 rt2870_io_mac_write(sc, reg + i, val);
168 * rt2870_io_eeprom_read
170 uint16_t rt2870_io_eeprom_read(struct rt2870_softc *sc, uint16_t addr)
172 uint16_t val;
174 rt2870_io_eeprom_read_multi(sc, addr, &val, sizeof(val));
176 return le16toh(val);
180 * rt2870_io_eeprom_read_multi
182 void rt2870_io_eeprom_read_multi(struct rt2870_softc *sc,
183 uint16_t addr, void *buf, size_t len)
185 int error;
187 error = rt2870_io_vendor_req(sc, UT_READ_VENDOR_DEVICE,
188 RT2870_IO_USB_REQ_EEPROM_READ_MULTI, 0, addr, buf, len);
189 if (error != 0)
190 printf("%s: could not multi read EEPROM: %s\n",
191 device_get_nameunit(sc->dev), usbd_errstr(error));
195 * rt2870_io_bbp_read
197 uint8_t rt2870_io_bbp_read(struct rt2870_softc *sc, uint8_t reg)
199 uint32_t val;
200 int ntries;
202 for (ntries = 0; ntries < 10; ntries++)
203 if (!(rt2870_io_mac_read(sc, RT2870_REG_BBP_CSR_CFG) &
204 RT2870_REG_BBP_CSR_BUSY))
205 break;
207 if (ntries == 10)
209 printf("%s: could not read BBP\n",
210 device_get_nameunit(sc->dev));
211 return 0;
214 val = RT2870_REG_BBP_CSR_BUSY |
215 RT2870_REG_BBP_CSR_READ |
216 ((reg & RT2870_REG_BBP_REG_MASK) << RT2870_REG_BBP_REG_SHIFT);
218 rt2870_io_mac_write(sc, RT2870_REG_BBP_CSR_CFG, val);
220 for (ntries = 0; ntries < 10; ntries++)
222 val = rt2870_io_mac_read(sc, RT2870_REG_BBP_CSR_CFG);
223 if (!(val & RT2870_REG_BBP_CSR_BUSY))
224 return ((val >> RT2870_REG_BBP_VAL_SHIFT) &
225 RT2870_REG_BBP_VAL_MASK);
227 DELAY(1);
230 printf("%s: could not read BBP\n", device_get_nameunit(sc->dev));
232 return 0;
236 * rt2870_io_bbp_write
238 void rt2870_io_bbp_write(struct rt2870_softc *sc, uint8_t reg, uint8_t val)
240 uint32_t tmp;
241 int ntries;
243 for (ntries = 0; ntries < 10; ntries++)
244 if (!(rt2870_io_mac_read(sc, RT2870_REG_BBP_CSR_CFG) &
245 RT2870_REG_BBP_CSR_BUSY))
246 break;
248 if (ntries == 10)
250 printf("%s: could not write to BBP\n",
251 device_get_nameunit(sc->dev));
252 return;
255 tmp = RT2870_REG_BBP_CSR_BUSY |
256 ((reg & RT2870_REG_BBP_REG_MASK) << RT2870_REG_BBP_REG_SHIFT) |
257 ((val & RT2870_REG_BBP_VAL_MASK) << RT2870_REG_BBP_VAL_SHIFT);
259 rt2870_io_mac_write(sc, RT2870_REG_BBP_CSR_CFG, tmp);
263 * rt2870_io_rf_write
265 void rt2870_io_rf_write(struct rt2870_softc *sc, uint8_t reg, uint32_t val)
267 int ntries;
269 for (ntries = 0; ntries < 10; ntries++)
270 if (!(rt2870_io_mac_read(sc, RT2870_REG_RF_CSR_CFG0) &
271 RT2870_REG_RF_BUSY))
272 break;
274 if (ntries == 10)
276 printf("%s: could not write to RF\n",
277 device_get_nameunit(sc->dev));
278 return;
281 rt2870_io_mac_write(sc, RT2870_REG_RF_CSR_CFG0, val);
285 * rt2870_io_mcu_cmd
287 void rt2870_io_mcu_cmd(struct rt2870_softc *sc, uint8_t cmd,
288 uint8_t token, uint16_t arg)
290 uint32_t tmp;
291 int ntries;
293 for (ntries = 0; ntries < 100; ntries++)
295 if (!(rt2870_io_mac_read(sc, RT2870_REG_H2M_MAILBOX) &
296 RT2870_REG_H2M_BUSY))
297 break;
299 DELAY(2);
302 if (ntries == 100)
304 printf("%s: could not read H2M\n",
305 device_get_nameunit(sc->dev));
306 return;
309 tmp = RT2870_REG_H2M_BUSY | (token << 16) | arg;
311 rt2870_io_mac_write(sc, RT2870_REG_H2M_MAILBOX, tmp);
312 rt2870_io_mac_write(sc, RT2870_REG_H2M_HOST_CMD, cmd);
316 * rt2870_io_mcu_load_ucode
318 int rt2870_io_mcu_load_ucode(struct rt2870_softc *sc,
319 const uint8_t *ucode, size_t len)
321 int i, error, ntries;
322 uint16_t crc;
324 for (i = 0, crc = 0xffff; i < len - 2; i++)
325 crc = RT2870_IO_BYTE_CRC16(rt2870_io_byte_rev(ucode[i]), crc);
327 if (ucode[len - 2] != rt2870_io_byte_rev(crc >> 8) ||
328 ucode[len - 1] != rt2870_io_byte_rev(crc))
330 printf("%s: wrong microcode crc\n",
331 device_get_nameunit(sc->dev));
332 return EINVAL;
335 rt2870_io_mac_write_multi(sc, RT2870_REG_MCU_UCODE_BASE, ucode, len);
337 rt2870_io_mac_write(sc, RT2870_REG_H2M_MAILBOX_CID, 0xffffffff);
338 rt2870_io_mac_write(sc, RT2870_REG_H2M_MAILBOX_STATUS, 0xffffffff);
340 error = rt2870_io_vendor_req(sc, UT_WRITE_VENDOR_DEVICE,
341 RT2870_IO_USB_REQ_MCU_CNTL, RT2870_IO_USB_VALUE_MCU_RUN, 0, NULL, 0);
342 if (error != 0)
344 printf("%s: could not run firmware: %s\n",
345 device_get_nameunit(sc->dev), usbd_errstr(error));
346 return error;
349 for (ntries = 0; ntries < 1000; ntries++)
351 if (rt2870_io_mac_read(sc, RT2870_REG_PBF_SYS_CTRL) &
352 RT2870_REG_MCU_READY)
353 break;
355 DELAY(1000);
358 if (ntries == 1000)
360 printf("%s: timeout waiting for MCU to initialize\n",
361 device_get_nameunit(sc->dev));
362 return ETIMEDOUT;
365 return 0;
369 * rt2870_io_mcu_reset
371 int rt2870_io_mcu_reset(struct rt2870_softc *sc)
373 return rt2870_io_vendor_req(sc, UT_WRITE_VENDOR_DEVICE,
374 RT2870_IO_USB_REQ_MCU_CNTL, RT2870_IO_USB_VALUE_MCU_RESET, 0, NULL, 0);
378 * rt2870_io_vendor_req
380 static int rt2870_io_vendor_req(struct rt2870_softc *sc,
381 uint8_t reqtype, uint8_t req, uint16_t value, uint16_t index,
382 void *buf, uint16_t len)
384 usb_device_request_t usb_req;
385 usbd_status error;
386 int ntries;
388 for (ntries = 0; ntries < 10; ntries++)
390 usb_req.bmRequestType = reqtype;
391 usb_req.bRequest = req;
392 USETW(usb_req.wValue, value);
393 USETW(usb_req.wIndex, index);
394 USETW(usb_req.wLength, len);
396 error = usbd_do_request(sc->usb_dev, &usb_req, buf);
397 if (error == 0)
398 break;
400 DELAY(5000);
403 return error;
407 * rt2870_io_byte_rev
409 static uint8_t rt2870_io_byte_rev(uint8_t byte)
411 int i;
412 uint8_t tmp;
414 for(i = 0, tmp = 0; ; i++)
416 if(byte & 0x80)
417 tmp |= 0x80;
419 if(i == 7)
420 break;
422 byte <<= 1;
423 tmp >>= 1;
426 return tmp;