misc: Fix typos in comments
[qemu/ar7.git] / hw / net / atheros_wlan_io.c
blob8b69e8609bf546d88d37f1e8accf0f1aa7e94518
1 /**
2 * QEMU WLAN device emulation
4 * Copyright (c) 2008 Clemens Kolbitsch
5 * Copyright (c) 2009-2011 Stefan Weil
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
25 * Modifications:
26 * 2008-February-24 Clemens Kolbitsch :
27 * New implementation based on ne2000.c
32 #include "config-host.h"
34 #if defined(CONFIG_WIN32)
35 #warning("not compiled for Windows host")
36 #else
38 #include "hw.h"
39 #include "pci/pci.h"
40 #include "pc.h"
41 #include "net/net.h"
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <sys/types.h>
46 #include <sys/shm.h>
47 #include <sys/stat.h>
48 #include <sys/socket.h>
49 #include <sys/ipc.h>
50 #include <sys/sem.h>
51 #include <sys/mman.h>
52 #include <netinet/in.h>
53 #include <netdb.h>
54 #include <string.h>
55 #include <unistd.h>
56 #include <fcntl.h>
58 #include <signal.h>
60 #include <time.h>
61 #include <sys/time.h>
63 #include "hw/atheros_wlan.h"
64 #include "hw/atheros_wlan_ap.h"
65 #include "hw/atheros_wlan_io.h"
68 * MadWifi OPENHAL atheros constants
70 #include "hw/ath5k.h"
71 #include "hw/ath5k_hw.h"
72 #include "hw/ath5kreg.h"
75 static const struct Atheros_WLAN_frequency Atheros_WLAN_frequency_data[] = {
76 { 20689, 3077, 2412 }, /* channel 1 */
77 { 20715, 3078, 2417 }, /* channel 2 */
78 { 20689, 3079, 2422 }, /* channel 3 */
79 { 20715, 3079, 2427 }, /* channel 4 */
80 { 20529, 3076, 2432 }, /* channel 5 */
81 { 20507, 3078, 2437 }, /* channel 6 */
82 { 20529, 3078, 2442 }, /* channel 7 */
83 { 20507, 3079, 2447 }, /* channel 8 */
84 { 20529, 3077, 2452 }, /* channel 9 */
85 { 20635, 3078, 2457 }, /* channel 10 */
86 { 20529, 3079, 2462 }, /* channel 11 */
87 { 20635, 3079, 2467 }, /* channel 12 */
88 { 20657, 3076, 2472 }, /* channel 13 */
89 { 20529, 1029, 2484 } /* channel 14 */
93 * NOTE: By using this function instead
94 * of accessing the array directly through
95 * an index, we can leave out parts of the
96 * EEPROM data!!
98 static int get_eeprom_data(Atheros_WLANState *s, uint32_t addr, uint32_t *val)
100 if (val == NULL) {
101 return 1;
104 /* why?? but seems necessary... */
105 addr--;
107 if (addr > s->eeprom_size) {
108 return 2;
111 *val = s->eeprom_data[addr];
112 return 0;
120 static void updateFrequency(Atheros_WLANState *s)
122 int i;
123 uint32_t new_frequency = 0;
124 for (i = 0; i < ARRAY_SIZE(Atheros_WLAN_frequency_data); i++) {
125 if (Atheros_WLAN_frequency_data[i].value1 !=
126 s->current_frequency_partial_data[0]) {
127 continue;
130 if (Atheros_WLAN_frequency_data[i].value2 !=
131 s->current_frequency_partial_data[1]) {
132 continue;
135 new_frequency = Atheros_WLAN_frequency_data[i].frequency;
136 break;
139 if (new_frequency) {
140 s->current_frequency = new_frequency;
146 static uint32_t mm_readl(Atheros_WLANState *s, hwaddr addr);
147 static void mm_writel(Atheros_WLANState *s, hwaddr addr,
148 uint32_t val);
150 static void Atheros_WLAN_mmio_writeb(void *opaque, hwaddr addr,
151 uint32_t val)
153 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
154 DEBUG_PRINT(("mmio_writeb " TARGET_FMT_plx " val %x\n", addr, val));
155 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
158 static void Atheros_WLAN_mmio_writew(void *opaque, hwaddr addr,
159 uint32_t val)
161 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
162 DEBUG_PRINT(("mmio_writew " TARGET_FMT_plx " val %x\n", addr, val));
163 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
166 static void Atheros_WLAN_mmio_writel(void *opaque, hwaddr addr,
167 uint32_t val)
169 mm_writel(opaque, Atheros_WLAN_MEM_SANITIZE(addr), val);
170 DEBUG_PRINT((" through call: mmio_writel " TARGET_FMT_plx
171 " val 0x%x (%u)\n",
172 Atheros_WLAN_MEM_SANITIZE(addr), val, val));
175 static uint32_t Atheros_WLAN_mmio_readb(void *opaque, hwaddr addr)
177 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
178 DEBUG_PRINT(("mmio_readb " TARGET_FMT_plx "\n", addr));
179 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
181 return 0;
184 static uint32_t Atheros_WLAN_mmio_readw(void *opaque, hwaddr addr)
186 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
187 DEBUG_PRINT(("mmio_readw " TARGET_FMT_plx "\n", addr));
188 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
190 return 0;
193 static uint32_t Atheros_WLAN_mmio_readl(void *opaque, hwaddr addr)
195 uint32_t val;
196 val = mm_readl(opaque, Atheros_WLAN_MEM_SANITIZE(addr));
198 DEBUG_PRINT((" mmio_readl " TARGET_FMT_plx " = 0x%x (%u)\n",
199 Atheros_WLAN_MEM_SANITIZE(addr), val, val));
200 return val;
203 static uint64_t Atheros_WLAN_read(void *opaque, hwaddr addr,
204 unsigned size)
206 Atheros_WLANState *s = opaque;
207 uint64_t val;
208 switch (size) {
209 case 1:
210 val = Atheros_WLAN_mmio_readb(s, addr);
211 break;
212 case 2:
213 val = Atheros_WLAN_mmio_readw(s, addr);
214 break;
215 case 4:
216 val = Atheros_WLAN_mmio_readl(s, addr);
217 break;
218 default:
219 assert(!"bad size");
221 return val;
224 static void Atheros_WLAN_write(void *opaque, hwaddr addr,
225 uint64_t val, unsigned size)
227 Atheros_WLANState *s = opaque;
228 switch (size) {
229 case 1:
230 Atheros_WLAN_mmio_writeb(s, addr, val);
231 break;
232 case 2:
233 Atheros_WLAN_mmio_writew(s, addr, val);
234 break;
235 case 4:
236 Atheros_WLAN_mmio_writel(s, addr, val);
237 break;
238 default:
239 assert(!"bad size");
243 static const MemoryRegionOps Atheros_WLAN_ops = {
244 .read = Atheros_WLAN_read,
245 .write = Atheros_WLAN_write,
246 .endianness = DEVICE_LITTLE_ENDIAN,
249 void Atheros_WLAN_setup_io(PCIAtheros_WLANState *d)
251 Atheros_WLANState *s = &d->Atheros_WLAN;
253 memory_region_init_io(&s->mmio_bar, &Atheros_WLAN_ops, s, "atheros_mmio",
254 Atheros_WLAN_MEM_SIZE);
255 pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio_bar);
260 #define FASTBINLOG(x) \
261 (x == 1) ? 0 : \
262 (x == 2) ? 1 : \
263 (x == 4) ? 2 : \
264 (x == 8) ? 3 : \
265 (x == 16) ? 4 : \
266 (x == 32) ? 5 : \
267 (x == 64) ? 6 : \
268 (x == 128) ? 7 : \
269 (x == 256) ? 8 : \
270 (x == 512) ? 9 : \
271 (x == 1024) ? 10 : \
272 (x == 2048) ? 11 : \
273 (x == 4096) ? 12 : 13
277 static uint32_t mm_readl(Atheros_WLANState *s, hwaddr addr)
279 uint32_t val = GET_MEM_L(s->mem, addr);
280 switch (addr) {
281 case ATH_HW_IRQ_PENDING:
283 * This indicates that the interrupt
284 * routine has been called. reset interrupt
285 * status and put the interrupt-status
286 * number at the correct memory-location
288 * In case multiple interrupts are pending
289 * this memory-location is checked multiple
290 * times... each time, we put another interrupt
291 * status into memory until no more interrupts
292 * have to be handled
294 Atheros_WLAN_disable_irq(s);
296 DEBUG_PRINT((">> irq pending? ... 0x%x\n", val));
297 SET_MEM_L(s->mem, 0x0080, 0x0);
298 SET_MEM_L(s->mem, 0x80ec, 0x0001c680);
299 SET_MEM_L(s->mem, 0x80f0, 0x000055dc);
300 SET_MEM_L(s->mem, 0x80f8, 0x0015f6fc);
301 SET_MEM_L(s->mem, 0x9850, 0x0de8b0da);
302 break;
305 * The following registers are Read-and-Clear
306 * registers --> must be reset after a read!!
308 * However, it does not work when using linux!!
310 case AR5K_PISR:
311 if (s->device_driver_type == WINXP_DRIVER) {
312 addr = AR5K_RAC_PISR;
313 /* fall through... */
314 } else {
315 break;
318 case AR5K_RAC_PISR:
319 Atheros_WLAN_update_irq(s);
320 val = GET_MEM_L(s->mem, addr);
321 SET_MEM_L(s->mem, addr, 0);
322 SET_MEM_L(s->mem, AR5K_PCICFG, 0x34);
324 DEBUG_PRINT((">> irq status 0x%x\n", val));
325 break;
327 case AR5K_RAC_SISR0:
328 case AR5K_RAC_SISR1:
329 case AR5K_RAC_SISR2:
330 case AR5K_RAC_SISR3:
331 case AR5K_RAC_SISR4:
332 val = 0;
333 SET_MEM_L(s->mem, addr, 0);
334 DEBUG_PRINT(("secondary irq status\n"));
335 break;
339 * According to the openHAL source
340 * documentation this is also read-and-clear
341 * but if it is made so, the WinDriver does
342 * not work any more...
344 case AR5K_RXDP:
345 /* SET_MEM_L(s->mem, addr, 0); */
346 break;
348 default:
349 break;
351 return val;
354 static void mm_writel(Atheros_WLANState *s, hwaddr addr,
355 uint32_t val)
357 uint32_t h;
358 switch (addr) {
360 /******************************************************************
362 * ath5k_hw_init ---> ath5k_hw_nic_wakeup
364 ******************************************************************/
366 case AR5K_RESET_CTL:
368 if (val == (AR5K_RESET_CTL_CHIP | AR5K_RESET_CTL_PCI)) {
369 /* ath5k_hw.c: 613 */
370 DEBUG_PRINT(("reset device (MAC + PCI)\n"));
373 * claim device is inited
375 SET_MEM_L(s->mem, AR5K_STA_ID1, 0);
376 SET_MEM_L(s->mem, AR5K_RESET_CTL, 3);
377 } else if (val & (AR5K_RESET_CTL_CHIP | AR5K_RESET_CTL_PCI)) {
378 /* ath5k_hw.c: 613 */
379 DEBUG_PRINT(("reset device (MAC + PCI + ?)\n"));
382 * claim device is inited
384 SET_MEM_L(s->mem, AR5K_STA_ID1, 0);
385 SET_MEM_L(s->mem, AR5K_RESET_CTL, 3);
386 } else {
387 /* ath5k_hw.c: 626 */
388 DEBUG_PRINT(("reset device (generic)\n"));
391 * warm-start device
393 SET_MEM_L(s->mem, AR5K_RESET_CTL, 0);
395 break;
398 /******************************************************************
400 * interrupt handling
402 ******************************************************************/
404 case AR5K_IER:
405 if (val == AR5K_IER_DISABLE) {
406 /* ath5k_hw.c: 1636 */
407 DEBUG_PRINT(("disabling interrupts\n"));
408 SET_MEM_L(s->mem, AR5K_GPIODO, 0x0);
409 SET_MEM_L(s->mem, AR5K_GPIODI, 0x0);
411 s->interrupt_enabled = 0;
412 } else if (val == AR5K_IER_ENABLE) {
413 /* ath5k_hw.c: 1674 */
414 DEBUG_PRINT(("enabling interrupts\n"));
415 SET_MEM_L(s->mem, AR5K_GPIODO, 0x2);
416 SET_MEM_L(s->mem, AR5K_GPIODI, 0x3); /* new */
418 s->interrupt_enabled = 1;
419 } else {
420 DEBUG_PRINT(("setting interrupt-enable to undefined value!!\n"));
422 break;
424 case AR5K_GPIODO:
425 if (val == 0x2) {
426 SET_MEM_L(s->mem, AR5K_GPIODI, 0x3);
428 break;
430 case AR5K_GPIODI: /* new */
431 if (val == 0x2) {
432 SET_MEM_L(s->mem, AR5K_GPIODO, 0x3);
434 break;
436 case AR5K_PIMR:
437 /* ath5k_hw.c: 1668 */
438 DEBUG_PRINT(("setting primary interrupt-mask to 0x%x (%u)\n",
439 val, val));
440 s->interrupt_p_mask = val;
442 SET_MEM_L(s->mem, addr, val);
443 break;
445 case AR5K_SIMR0:
446 DEBUG_PRINT(("setting secondary interrupt-mask 0 to 0x%x (%u)\n",
447 val, val));
448 s->interrupt_s_mask[0] = val;
449 break;
450 case AR5K_SIMR1:
451 DEBUG_PRINT(("setting secondary interrupt-mask 1 to 0x%x (%u)\n",
452 val, val));
453 s->interrupt_s_mask[1] = val;
454 break;
455 case AR5K_SIMR2:
456 DEBUG_PRINT(("setting secondary interrupt-mask 2 to 0x%x (%u)\n",
457 val, val));
458 s->interrupt_s_mask[2] = val;
459 break;
460 case AR5K_SIMR3:
461 DEBUG_PRINT(("setting secondary interrupt-mask 3 to 0x%x (%u)\n",
462 val, val));
463 s->interrupt_s_mask[3] = val;
464 break;
465 case AR5K_SIMR4:
466 DEBUG_PRINT(("setting secondary interrupt-mask 4 to 0x%x (%u)\n",
467 val, val));
468 s->interrupt_s_mask[4] = val;
469 break;
471 /******************************************************************
473 * ath5k queuing (for transmit and receive buffers)
475 ******************************************************************/
477 case AR5K_QCU_TXE:
478 /* ath5k_hw.c: 1423ff */
480 /* enable specified queue (nr in val) */
481 val = FASTBINLOG(val);
483 DEBUG_PRINT(("queue %u enabled\n", val));
484 if (val < 16) {
485 s->transmit_queue_enabled[val] = 1;
486 Atheros_WLAN_handleTxBuffer(s, val);
487 } else {
488 DEBUG_PRINT(("unknown queue 0x%x (%u)\n", val, val));
490 break;
492 case AR5K_QCU_TXD:
493 /* ath5k_hw.c: 1423ff */
495 /* disable specified queue (nr in val) */
496 val = FASTBINLOG(val);
498 DEBUG_PRINT(("queue %u disabled\n", val));
499 if (val < 16) {
500 s->transmit_queue_enabled[val] = 0;
501 } else {
502 DEBUG_PRINT(("unknown queue 0x%x (%u)\n", val, val));
504 break;
506 case AR5K_IFS0:
507 case AR5K_IFS1:
508 DEBUG_PRINT(("TODO: find out what inter frame spacing registers are used for...\n"));
509 break;
511 case AR5K_CFG:
512 if (val == AR5K_INIT_CFG) {
513 /* ath5k_hw.c: 1261 */
514 DEBUG_PRINT(("Reset configuration register (for hw bitswap)\n"));
516 SET_MEM_L(s->mem, AR5K_SLEEP_CTL, 0x0);
517 break;
519 case AR5K_TXCFG:
520 /* ath5k_hw.c: 1122 */
521 DEBUG_PRINT(("Setting transmit queue size to %u byte\n",
522 (1 << (val + 2))));
524 s->transmit_queue_size = (1 << (val + 2));
525 break;
527 case AR5K_CR:
528 if (val == AR5K_CR_TXE0) { /* TX Enable for queue 0 on 5210 */
529 DEBUG_PRINT(("TX enable for queue 0\n"));
530 } else if (val == AR5K_CR_TXE1) { /* TX Enable for queue 1 on 5210 */
531 DEBUG_PRINT(("TX enable for queue 1\n"));
532 } else if (val == AR5K_CR_RXE) { /* RX Enable */
533 DEBUG_PRINT(("RX enable\n"));
534 SET_MEM_L(s->mem, AR5K_DIAG_SW_5211, 0x0);
535 } else if (val == AR5K_CR_TXD0) { /* TX Disable for queue 0 on 5210 */
536 DEBUG_PRINT(("TX disable for queue 0\n"));
537 } else if (val == AR5K_CR_TXD1) { /* TX Disable for queue 1 on 5210 */
538 DEBUG_PRINT(("TX disable for queue 1\n"));
539 } else if (val == AR5K_CR_RXD) { /* RX Disable */
540 DEBUG_PRINT(("RX disable\n"));
541 } else if (val == AR5K_CR_SWI) { /* unknown... */
543 DEBUG_PRINT(("Undefined TX/RX en/disable CR_SWI\n"));
544 } else {
545 DEBUG_PRINT(("Undefined TX/RX en/disable\n"));
547 break;
549 case AR5K_RXDP:
551 * unknown location, but this should
552 * set the location of the receive
553 * buffer's PHYSICAL address!!
555 DEBUG_PRINT(("Setting receive queue to address 0x%x (%u)\n",
556 val, val));
559 * This address will be queried again
560 * later... store it!!
562 if (val == 0) {
563 /* hm... ar5424 resets its queue to 0 :-( */
565 SET_MEM_L(s->mem, addr, val);
566 s->receive_queue_address = (hwaddr)val;
569 * Madwifi hack: we allow only a certain
570 * number of packets in the receive queue!!
572 s->receive_queue_count = 0;
573 break;
575 case AR5K_QUEUE_TXDP(0):
576 case AR5K_QUEUE_TXDP(1):
577 case AR5K_QUEUE_TXDP(2):
578 case AR5K_QUEUE_TXDP(3):
579 case AR5K_QUEUE_TXDP(4):
580 case AR5K_QUEUE_TXDP(5):
581 case AR5K_QUEUE_TXDP(6):
582 case AR5K_QUEUE_TXDP(7):
583 case AR5K_QUEUE_TXDP(8):
584 case AR5K_QUEUE_TXDP(9):
585 case AR5K_QUEUE_TXDP(10):
586 case AR5K_QUEUE_TXDP(11):
587 case AR5K_QUEUE_TXDP(12):
588 case AR5K_QUEUE_TXDP(13):
589 case AR5K_QUEUE_TXDP(14):
590 case AR5K_QUEUE_TXDP(15):
592 * unknown location, but this should
593 * set the location of queue-dependent
594 * transmit buffer's PHYSICAL address!!
596 DEBUG_PRINT(("Setting a transmit queue to address 0x%x (%u)\n",
597 val, val));
600 * This address will be queried again
601 * later... store it!!
603 SET_MEM_L(s->mem, addr, val);
605 addr -= AR5K_QCU_TXDP_BASE;
606 addr /= 4;
607 if (addr < 16) {
609 * In case the given address specifies a
610 * valid DMA address, let's use it and copy
611 * the data into our device and process it
612 * once the queue is enabled
614 s->transmit_queue_processed[addr] = 0;
615 s->transmit_queue_address[addr] = (hwaddr)val;
616 } else {
617 DEBUG_PRINT(("unknown queue " TARGET_FMT_plx "\n", addr));
619 break;
621 case AR5K_RXCFG:
622 /* ath5k_hw.c: 1124 */
623 DEBUG_PRINT(("Setting receive queue size to %u byte\n",
624 (1 << (val + 2))));
625 SET_MEM_L(s->mem, addr, val);
626 break;
628 case AR5K_QUEUE_QCUMASK(0):
629 case AR5K_QUEUE_QCUMASK(1):
630 case AR5K_QUEUE_QCUMASK(2):
631 case AR5K_QUEUE_QCUMASK(3):
632 case AR5K_QUEUE_QCUMASK(4):
633 case AR5K_QUEUE_QCUMASK(5):
634 case AR5K_QUEUE_QCUMASK(6):
635 case AR5K_QUEUE_QCUMASK(7):
636 case AR5K_QUEUE_QCUMASK(8):
637 case AR5K_QUEUE_QCUMASK(9):
638 case AR5K_QUEUE_QCUMASK(10):
639 case AR5K_QUEUE_QCUMASK(11):
640 case AR5K_QUEUE_QCUMASK(12):
641 case AR5K_QUEUE_QCUMASK(13):
642 case AR5K_QUEUE_QCUMASK(14):
643 case AR5K_QUEUE_QCUMASK(15):
644 DEBUG_PRINT(("ath5k_hw_reset_tx_queue for queue x (%u)\n", val));
645 break;
647 case AR5K_QUEUE_DFS_RETRY_LIMIT(0):
648 case AR5K_QUEUE_DFS_RETRY_LIMIT(1):
649 case AR5K_QUEUE_DFS_RETRY_LIMIT(2):
650 case AR5K_QUEUE_DFS_RETRY_LIMIT(3):
651 case AR5K_QUEUE_DFS_RETRY_LIMIT(4):
652 case AR5K_QUEUE_DFS_RETRY_LIMIT(5):
653 case AR5K_QUEUE_DFS_RETRY_LIMIT(6):
654 case AR5K_QUEUE_DFS_RETRY_LIMIT(7):
655 case AR5K_QUEUE_DFS_RETRY_LIMIT(8):
656 case AR5K_QUEUE_DFS_RETRY_LIMIT(9):
657 case AR5K_QUEUE_DFS_RETRY_LIMIT(10):
658 case AR5K_QUEUE_DFS_RETRY_LIMIT(11):
659 case AR5K_QUEUE_DFS_RETRY_LIMIT(12):
660 case AR5K_QUEUE_DFS_RETRY_LIMIT(13):
661 case AR5K_QUEUE_DFS_RETRY_LIMIT(14):
662 case AR5K_QUEUE_DFS_RETRY_LIMIT(15):
663 DEBUG_PRINT(("setting retry-limit for queue x to 0x%x (%u)\n",
664 val, val));
665 break;
667 case AR5K_QUEUE_DFS_LOCAL_IFS(0):
668 case AR5K_QUEUE_DFS_LOCAL_IFS(1):
669 case AR5K_QUEUE_DFS_LOCAL_IFS(2):
670 case AR5K_QUEUE_DFS_LOCAL_IFS(3):
671 case AR5K_QUEUE_DFS_LOCAL_IFS(4):
672 case AR5K_QUEUE_DFS_LOCAL_IFS(5):
673 case AR5K_QUEUE_DFS_LOCAL_IFS(6):
674 case AR5K_QUEUE_DFS_LOCAL_IFS(7):
675 case AR5K_QUEUE_DFS_LOCAL_IFS(8):
676 case AR5K_QUEUE_DFS_LOCAL_IFS(9):
677 case AR5K_QUEUE_DFS_LOCAL_IFS(10):
678 case AR5K_QUEUE_DFS_LOCAL_IFS(11):
679 case AR5K_QUEUE_DFS_LOCAL_IFS(12):
680 case AR5K_QUEUE_DFS_LOCAL_IFS(13):
681 case AR5K_QUEUE_DFS_LOCAL_IFS(14):
682 case AR5K_QUEUE_DFS_LOCAL_IFS(15):
683 DEBUG_PRINT(("setting interframe space for queue x to 0x%x (%u)\n",
684 val, val));
685 break;
687 case AR5K_QUEUE_MISC(0):
688 case AR5K_QUEUE_MISC(1):
689 case AR5K_QUEUE_MISC(2):
690 case AR5K_QUEUE_MISC(3):
691 case AR5K_QUEUE_MISC(4):
692 case AR5K_QUEUE_MISC(5):
693 case AR5K_QUEUE_MISC(6):
694 case AR5K_QUEUE_MISC(7):
695 case AR5K_QUEUE_MISC(8):
696 case AR5K_QUEUE_MISC(9):
697 case AR5K_QUEUE_MISC(10):
698 case AR5K_QUEUE_MISC(11):
699 case AR5K_QUEUE_MISC(12):
700 case AR5K_QUEUE_MISC(13):
701 case AR5K_QUEUE_MISC(14):
702 case AR5K_QUEUE_MISC(15):
703 DEBUG_PRINT(("setting options for queue x to 0x%x (%u)\n", val, val));
704 break;
706 case AR5K_SLEEP_CTL:
707 SET_MEM_L(s->mem, AR5K_SLEEP_CTL, val);
708 if (val == AR5K_SLEEP_CTL_SLE_WAKE) {
709 DEBUG_PRINT(("waking up device\n"));
712 * yes, we are awake
714 * basically it just checks if power-down
715 * is false (val & AR5K_PCICFG_SPWR_DN == 0)
716 * but my AR5212 says 20 what has the same
717 * result but might be better ;-)
719 SET_MEM_L(s->mem, AR5K_PCICFG, 0x14);
720 SET_MEM_L(s->mem, AR5K_STA_ID1, 0x00049e2e);
721 #if 0
722 SET_MEM_L(s->mem, AR5K_STA_ID1, 0x0);
724 SET_MEM_L(s->mem, AR5K_PCICFG, 0x34);
725 SET_MEM_L(s->mem, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV);
726 #endif
727 } else if (val == AR5K_SLEEP_CTL_SLE_SLP) {
728 DEBUG_PRINT(("putting device to sleep\n"));
729 } else {
730 DEBUG_PRINT(("unknown SLEEP command %u\n", val));
732 break;
734 case AR5K_PHY_PLL:
736 * ...set the PHY operating mode after reset
739 /* ath5k_hw.c: 632 */
740 DEBUG_PRINT(("setting PHY operating mode (PLL)\n"));
741 break;
743 case AR5K_PHY_MODE:
745 * ...set the PHY operating mode after reset
748 /* ath5k_hw.c: 635 */
749 DEBUG_PRINT(("setting PHY operating mode (mode)\n"));
750 break;
752 case AR5K_PHY_TURBO:
754 * ...set the PHY operating mode after reset
757 /* ath5k_hw.c: 636 */
758 DEBUG_PRINT(("setting PHY operating mode (turbo)\n"));
759 break;
762 /******************************************************************
764 * ath5k_hw_init ---> ath5k_hw_radio_revision
766 ******************************************************************/
768 case AR5K_PHY(0):
770 * Unknown
772 if (val == AR5K_PHY_SHIFT_2GHZ) {
773 DEBUG_PRINT(("requesting 2GHZ radio\n"));
774 SET_MEM_L(s->mem, AR5K_PHY(0x100), 0x4c047000);
776 /* ath5k_hw.c: 662 */
777 else if (val == AR5K_PHY_SHIFT_5GHZ) {
778 DEBUG_PRINT(("requesting 5GHZ radio\n"));
779 SET_MEM_L(s->mem, AR5K_PHY(0x100), 0x8e000000);
782 SET_MEM_L(s->mem, AR5K_SLEEP_CTL, 0x0);
783 break;
785 case AR5K_PHY(0x20):
787 * request radio revision
790 /* ath5k_hw.c: 659 */
791 if (val == AR5K_PHY_SHIFT_2GHZ) {
792 DEBUG_PRINT(("requesting 2GHZ radio\n"));
793 SET_MEM_L(s->mem, AR5K_PHY(0x100), 0x4c047000); /* 1275359232); */
795 /* ath5k_hw.c: 662 */
796 else if (val == AR5K_PHY_SHIFT_5GHZ) {
797 DEBUG_PRINT(("requesting 5GHZ radio\n"));
798 SET_MEM_L(s->mem, AR5K_PHY(0x100), 0x7fffffff); /* 2382364672); */
800 /* ath5k_hw.c: 671 */
801 else if (val == 0x00001c16) {
802 DEBUG_PRINT(("requesting radio\n"));
804 /* ath5k_hw.c: 674 */
805 else if (val == 0x00010000) {
806 DEBUG_PRINT(("requesting radio 8 times...\n"));
807 /* NOW we request the radio revision (it was set before...) */
808 #if 0
809 SET_MEM_L(s->mem, 0x9c00, 0x8e026023);
810 #endif
811 SET_MEM_L(s->mem, 0x9c00, 0x8e000000);
813 SET_MEM_L(s->mem, 0x9c00, 0x4c047000);
816 break;
819 * Setting frequency is different for AR5210/AR5211/AR5212
821 * see ath5k_hw.c: 4590 ff
823 * they all set AR5K_PHY(0x27),
824 * AR5210 sets AR5K_PHY(0x30),
825 * AR5211 sets AR5K_PHY(0x34) and
826 * AR5212 sets AR5K_PHY(0x36)
829 * The virtual device seems to read out 0x34 for
830 * the current channel (e.g. after a packet has
831 * been received)!!
833 case AR5K_PHY(0x27):
834 #if 0
835 fprintf(stderr, "0x%04x => 0x%08x (27)\n", addr, val);
836 #endif
837 SET_MEM_L(s->mem, addr, val);
838 s->current_frequency_partial_data[0] = val;
839 updateFrequency(s);
840 break;
842 case AR5K_PHY(0x34):
843 #if 0
844 fprintf(stderr, "0x%04x => 0x%08x (34)\n", addr, val);
845 #endif
846 SET_MEM_L(s->mem, addr, val);
847 s->current_frequency_partial_data[1] = val;
848 updateFrequency(s);
849 break;
852 * these are used by AR521 and AR5212 respectively,
853 * but we seem to simulate an AR5211 and the calls
854 * destroy our channel frequency mapping :-(
856 case AR5K_PHY(0x30):
857 fprintf(stderr, "0x%04x => 0x%08x (30)\n", addr, val);
858 SET_MEM_L(s->mem, addr, val);
859 s->current_frequency_partial_data[1] = val;
860 updateFrequency(s);
861 break;
862 case AR5K_PHY(0x36):
863 fprintf(stderr, "0x%04x => 0x%08x (36)\n", addr, val);
864 SET_MEM_L(s->mem, addr, val);
865 s->current_frequency_partial_data[1] = val;
866 updateFrequency(s);
867 break;
871 case AR5K_PHY(0x21):
872 case AR5K_PHY(0x22):
873 case AR5K_PHY(0x23):
874 case AR5K_PHY(0x24):
875 case AR5K_PHY(0x25):
876 case AR5K_PHY(0x26):
877 case AR5K_PHY(0x28):
878 case AR5K_PHY(0x29):
879 case AR5K_PHY(0x31):
880 case AR5K_PHY(0x32):
881 case AR5K_PHY(0x33):
882 case AR5K_PHY(0x35):
883 case AR5K_PHY(0x37):
884 case AR5K_PHY(0x38):
885 case AR5K_PHY(0x39):
886 case AR5K_PHY(0x40):
887 case AR5K_PHY(0x41):
888 case AR5K_PHY(0x42):
889 case AR5K_PHY(0x43):
890 case AR5K_PHY(0x44):
891 case AR5K_PHY(0x45):
892 case AR5K_PHY(0x46):
893 case AR5K_PHY(0x47):
894 case AR5K_PHY(0x48):
895 case AR5K_PHY(0x49):
896 case AR5K_PHY(0x50):
897 fprintf(stderr, "0x%04x => 0x%08x\n", addr, val);
898 break;*/
900 /******************************************************************
902 * ath5k_hw_init ---> ath5k_hw_set_associd (aka. set BSSID)
904 ******************************************************************/
906 case AR5K_BSS_IDM0:
907 case AR5K_BSS_IDM1:
909 * Set simple BSSID mask on 5212
912 /* ath5k_hw.c: 2420 */
913 DEBUG_PRINT(("setting bssid mask\n"));
914 break;
916 case AR5K_BSS_ID0:
917 case AR5K_BSS_ID1:
919 * Set BSSID which triggers the "SME Join" operation
922 /* ath5k_hw.c: 2432 & 2433 */
923 DEBUG_PRINT(("setting bssid : %c%c%c%c\n",
924 (val << 24) >> 24, (val << 16) >> 24,
925 (val << 8) >> 24, val >> 24));
926 break;
928 case AR5K_STA_ID0:
930 * a set to client(adhoc|managed) | ap | monitor mode is coming
932 * if there are more than one chip present, this
933 * call defines which chip is to be used!
936 /* ath5k_hw.c: 2358 */
937 DEBUG_PRINT(("a set to client | ap | monitor mode is coming for station %u\n", val));
939 /* ext */
940 SET_MEM_L(s->mem, addr, val);
942 break;
944 case AR5K_STA_ID1:
946 * seems to have a double-meaning:
948 * setting client mode AND power mode
951 /* ath5k_hw.c: 619 */
952 DEBUG_PRINT(("setting power mode\n"));
953 SET_MEM_L(s->mem, AR5K_STA_ID1, val);
954 SET_MEM_L(s->mem, AR5K_STA_ID0, 0x800a1100);
955 /*SET_MEM_L(s->mem, 0xc, 0x1a7d823c); */
956 SET_MEM_L(s->mem, 0xc, 0x0);
957 SET_MEM_L(s->mem, 0x00c0, 0x01040000);
960 /* ath5k_hw.c: 2361 */
961 if (val & AR5K_STA_ID1_ADHOC & AR5K_STA_ID1_DESC_ANTENNA) {
962 DEBUG_PRINT(("setting device into ADHOC mode\n"));
963 } else if (val & AR5K_STA_ID1_AP & AR5K_STA_ID1_RTS_DEF_ANTENNA) {
964 DEBUG_PRINT(("setting device into managed mode\n"));
965 } else if (val & AR5K_STA_ID1_DEFAULT_ANTENNA) {
966 DEBUG_PRINT(("setting device into some other mode (probably monitor)\n"));
967 } else {
968 DEBUG_PRINT(("setting device into unknown mode\n"));
970 break;
972 /******************************************************************
974 * ath5k_hw_init ---> ath5k_eeprom_init
976 ******************************************************************/
978 case AR5K_EEPROM_BASE:
980 * an access to an offset inside the
981 * EEPROM uses an initialization of
982 * the address at this location
985 /* ath5k_hw.c: 1738 */
986 DEBUG_PRINT(("there will be an access to the EEPROM at %08x\n", val));
989 * set the data that will be returned
990 * after calling AR5K_EEPROM_CMD=READ
992 switch (val) {
993 #if 0
994 case AR5K_EEPROM_MAGIC:
995 WRITE_EEPROM(s->mem, AR5K_EEPROM_MAGIC_VALUE);
996 break;
998 case AR5K_EEPROM_PROTECT:
999 WRITE_EEPROM(s->mem, 0);
1000 break;
1002 case AR5K_EEPROM_REG_DOMAIN:
1004 * reg-domain central europe ???
1006 WRITE_EEPROM(s->mem, 96);
1007 break;
1009 case AR5K_EEPROM_VERSION:
1010 WRITE_EEPROM(s->mem, AR5K_EEPROM_VERSION_3_4);
1011 break;
1013 case AR5K_EEPROM_HDR:
1014 WRITE_EEPROM(s->mem, 23046);
1015 break;
1017 case 195:
1019 * an radio-GHZ specific eeprom data (AR5K_EEPROM_ANT_GAIN)
1021 * on my AR5212 it is 0
1024 /* ath5k_hw.c: 2023 */
1025 WRITE_EEPROM(s->mem, 0);
1026 break;
1028 case 0x20:
1030 * before we read the MAC addr, we read this (???)
1032 * ATTENTION: this value is present in the EEPROM!!
1035 /* ath5k_hw.c : 2185 */
1036 break;
1038 case 0x1f:
1040 * 1st part of MAC-addr
1042 DEBUG_PRINT(("EEPROM request first part of MAC\n"));
1043 WRITE_EEPROM(s->mem, (s->phys[0] << 8) | s->phys[1]);
1044 break;
1046 case 0x1e:
1048 * 2nd part of MAC-addr
1050 DEBUG_PRINT(("EEPROM request second part of MAC\n"));
1051 WRITE_EEPROM(s->mem, (s->phys[2] << 8) | s->phys[3]);
1052 break;
1054 case 0x1d:
1056 * 3rd part of MAC-addr
1058 DEBUG_PRINT(("EEPROM request third part of MAC\n"));
1059 WRITE_EEPROM(s->mem, (s->phys[4] << 8) | s->phys[5]);
1060 break;
1061 #endif
1063 * ATTENTION: if we modify anything in the
1064 * eeprom, we might get (at least in linux we
1065 * do) an EEPROM-checksum error!!
1068 case 0x0:
1070 * this is not part of the EEPROM dumps for some reason!!
1072 DEBUG_PRINT(("EEPROM request 0x0\n"));
1073 WRITE_EEPROM(s->mem, 0x13);
1074 break;
1076 default:
1077 if (!get_eeprom_data(s, val, &h)) {
1079 * we have a hit in the internal eeprom-buffer
1081 DEBUG_PRINT(("EEPROM hit %u at %u\n", h, val));
1082 WRITE_EEPROM(s->mem, h);
1083 } else {
1084 DEBUG_PRINT(("EEPROM request at %08x is unknown\n", val));
1085 WRITE_EEPROM(s->mem, 0);
1087 break;
1089 break;
1091 case AR5K_EEPROM_CMD:
1093 * what type of access is specified as well
1096 /* ath5k_hw.c: 1739 */
1097 if (val & AR5K_EEPROM_CMD_READ) {
1098 DEBUG_PRINT(("the EEPROM access will be READ\n"));
1101 * tell the device the read was successful
1103 SET_MEM_L(s->mem, AR5K_EEPROM_STAT_5210, AR5K_EEPROM_STAT_RDDONE);
1104 SET_MEM_L(s->mem, AR5K_EEPROM_STAT_5211, AR5K_EEPROM_STAT_RDDONE);
1106 * and return the data that was set
1107 * during the write to AR5K_EEPROM_BASE
1109 } else {
1110 DEBUG_PRINT(("the EEPROM access will be UNKNOWN\n"));
1111 fprintf(stderr, "Is this a write to the eeprom??\n");
1113 break;
1116 /******************************************************************
1118 * additional reverse engineering:
1120 ******************************************************************/
1122 case AR5K_USEC_5210: /* new */
1123 SET_MEM_L(s->mem, AR5K_XRMODE, 0x2a80001a);
1124 SET_MEM_L(s->mem, AR5K_XRTIMEOUT, 0x13881c20);
1125 break;
1127 case AR5K_PHY_AGCCTL: /* new */
1128 if (val & AR5K_PHY_AGCCTL_CAL) {
1129 SET_MEM_L(s->mem, AR5K_PHY_AGCCTL, val & (~AR5K_PHY_AGCCTL_CAL));
1130 } else if (val & AR5K_PHY_AGCCTL_NF) {
1131 SET_MEM_L(s->mem, AR5K_PHY_AGCCTL, val & (~AR5K_PHY_AGCCTL_NF));
1133 break;
1135 default:
1136 if (addr / 4 < Atheros_WLAN_MEM_SIZE) {
1137 SET_MEM_L(s->mem, addr, val);
1140 if ((addr >= AR5K_PCU_MIN) &&
1141 (addr <= AR5K_PCU_MAX)) {
1142 DEBUG_PRINT(("Setting up ini-registers...!!\n"));
1143 } else {
1144 DEBUG_PRINT(("Unknown call to memory!!\n"));
1146 break;
1150 #endif /* CONFIG_WIN32 */