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 "qemu/osdep.h"
34 #if defined(CONFIG_WIN32)
35 #warning("not compiled for Windows host")
44 #include <sys/socket.h>
48 #include <netinet/in.h>
53 #include "hw/atheros_wlan.h"
54 #include "hw/atheros_wlan_ap.h"
55 #include "hw/atheros_wlan_io.h"
58 * MadWifi OPENHAL atheros constants
61 #include "hw/ath5k_hw.h"
62 #include "hw/ath5kreg.h"
65 static const struct Atheros_WLAN_frequency Atheros_WLAN_frequency_data
[] = {
66 { 20689, 3077, 2412 }, /* channel 1 */
67 { 20715, 3078, 2417 }, /* channel 2 */
68 { 20689, 3079, 2422 }, /* channel 3 */
69 { 20715, 3079, 2427 }, /* channel 4 */
70 { 20529, 3076, 2432 }, /* channel 5 */
71 { 20507, 3078, 2437 }, /* channel 6 */
72 { 20529, 3078, 2442 }, /* channel 7 */
73 { 20507, 3079, 2447 }, /* channel 8 */
74 { 20529, 3077, 2452 }, /* channel 9 */
75 { 20635, 3078, 2457 }, /* channel 10 */
76 { 20529, 3079, 2462 }, /* channel 11 */
77 { 20635, 3079, 2467 }, /* channel 12 */
78 { 20657, 3076, 2472 }, /* channel 13 */
79 { 20529, 1029, 2484 } /* channel 14 */
83 * NOTE: By using this function instead
84 * of accessing the array directly through
85 * an index, we can leave out parts of the
88 static int get_eeprom_data(Atheros_WLANState
*s
, uint32_t addr
, uint32_t *val
)
94 /* why?? but seems necessary... */
97 if (addr
> s
->eeprom_size
) {
101 *val
= s
->eeprom_data
[addr
];
110 static void updateFrequency(Atheros_WLANState
*s
)
113 uint32_t new_frequency
= 0;
114 for (i
= 0; i
< ARRAY_SIZE(Atheros_WLAN_frequency_data
); i
++) {
115 if (Atheros_WLAN_frequency_data
[i
].value1
!=
116 s
->current_frequency_partial_data
[0]) {
120 if (Atheros_WLAN_frequency_data
[i
].value2
!=
121 s
->current_frequency_partial_data
[1]) {
125 new_frequency
= Atheros_WLAN_frequency_data
[i
].frequency
;
130 s
->current_frequency
= new_frequency
;
136 static uint32_t mm_readl(Atheros_WLANState
*s
, hwaddr addr
);
137 static void mm_writel(Atheros_WLANState
*s
, hwaddr addr
,
140 static void Atheros_WLAN_mmio_writeb(void *opaque
, hwaddr addr
,
143 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
144 DEBUG_PRINT(("mmio_writeb " TARGET_FMT_plx
" val %x\n", addr
, val
));
145 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
148 static void Atheros_WLAN_mmio_writew(void *opaque
, hwaddr addr
,
151 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
152 DEBUG_PRINT(("mmio_writew " TARGET_FMT_plx
" val %x\n", addr
, val
));
153 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
156 static void Atheros_WLAN_mmio_writel(void *opaque
, hwaddr addr
,
159 mm_writel(opaque
, Atheros_WLAN_MEM_SANITIZE(addr
), val
);
160 DEBUG_PRINT((" through call: mmio_writel " TARGET_FMT_plx
162 Atheros_WLAN_MEM_SANITIZE(addr
), val
, val
));
165 static uint32_t Atheros_WLAN_mmio_readb(void *opaque
, hwaddr addr
)
167 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
168 DEBUG_PRINT(("mmio_readb " TARGET_FMT_plx
"\n", addr
));
169 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
174 static uint32_t Atheros_WLAN_mmio_readw(void *opaque
, hwaddr addr
)
176 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
177 DEBUG_PRINT(("mmio_readw " TARGET_FMT_plx
"\n", addr
));
178 DEBUG_PRINT(("!!! DEBUG INIMPLEMENTED !!!\n"));
183 static uint32_t Atheros_WLAN_mmio_readl(void *opaque
, hwaddr addr
)
186 val
= mm_readl(opaque
, Atheros_WLAN_MEM_SANITIZE(addr
));
188 DEBUG_PRINT((" mmio_readl " TARGET_FMT_plx
" = 0x%x (%u)\n",
189 Atheros_WLAN_MEM_SANITIZE(addr
), val
, val
));
193 static uint64_t Atheros_WLAN_read(void *opaque
, hwaddr addr
,
196 Atheros_WLANState
*s
= opaque
;
200 val
= Atheros_WLAN_mmio_readb(s
, addr
);
203 val
= Atheros_WLAN_mmio_readw(s
, addr
);
206 val
= Atheros_WLAN_mmio_readl(s
, addr
);
214 static void Atheros_WLAN_write(void *opaque
, hwaddr addr
,
215 uint64_t val
, unsigned size
)
217 Atheros_WLANState
*s
= opaque
;
220 Atheros_WLAN_mmio_writeb(s
, addr
, val
);
223 Atheros_WLAN_mmio_writew(s
, addr
, val
);
226 Atheros_WLAN_mmio_writel(s
, addr
, val
);
233 static const MemoryRegionOps Atheros_WLAN_ops
= {
234 .read
= Atheros_WLAN_read
,
235 .write
= Atheros_WLAN_write
,
236 .endianness
= DEVICE_LITTLE_ENDIAN
,
239 void Atheros_WLAN_setup_io(PCIAtheros_WLANState
*d
)
241 Atheros_WLANState
*s
= &d
->Atheros_WLAN
;
243 memory_region_init_io(&s
->mmio_bar
, &Atheros_WLAN_ops
, s
, "atheros_mmio",
244 Atheros_WLAN_MEM_SIZE
);
245 pci_register_bar(&s
->dev
, 0, PCI_BASE_ADDRESS_SPACE_MEMORY
, &s
->mmio_bar
);
250 #define FASTBINLOG(x) \
263 (x == 4096) ? 12 : 13
267 static uint32_t mm_readl(Atheros_WLANState
*s
, hwaddr addr
)
269 uint32_t val
= GET_MEM_L(s
->mem
, addr
);
271 case ATH_HW_IRQ_PENDING
:
273 * This indicates that the interrupt
274 * routine has been called. reset interrupt
275 * status and put the interrupt-status
276 * number at the correct memory-location
278 * In case multiple interrupts are pending
279 * this memory-location is checked multiple
280 * times... each time, we put another interrupt
281 * status into memory until no more interrupts
284 Atheros_WLAN_disable_irq(s
);
286 DEBUG_PRINT((">> irq pending? ... 0x%x\n", val
));
287 SET_MEM_L(s
->mem
, 0x0080, 0x0);
288 SET_MEM_L(s
->mem
, 0x80ec, 0x0001c680);
289 SET_MEM_L(s
->mem
, 0x80f0, 0x000055dc);
290 SET_MEM_L(s
->mem
, 0x80f8, 0x0015f6fc);
291 SET_MEM_L(s
->mem
, 0x9850, 0x0de8b0da);
295 * The following registers are Read-and-Clear
296 * registers --> must be reset after a read!!
298 * However, it does not work when using linux!!
301 if (s
->device_driver_type
== WINXP_DRIVER
) {
302 addr
= AR5K_RAC_PISR
;
303 /* fall through... */
309 Atheros_WLAN_update_irq(s
);
310 val
= GET_MEM_L(s
->mem
, addr
);
311 SET_MEM_L(s
->mem
, addr
, 0);
312 SET_MEM_L(s
->mem
, AR5K_PCICFG
, 0x34);
314 DEBUG_PRINT((">> irq status 0x%x\n", val
));
323 SET_MEM_L(s
->mem
, addr
, 0);
324 DEBUG_PRINT(("secondary irq status\n"));
329 * According to the openHAL source
330 * documentation this is also read-and-clear
331 * but if it is made so, the WinDriver does
332 * not work any more...
335 /* SET_MEM_L(s->mem, addr, 0); */
344 static void mm_writel(Atheros_WLANState
*s
, hwaddr addr
,
350 /******************************************************************
352 * ath5k_hw_init ---> ath5k_hw_nic_wakeup
354 ******************************************************************/
358 if (val
== (AR5K_RESET_CTL_CHIP
| AR5K_RESET_CTL_PCI
)) {
359 /* ath5k_hw.c: 613 */
360 DEBUG_PRINT(("reset device (MAC + PCI)\n"));
363 * claim device is inited
365 SET_MEM_L(s
->mem
, AR5K_STA_ID1
, 0);
366 SET_MEM_L(s
->mem
, AR5K_RESET_CTL
, 3);
367 } else if (val
& (AR5K_RESET_CTL_CHIP
| AR5K_RESET_CTL_PCI
)) {
368 /* ath5k_hw.c: 613 */
369 DEBUG_PRINT(("reset device (MAC + PCI + ?)\n"));
372 * claim device is inited
374 SET_MEM_L(s
->mem
, AR5K_STA_ID1
, 0);
375 SET_MEM_L(s
->mem
, AR5K_RESET_CTL
, 3);
377 /* ath5k_hw.c: 626 */
378 DEBUG_PRINT(("reset device (generic)\n"));
383 SET_MEM_L(s
->mem
, AR5K_RESET_CTL
, 0);
388 /******************************************************************
392 ******************************************************************/
395 if (val
== AR5K_IER_DISABLE
) {
396 /* ath5k_hw.c: 1636 */
397 DEBUG_PRINT(("disabling interrupts\n"));
398 SET_MEM_L(s
->mem
, AR5K_GPIODO
, 0x0);
399 SET_MEM_L(s
->mem
, AR5K_GPIODI
, 0x0);
401 s
->interrupt_enabled
= 0;
402 } else if (val
== AR5K_IER_ENABLE
) {
403 /* ath5k_hw.c: 1674 */
404 DEBUG_PRINT(("enabling interrupts\n"));
405 SET_MEM_L(s
->mem
, AR5K_GPIODO
, 0x2);
406 SET_MEM_L(s
->mem
, AR5K_GPIODI
, 0x3); /* new */
408 s
->interrupt_enabled
= 1;
410 DEBUG_PRINT(("setting interrupt-enable to undefined value!!\n"));
416 SET_MEM_L(s
->mem
, AR5K_GPIODI
, 0x3);
420 case AR5K_GPIODI
: /* new */
422 SET_MEM_L(s
->mem
, AR5K_GPIODO
, 0x3);
427 /* ath5k_hw.c: 1668 */
428 DEBUG_PRINT(("setting primary interrupt-mask to 0x%x (%u)\n",
430 s
->interrupt_p_mask
= val
;
432 SET_MEM_L(s
->mem
, addr
, val
);
436 DEBUG_PRINT(("setting secondary interrupt-mask 0 to 0x%x (%u)\n",
438 s
->interrupt_s_mask
[0] = val
;
441 DEBUG_PRINT(("setting secondary interrupt-mask 1 to 0x%x (%u)\n",
443 s
->interrupt_s_mask
[1] = val
;
446 DEBUG_PRINT(("setting secondary interrupt-mask 2 to 0x%x (%u)\n",
448 s
->interrupt_s_mask
[2] = val
;
451 DEBUG_PRINT(("setting secondary interrupt-mask 3 to 0x%x (%u)\n",
453 s
->interrupt_s_mask
[3] = val
;
456 DEBUG_PRINT(("setting secondary interrupt-mask 4 to 0x%x (%u)\n",
458 s
->interrupt_s_mask
[4] = val
;
461 /******************************************************************
463 * ath5k queuing (for transmit and receive buffers)
465 ******************************************************************/
468 /* ath5k_hw.c: 1423ff */
470 /* enable specified queue (nr in val) */
471 val
= FASTBINLOG(val
);
473 DEBUG_PRINT(("queue %u enabled\n", val
));
475 s
->transmit_queue_enabled
[val
] = 1;
476 Atheros_WLAN_handleTxBuffer(s
, val
);
478 DEBUG_PRINT(("unknown queue 0x%x (%u)\n", val
, val
));
483 /* ath5k_hw.c: 1423ff */
485 /* disable specified queue (nr in val) */
486 val
= FASTBINLOG(val
);
488 DEBUG_PRINT(("queue %u disabled\n", val
));
490 s
->transmit_queue_enabled
[val
] = 0;
492 DEBUG_PRINT(("unknown queue 0x%x (%u)\n", val
, val
));
498 DEBUG_PRINT(("TODO: find out what inter frame spacing registers are used for...\n"));
502 if (val
== AR5K_INIT_CFG
) {
503 /* ath5k_hw.c: 1261 */
504 DEBUG_PRINT(("Reset configuration register (for hw bitswap)\n"));
506 SET_MEM_L(s
->mem
, AR5K_SLEEP_CTL
, 0x0);
510 /* ath5k_hw.c: 1122 */
511 DEBUG_PRINT(("Setting transmit queue size to %u byte\n",
514 s
->transmit_queue_size
= (1 << (val
+ 2));
518 if (val
== AR5K_CR_TXE0
) { /* TX Enable for queue 0 on 5210 */
519 DEBUG_PRINT(("TX enable for queue 0\n"));
520 } else if (val
== AR5K_CR_TXE1
) { /* TX Enable for queue 1 on 5210 */
521 DEBUG_PRINT(("TX enable for queue 1\n"));
522 } else if (val
== AR5K_CR_RXE
) { /* RX Enable */
523 DEBUG_PRINT(("RX enable\n"));
524 SET_MEM_L(s
->mem
, AR5K_DIAG_SW_5211
, 0x0);
525 } else if (val
== AR5K_CR_TXD0
) { /* TX Disable for queue 0 on 5210 */
526 DEBUG_PRINT(("TX disable for queue 0\n"));
527 } else if (val
== AR5K_CR_TXD1
) { /* TX Disable for queue 1 on 5210 */
528 DEBUG_PRINT(("TX disable for queue 1\n"));
529 } else if (val
== AR5K_CR_RXD
) { /* RX Disable */
530 DEBUG_PRINT(("RX disable\n"));
531 } else if (val
== AR5K_CR_SWI
) { /* unknown... */
533 DEBUG_PRINT(("Undefined TX/RX en/disable CR_SWI\n"));
535 DEBUG_PRINT(("Undefined TX/RX en/disable\n"));
541 * unknown location, but this should
542 * set the location of the receive
543 * buffer's PHYSICAL address!!
545 DEBUG_PRINT(("Setting receive queue to address 0x%x (%u)\n",
549 * This address will be queried again
550 * later... store it!!
553 /* hm... ar5424 resets its queue to 0 :-( */
555 SET_MEM_L(s
->mem
, addr
, val
);
556 s
->receive_queue_address
= (hwaddr
)val
;
559 * Madwifi hack: we allow only a certain
560 * number of packets in the receive queue!!
562 s
->receive_queue_count
= 0;
565 case AR5K_QUEUE_TXDP(0):
566 case AR5K_QUEUE_TXDP(1):
567 case AR5K_QUEUE_TXDP(2):
568 case AR5K_QUEUE_TXDP(3):
569 case AR5K_QUEUE_TXDP(4):
570 case AR5K_QUEUE_TXDP(5):
571 case AR5K_QUEUE_TXDP(6):
572 case AR5K_QUEUE_TXDP(7):
573 case AR5K_QUEUE_TXDP(8):
574 case AR5K_QUEUE_TXDP(9):
575 case AR5K_QUEUE_TXDP(10):
576 case AR5K_QUEUE_TXDP(11):
577 case AR5K_QUEUE_TXDP(12):
578 case AR5K_QUEUE_TXDP(13):
579 case AR5K_QUEUE_TXDP(14):
580 case AR5K_QUEUE_TXDP(15):
582 * unknown location, but this should
583 * set the location of queue-dependent
584 * transmit buffer's PHYSICAL address!!
586 DEBUG_PRINT(("Setting a transmit queue to address 0x%x (%u)\n",
590 * This address will be queried again
591 * later... store it!!
593 SET_MEM_L(s
->mem
, addr
, val
);
595 addr
-= AR5K_QCU_TXDP_BASE
;
599 * In case the given address specifies a
600 * valid DMA address, let's use it and copy
601 * the data into our device and process it
602 * once the queue is enabled
604 s
->transmit_queue_processed
[addr
] = 0;
605 s
->transmit_queue_address
[addr
] = (hwaddr
)val
;
607 DEBUG_PRINT(("unknown queue " TARGET_FMT_plx
"\n", addr
));
612 /* ath5k_hw.c: 1124 */
613 DEBUG_PRINT(("Setting receive queue size to %u byte\n",
615 SET_MEM_L(s
->mem
, addr
, val
);
618 case AR5K_QUEUE_QCUMASK(0):
619 case AR5K_QUEUE_QCUMASK(1):
620 case AR5K_QUEUE_QCUMASK(2):
621 case AR5K_QUEUE_QCUMASK(3):
622 case AR5K_QUEUE_QCUMASK(4):
623 case AR5K_QUEUE_QCUMASK(5):
624 case AR5K_QUEUE_QCUMASK(6):
625 case AR5K_QUEUE_QCUMASK(7):
626 case AR5K_QUEUE_QCUMASK(8):
627 case AR5K_QUEUE_QCUMASK(9):
628 case AR5K_QUEUE_QCUMASK(10):
629 case AR5K_QUEUE_QCUMASK(11):
630 case AR5K_QUEUE_QCUMASK(12):
631 case AR5K_QUEUE_QCUMASK(13):
632 case AR5K_QUEUE_QCUMASK(14):
633 case AR5K_QUEUE_QCUMASK(15):
634 DEBUG_PRINT(("ath5k_hw_reset_tx_queue for queue x (%u)\n", val
));
637 case AR5K_QUEUE_DFS_RETRY_LIMIT(0):
638 case AR5K_QUEUE_DFS_RETRY_LIMIT(1):
639 case AR5K_QUEUE_DFS_RETRY_LIMIT(2):
640 case AR5K_QUEUE_DFS_RETRY_LIMIT(3):
641 case AR5K_QUEUE_DFS_RETRY_LIMIT(4):
642 case AR5K_QUEUE_DFS_RETRY_LIMIT(5):
643 case AR5K_QUEUE_DFS_RETRY_LIMIT(6):
644 case AR5K_QUEUE_DFS_RETRY_LIMIT(7):
645 case AR5K_QUEUE_DFS_RETRY_LIMIT(8):
646 case AR5K_QUEUE_DFS_RETRY_LIMIT(9):
647 case AR5K_QUEUE_DFS_RETRY_LIMIT(10):
648 case AR5K_QUEUE_DFS_RETRY_LIMIT(11):
649 case AR5K_QUEUE_DFS_RETRY_LIMIT(12):
650 case AR5K_QUEUE_DFS_RETRY_LIMIT(13):
651 case AR5K_QUEUE_DFS_RETRY_LIMIT(14):
652 case AR5K_QUEUE_DFS_RETRY_LIMIT(15):
653 DEBUG_PRINT(("setting retry-limit for queue x to 0x%x (%u)\n",
657 case AR5K_QUEUE_DFS_LOCAL_IFS(0):
658 case AR5K_QUEUE_DFS_LOCAL_IFS(1):
659 case AR5K_QUEUE_DFS_LOCAL_IFS(2):
660 case AR5K_QUEUE_DFS_LOCAL_IFS(3):
661 case AR5K_QUEUE_DFS_LOCAL_IFS(4):
662 case AR5K_QUEUE_DFS_LOCAL_IFS(5):
663 case AR5K_QUEUE_DFS_LOCAL_IFS(6):
664 case AR5K_QUEUE_DFS_LOCAL_IFS(7):
665 case AR5K_QUEUE_DFS_LOCAL_IFS(8):
666 case AR5K_QUEUE_DFS_LOCAL_IFS(9):
667 case AR5K_QUEUE_DFS_LOCAL_IFS(10):
668 case AR5K_QUEUE_DFS_LOCAL_IFS(11):
669 case AR5K_QUEUE_DFS_LOCAL_IFS(12):
670 case AR5K_QUEUE_DFS_LOCAL_IFS(13):
671 case AR5K_QUEUE_DFS_LOCAL_IFS(14):
672 case AR5K_QUEUE_DFS_LOCAL_IFS(15):
673 DEBUG_PRINT(("setting interframe space for queue x to 0x%x (%u)\n",
677 case AR5K_QUEUE_MISC(0):
678 case AR5K_QUEUE_MISC(1):
679 case AR5K_QUEUE_MISC(2):
680 case AR5K_QUEUE_MISC(3):
681 case AR5K_QUEUE_MISC(4):
682 case AR5K_QUEUE_MISC(5):
683 case AR5K_QUEUE_MISC(6):
684 case AR5K_QUEUE_MISC(7):
685 case AR5K_QUEUE_MISC(8):
686 case AR5K_QUEUE_MISC(9):
687 case AR5K_QUEUE_MISC(10):
688 case AR5K_QUEUE_MISC(11):
689 case AR5K_QUEUE_MISC(12):
690 case AR5K_QUEUE_MISC(13):
691 case AR5K_QUEUE_MISC(14):
692 case AR5K_QUEUE_MISC(15):
693 DEBUG_PRINT(("setting options for queue x to 0x%x (%u)\n", val
, val
));
697 SET_MEM_L(s
->mem
, AR5K_SLEEP_CTL
, val
);
698 if (val
== AR5K_SLEEP_CTL_SLE_WAKE
) {
699 DEBUG_PRINT(("waking up device\n"));
704 * basically it just checks if power-down
705 * is false (val & AR5K_PCICFG_SPWR_DN == 0)
706 * but my AR5212 says 20 what has the same
707 * result but might be better ;-)
709 SET_MEM_L(s
->mem
, AR5K_PCICFG
, 0x14);
710 SET_MEM_L(s
->mem
, AR5K_STA_ID1
, 0x00049e2e);
712 SET_MEM_L(s
->mem
, AR5K_STA_ID1
, 0x0);
714 SET_MEM_L(s
->mem
, AR5K_PCICFG
, 0x34);
715 SET_MEM_L(s
->mem
, AR5K_STA_ID1
, AR5K_STA_ID1_PWR_SV
);
717 } else if (val
== AR5K_SLEEP_CTL_SLE_SLP
) {
718 DEBUG_PRINT(("putting device to sleep\n"));
720 DEBUG_PRINT(("unknown SLEEP command %u\n", val
));
726 * ...set the PHY operating mode after reset
729 /* ath5k_hw.c: 632 */
730 DEBUG_PRINT(("setting PHY operating mode (PLL)\n"));
735 * ...set the PHY operating mode after reset
738 /* ath5k_hw.c: 635 */
739 DEBUG_PRINT(("setting PHY operating mode (mode)\n"));
744 * ...set the PHY operating mode after reset
747 /* ath5k_hw.c: 636 */
748 DEBUG_PRINT(("setting PHY operating mode (turbo)\n"));
752 /******************************************************************
754 * ath5k_hw_init ---> ath5k_hw_radio_revision
756 ******************************************************************/
762 if (val
== AR5K_PHY_SHIFT_2GHZ
) {
763 DEBUG_PRINT(("requesting 2GHZ radio\n"));
764 SET_MEM_L(s
->mem
, AR5K_PHY(0x100), 0x4c047000);
766 /* ath5k_hw.c: 662 */
767 else if (val
== AR5K_PHY_SHIFT_5GHZ
) {
768 DEBUG_PRINT(("requesting 5GHZ radio\n"));
769 SET_MEM_L(s
->mem
, AR5K_PHY(0x100), 0x8e000000);
772 SET_MEM_L(s
->mem
, AR5K_SLEEP_CTL
, 0x0);
777 * request radio revision
780 /* ath5k_hw.c: 659 */
781 if (val
== AR5K_PHY_SHIFT_2GHZ
) {
782 DEBUG_PRINT(("requesting 2GHZ radio\n"));
783 SET_MEM_L(s
->mem
, AR5K_PHY(0x100), 0x4c047000); /* 1275359232); */
785 /* ath5k_hw.c: 662 */
786 else if (val
== AR5K_PHY_SHIFT_5GHZ
) {
787 DEBUG_PRINT(("requesting 5GHZ radio\n"));
788 SET_MEM_L(s
->mem
, AR5K_PHY(0x100), 0x7fffffff); /* 2382364672); */
790 /* ath5k_hw.c: 671 */
791 else if (val
== 0x00001c16) {
792 DEBUG_PRINT(("requesting radio\n"));
794 /* ath5k_hw.c: 674 */
795 else if (val
== 0x00010000) {
796 DEBUG_PRINT(("requesting radio 8 times...\n"));
797 /* NOW we request the radio revision (it was set before...) */
799 SET_MEM_L(s
->mem
, 0x9c00, 0x8e026023);
801 SET_MEM_L(s
->mem
, 0x9c00, 0x8e000000);
803 SET_MEM_L(s
->mem
, 0x9c00, 0x4c047000);
809 * Setting frequency is different for AR5210/AR5211/AR5212
811 * see ath5k_hw.c: 4590 ff
813 * they all set AR5K_PHY(0x27),
814 * AR5210 sets AR5K_PHY(0x30),
815 * AR5211 sets AR5K_PHY(0x34) and
816 * AR5212 sets AR5K_PHY(0x36)
819 * The virtual device seems to read out 0x34 for
820 * the current channel (e.g. after a packet has
825 fprintf(stderr
, "0x%04x => 0x%08x (27)\n", addr
, val
);
827 SET_MEM_L(s
->mem
, addr
, val
);
828 s
->current_frequency_partial_data
[0] = val
;
834 fprintf(stderr
, "0x%04x => 0x%08x (34)\n", addr
, val
);
836 SET_MEM_L(s
->mem
, addr
, val
);
837 s
->current_frequency_partial_data
[1] = val
;
842 * these are used by AR521 and AR5212 respectively,
843 * but we seem to simulate an AR5211 and the calls
844 * destroy our channel frequency mapping :-(
847 fprintf(stderr, "0x%04x => 0x%08x (30)\n", addr, val);
848 SET_MEM_L(s->mem, addr, val);
849 s->current_frequency_partial_data[1] = val;
853 fprintf(stderr, "0x%04x => 0x%08x (36)\n", addr, val);
854 SET_MEM_L(s->mem, addr, val);
855 s->current_frequency_partial_data[1] = val;
887 fprintf(stderr, "0x%04x => 0x%08x\n", addr, val);
890 /******************************************************************
892 * ath5k_hw_init ---> ath5k_hw_set_associd (aka. set BSSID)
894 ******************************************************************/
899 * Set simple BSSID mask on 5212
902 /* ath5k_hw.c: 2420 */
903 DEBUG_PRINT(("setting bssid mask\n"));
909 * Set BSSID which triggers the "SME Join" operation
912 /* ath5k_hw.c: 2432 & 2433 */
913 DEBUG_PRINT(("setting bssid : %c%c%c%c\n",
914 (val
<< 24) >> 24, (val
<< 16) >> 24,
915 (val
<< 8) >> 24, val
>> 24));
920 * a set to client(adhoc|managed) | ap | monitor mode is coming
922 * if there are more than one chip present, this
923 * call defines which chip is to be used!
926 /* ath5k_hw.c: 2358 */
927 DEBUG_PRINT(("a set to client | ap | monitor mode is coming for station %u\n", val
));
930 SET_MEM_L(s
->mem
, addr
, val
);
936 * seems to have a double-meaning:
938 * setting client mode AND power mode
941 /* ath5k_hw.c: 619 */
942 DEBUG_PRINT(("setting power mode\n"));
943 SET_MEM_L(s
->mem
, AR5K_STA_ID1
, val
);
944 SET_MEM_L(s
->mem
, AR5K_STA_ID0
, 0x800a1100);
945 /*SET_MEM_L(s->mem, 0xc, 0x1a7d823c); */
946 SET_MEM_L(s
->mem
, 0xc, 0x0);
947 SET_MEM_L(s
->mem
, 0x00c0, 0x01040000);
950 /* ath5k_hw.c: 2361 */
951 if (val
& AR5K_STA_ID1_ADHOC
& AR5K_STA_ID1_DESC_ANTENNA
) {
952 DEBUG_PRINT(("setting device into ADHOC mode\n"));
953 } else if (val
& AR5K_STA_ID1_AP
& AR5K_STA_ID1_RTS_DEF_ANTENNA
) {
954 DEBUG_PRINT(("setting device into managed mode\n"));
955 } else if (val
& AR5K_STA_ID1_DEFAULT_ANTENNA
) {
956 DEBUG_PRINT(("setting device into some other mode (probably monitor)\n"));
958 DEBUG_PRINT(("setting device into unknown mode\n"));
962 /******************************************************************
964 * ath5k_hw_init ---> ath5k_eeprom_init
966 ******************************************************************/
968 case AR5K_EEPROM_BASE
:
970 * an access to an offset inside the
971 * EEPROM uses an initialization of
972 * the address at this location
975 /* ath5k_hw.c: 1738 */
976 DEBUG_PRINT(("there will be an access to the EEPROM at %08x\n", val
));
979 * set the data that will be returned
980 * after calling AR5K_EEPROM_CMD=READ
984 case AR5K_EEPROM_MAGIC
:
985 WRITE_EEPROM(s
->mem
, AR5K_EEPROM_MAGIC_VALUE
);
988 case AR5K_EEPROM_PROTECT
:
989 WRITE_EEPROM(s
->mem
, 0);
992 case AR5K_EEPROM_REG_DOMAIN
:
994 * reg-domain central europe ???
996 WRITE_EEPROM(s
->mem
, 96);
999 case AR5K_EEPROM_VERSION
:
1000 WRITE_EEPROM(s
->mem
, AR5K_EEPROM_VERSION_3_4
);
1003 case AR5K_EEPROM_HDR
:
1004 WRITE_EEPROM(s
->mem
, 23046);
1009 * an radio-GHZ specific eeprom data (AR5K_EEPROM_ANT_GAIN)
1011 * on my AR5212 it is 0
1014 /* ath5k_hw.c: 2023 */
1015 WRITE_EEPROM(s
->mem
, 0);
1020 * before we read the MAC addr, we read this (???)
1022 * ATTENTION: this value is present in the EEPROM!!
1025 /* ath5k_hw.c : 2185 */
1030 * 1st part of MAC-addr
1032 DEBUG_PRINT(("EEPROM request first part of MAC\n"));
1033 WRITE_EEPROM(s
->mem
, (s
->phys
[0] << 8) | s
->phys
[1]);
1038 * 2nd part of MAC-addr
1040 DEBUG_PRINT(("EEPROM request second part of MAC\n"));
1041 WRITE_EEPROM(s
->mem
, (s
->phys
[2] << 8) | s
->phys
[3]);
1046 * 3rd part of MAC-addr
1048 DEBUG_PRINT(("EEPROM request third part of MAC\n"));
1049 WRITE_EEPROM(s
->mem
, (s
->phys
[4] << 8) | s
->phys
[5]);
1053 * ATTENTION: if we modify anything in the
1054 * eeprom, we might get (at least in linux we
1055 * do) an EEPROM-checksum error!!
1060 * this is not part of the EEPROM dumps for some reason!!
1062 DEBUG_PRINT(("EEPROM request 0x0\n"));
1063 WRITE_EEPROM(s
->mem
, 0x13);
1067 if (!get_eeprom_data(s
, val
, &h
)) {
1069 * we have a hit in the internal eeprom-buffer
1071 DEBUG_PRINT(("EEPROM hit %u at %u\n", h
, val
));
1072 WRITE_EEPROM(s
->mem
, h
);
1074 DEBUG_PRINT(("EEPROM request at %08x is unknown\n", val
));
1075 WRITE_EEPROM(s
->mem
, 0);
1081 case AR5K_EEPROM_CMD
:
1083 * what type of access is specified as well
1086 /* ath5k_hw.c: 1739 */
1087 if (val
& AR5K_EEPROM_CMD_READ
) {
1088 DEBUG_PRINT(("the EEPROM access will be READ\n"));
1091 * tell the device the read was successful
1093 SET_MEM_L(s
->mem
, AR5K_EEPROM_STAT_5210
, AR5K_EEPROM_STAT_RDDONE
);
1094 SET_MEM_L(s
->mem
, AR5K_EEPROM_STAT_5211
, AR5K_EEPROM_STAT_RDDONE
);
1096 * and return the data that was set
1097 * during the write to AR5K_EEPROM_BASE
1100 DEBUG_PRINT(("the EEPROM access will be UNKNOWN\n"));
1101 fprintf(stderr
, "Is this a write to the eeprom??\n");
1106 /******************************************************************
1108 * additional reverse engineering:
1110 ******************************************************************/
1112 case AR5K_USEC_5210
: /* new */
1113 SET_MEM_L(s
->mem
, AR5K_XRMODE
, 0x2a80001a);
1114 SET_MEM_L(s
->mem
, AR5K_XRTIMEOUT
, 0x13881c20);
1117 case AR5K_PHY_AGCCTL
: /* new */
1118 if (val
& AR5K_PHY_AGCCTL_CAL
) {
1119 SET_MEM_L(s
->mem
, AR5K_PHY_AGCCTL
, val
& (~AR5K_PHY_AGCCTL_CAL
));
1120 } else if (val
& AR5K_PHY_AGCCTL_NF
) {
1121 SET_MEM_L(s
->mem
, AR5K_PHY_AGCCTL
, val
& (~AR5K_PHY_AGCCTL_NF
));
1126 if (addr
/ 4 < Atheros_WLAN_MEM_SIZE
) {
1127 SET_MEM_L(s
->mem
, addr
, val
);
1130 if ((addr
>= AR5K_PCU_MIN
) &&
1131 (addr
<= AR5K_PCU_MAX
)) {
1132 DEBUG_PRINT(("Setting up ini-registers...!!\n"));
1134 DEBUG_PRINT(("Unknown call to memory!!\n"));
1140 #endif /* CONFIG_WIN32 */