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
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")
45 #include <sys/types.h>
48 #include <sys/socket.h>
52 #include <netinet/in.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
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
98 static int get_eeprom_data(Atheros_WLANState
*s
, uint32_t addr
, uint32_t *val
)
104 /* why?? but seems necessary... */
107 if (addr
> s
->eeprom_size
) {
111 *val
= s
->eeprom_data
[addr
];
120 static void updateFrequency(Atheros_WLANState
*s
)
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]) {
130 if (Atheros_WLAN_frequency_data
[i
].value2
!=
131 s
->current_frequency_partial_data
[1]) {
135 new_frequency
= Atheros_WLAN_frequency_data
[i
].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
,
150 static void Atheros_WLAN_mmio_writeb(void *opaque
, hwaddr addr
,
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
,
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
,
169 mm_writel(opaque
, Atheros_WLAN_MEM_SANITIZE(addr
), val
);
170 DEBUG_PRINT((" through call: mmio_writel " TARGET_FMT_plx
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"));
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"));
193 static uint32_t Atheros_WLAN_mmio_readl(void *opaque
, hwaddr addr
)
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
));
203 static uint64_t Atheros_WLAN_read(void *opaque
, hwaddr addr
,
206 Atheros_WLANState
*s
= opaque
;
210 val
= Atheros_WLAN_mmio_readb(s
, addr
);
213 val
= Atheros_WLAN_mmio_readw(s
, addr
);
216 val
= Atheros_WLAN_mmio_readl(s
, addr
);
224 static void Atheros_WLAN_write(void *opaque
, hwaddr addr
,
225 uint64_t val
, unsigned size
)
227 Atheros_WLANState
*s
= opaque
;
230 Atheros_WLAN_mmio_writeb(s
, addr
, val
);
233 Atheros_WLAN_mmio_writew(s
, addr
, val
);
236 Atheros_WLAN_mmio_writel(s
, addr
, val
);
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) \
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
);
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
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);
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!!
311 if (s
->device_driver_type
== WINXP_DRIVER
) {
312 addr
= AR5K_RAC_PISR
;
313 /* fall through... */
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
));
333 SET_MEM_L(s
->mem
, addr
, 0);
334 DEBUG_PRINT(("secondary irq status\n"));
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...
345 /* SET_MEM_L(s->mem, addr, 0); */
354 static void mm_writel(Atheros_WLANState
*s
, hwaddr addr
,
360 /******************************************************************
362 * ath5k_hw_init ---> ath5k_hw_nic_wakeup
364 ******************************************************************/
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);
387 /* ath5k_hw.c: 626 */
388 DEBUG_PRINT(("reset device (generic)\n"));
393 SET_MEM_L(s
->mem
, AR5K_RESET_CTL
, 0);
398 /******************************************************************
402 ******************************************************************/
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;
420 DEBUG_PRINT(("setting interrupt-enable to undefined value!!\n"));
426 SET_MEM_L(s
->mem
, AR5K_GPIODI
, 0x3);
430 case AR5K_GPIODI
: /* new */
432 SET_MEM_L(s
->mem
, AR5K_GPIODO
, 0x3);
437 /* ath5k_hw.c: 1668 */
438 DEBUG_PRINT(("setting primary interrupt-mask to 0x%x (%u)\n",
440 s
->interrupt_p_mask
= val
;
442 SET_MEM_L(s
->mem
, addr
, val
);
446 DEBUG_PRINT(("setting secondary interrupt-mask 0 to 0x%x (%u)\n",
448 s
->interrupt_s_mask
[0] = val
;
451 DEBUG_PRINT(("setting secondary interrupt-mask 1 to 0x%x (%u)\n",
453 s
->interrupt_s_mask
[1] = val
;
456 DEBUG_PRINT(("setting secondary interrupt-mask 2 to 0x%x (%u)\n",
458 s
->interrupt_s_mask
[2] = val
;
461 DEBUG_PRINT(("setting secondary interrupt-mask 3 to 0x%x (%u)\n",
463 s
->interrupt_s_mask
[3] = val
;
466 DEBUG_PRINT(("setting secondary interrupt-mask 4 to 0x%x (%u)\n",
468 s
->interrupt_s_mask
[4] = val
;
471 /******************************************************************
473 * ath5k queuing (for transmit and receive buffers)
475 ******************************************************************/
478 /* ath5k_hw.c: 1423ff */
480 /* enable specified queue (nr in val) */
481 val
= FASTBINLOG(val
);
483 DEBUG_PRINT(("queue %u enabled\n", val
));
485 s
->transmit_queue_enabled
[val
] = 1;
486 Atheros_WLAN_handleTxBuffer(s
, val
);
488 DEBUG_PRINT(("unknown queue 0x%x (%u)\n", val
, val
));
493 /* ath5k_hw.c: 1423ff */
495 /* disable specified queue (nr in val) */
496 val
= FASTBINLOG(val
);
498 DEBUG_PRINT(("queue %u disabled\n", val
));
500 s
->transmit_queue_enabled
[val
] = 0;
502 DEBUG_PRINT(("unknown queue 0x%x (%u)\n", val
, val
));
508 DEBUG_PRINT(("TODO: find out what inter frame spacing registers are used for...\n"));
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);
520 /* ath5k_hw.c: 1122 */
521 DEBUG_PRINT(("Setting transmit queue size to %u byte\n",
524 s
->transmit_queue_size
= (1 << (val
+ 2));
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"));
545 DEBUG_PRINT(("Undefined TX/RX en/disable\n"));
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",
559 * This address will be queried again
560 * later... store it!!
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;
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",
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
;
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
;
617 DEBUG_PRINT(("unknown queue " TARGET_FMT_plx
"\n", addr
));
622 /* ath5k_hw.c: 1124 */
623 DEBUG_PRINT(("Setting receive queue size to %u byte\n",
625 SET_MEM_L(s
->mem
, addr
, val
);
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
));
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",
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",
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
));
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"));
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);
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
);
727 } else if (val
== AR5K_SLEEP_CTL_SLE_SLP
) {
728 DEBUG_PRINT(("putting device to sleep\n"));
730 DEBUG_PRINT(("unknown SLEEP command %u\n", val
));
736 * ...set the PHY operating mode after reset
739 /* ath5k_hw.c: 632 */
740 DEBUG_PRINT(("setting PHY operating mode (PLL)\n"));
745 * ...set the PHY operating mode after reset
748 /* ath5k_hw.c: 635 */
749 DEBUG_PRINT(("setting PHY operating mode (mode)\n"));
754 * ...set the PHY operating mode after reset
757 /* ath5k_hw.c: 636 */
758 DEBUG_PRINT(("setting PHY operating mode (turbo)\n"));
762 /******************************************************************
764 * ath5k_hw_init ---> ath5k_hw_radio_revision
766 ******************************************************************/
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);
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...) */
809 SET_MEM_L(s
->mem
, 0x9c00, 0x8e026023);
811 SET_MEM_L(s
->mem
, 0x9c00, 0x8e000000);
813 SET_MEM_L(s
->mem
, 0x9c00, 0x4c047000);
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
835 fprintf(stderr
, "0x%04x => 0x%08x (27)\n", addr
, val
);
837 SET_MEM_L(s
->mem
, addr
, val
);
838 s
->current_frequency_partial_data
[0] = val
;
844 fprintf(stderr
, "0x%04x => 0x%08x (34)\n", addr
, val
);
846 SET_MEM_L(s
->mem
, addr
, val
);
847 s
->current_frequency_partial_data
[1] = val
;
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 :-(
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;
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;
897 fprintf(stderr, "0x%04x => 0x%08x\n", addr, val);
900 /******************************************************************
902 * ath5k_hw_init ---> ath5k_hw_set_associd (aka. set BSSID)
904 ******************************************************************/
909 * Set simple BSSID mask on 5212
912 /* ath5k_hw.c: 2420 */
913 DEBUG_PRINT(("setting bssid mask\n"));
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));
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
));
940 SET_MEM_L(s
->mem
, addr
, val
);
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"));
968 DEBUG_PRINT(("setting device into unknown mode\n"));
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
994 case AR5K_EEPROM_MAGIC
:
995 WRITE_EEPROM(s
->mem
, AR5K_EEPROM_MAGIC_VALUE
);
998 case AR5K_EEPROM_PROTECT
:
999 WRITE_EEPROM(s
->mem
, 0);
1002 case AR5K_EEPROM_REG_DOMAIN
:
1004 * reg-domain central europe ???
1006 WRITE_EEPROM(s
->mem
, 96);
1009 case AR5K_EEPROM_VERSION
:
1010 WRITE_EEPROM(s
->mem
, AR5K_EEPROM_VERSION_3_4
);
1013 case AR5K_EEPROM_HDR
:
1014 WRITE_EEPROM(s
->mem
, 23046);
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);
1030 * before we read the MAC addr, we read this (???)
1032 * ATTENTION: this value is present in the EEPROM!!
1035 /* ath5k_hw.c : 2185 */
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]);
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]);
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]);
1063 * ATTENTION: if we modify anything in the
1064 * eeprom, we might get (at least in linux we
1065 * do) an EEPROM-checksum error!!
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);
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
);
1084 DEBUG_PRINT(("EEPROM request at %08x is unknown\n", val
));
1085 WRITE_EEPROM(s
->mem
, 0);
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
1110 DEBUG_PRINT(("the EEPROM access will be UNKNOWN\n"));
1111 fprintf(stderr
, "Is this a write to the eeprom??\n");
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);
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
));
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"));
1144 DEBUG_PRINT(("Unknown call to memory!!\n"));
1150 #endif /* CONFIG_WIN32 */