Clean include statements
[qemu/ar7.git] / hw / net / atheros_wlan_io.c
blobd439a73bba9694df5cbcec208f9068d930b0c98e
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 "qemu/osdep.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 <sys/shm.h>
44 #include <sys/socket.h>
45 #include <sys/ipc.h>
46 #include <sys/sem.h>
47 #include <sys/mman.h>
48 #include <netinet/in.h>
49 #include <netdb.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
60 #include "hw/ath5k.h"
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
86 * EEPROM data!!
88 static int get_eeprom_data(Atheros_WLANState *s, uint32_t addr, uint32_t *val)
90 if (val == NULL) {
91 return 1;
94 /* why?? but seems necessary... */
95 addr--;
97 if (addr > s->eeprom_size) {
98 return 2;
101 *val = s->eeprom_data[addr];
102 return 0;
110 static void updateFrequency(Atheros_WLANState *s)
112 int i;
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]) {
117 continue;
120 if (Atheros_WLAN_frequency_data[i].value2 !=
121 s->current_frequency_partial_data[1]) {
122 continue;
125 new_frequency = Atheros_WLAN_frequency_data[i].frequency;
126 break;
129 if (new_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,
138 uint32_t val);
140 static void Atheros_WLAN_mmio_writeb(void *opaque, hwaddr addr,
141 uint32_t val)
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,
149 uint32_t val)
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,
157 uint32_t val)
159 mm_writel(opaque, Atheros_WLAN_MEM_SANITIZE(addr), val);
160 DEBUG_PRINT((" through call: mmio_writel " TARGET_FMT_plx
161 " val 0x%x (%u)\n",
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"));
171 return 0;
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"));
180 return 0;
183 static uint32_t Atheros_WLAN_mmio_readl(void *opaque, hwaddr addr)
185 uint32_t val;
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));
190 return val;
193 static uint64_t Atheros_WLAN_read(void *opaque, hwaddr addr,
194 unsigned size)
196 Atheros_WLANState *s = opaque;
197 uint64_t val;
198 switch (size) {
199 case 1:
200 val = Atheros_WLAN_mmio_readb(s, addr);
201 break;
202 case 2:
203 val = Atheros_WLAN_mmio_readw(s, addr);
204 break;
205 case 4:
206 val = Atheros_WLAN_mmio_readl(s, addr);
207 break;
208 default:
209 assert(!"bad size");
211 return val;
214 static void Atheros_WLAN_write(void *opaque, hwaddr addr,
215 uint64_t val, unsigned size)
217 Atheros_WLANState *s = opaque;
218 switch (size) {
219 case 1:
220 Atheros_WLAN_mmio_writeb(s, addr, val);
221 break;
222 case 2:
223 Atheros_WLAN_mmio_writew(s, addr, val);
224 break;
225 case 4:
226 Atheros_WLAN_mmio_writel(s, addr, val);
227 break;
228 default:
229 assert(!"bad size");
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) \
251 (x == 1) ? 0 : \
252 (x == 2) ? 1 : \
253 (x == 4) ? 2 : \
254 (x == 8) ? 3 : \
255 (x == 16) ? 4 : \
256 (x == 32) ? 5 : \
257 (x == 64) ? 6 : \
258 (x == 128) ? 7 : \
259 (x == 256) ? 8 : \
260 (x == 512) ? 9 : \
261 (x == 1024) ? 10 : \
262 (x == 2048) ? 11 : \
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);
270 switch (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
282 * have to be handled
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);
292 break;
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!!
300 case AR5K_PISR:
301 if (s->device_driver_type == WINXP_DRIVER) {
302 addr = AR5K_RAC_PISR;
303 /* fall through... */
304 } else {
305 break;
308 case AR5K_RAC_PISR:
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));
315 break;
317 case AR5K_RAC_SISR0:
318 case AR5K_RAC_SISR1:
319 case AR5K_RAC_SISR2:
320 case AR5K_RAC_SISR3:
321 case AR5K_RAC_SISR4:
322 val = 0;
323 SET_MEM_L(s->mem, addr, 0);
324 DEBUG_PRINT(("secondary irq status\n"));
325 break;
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...
334 case AR5K_RXDP:
335 /* SET_MEM_L(s->mem, addr, 0); */
336 break;
338 default:
339 break;
341 return val;
344 static void mm_writel(Atheros_WLANState *s, hwaddr addr,
345 uint32_t val)
347 uint32_t h;
348 switch (addr) {
350 /******************************************************************
352 * ath5k_hw_init ---> ath5k_hw_nic_wakeup
354 ******************************************************************/
356 case AR5K_RESET_CTL:
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);
376 } else {
377 /* ath5k_hw.c: 626 */
378 DEBUG_PRINT(("reset device (generic)\n"));
381 * warm-start device
383 SET_MEM_L(s->mem, AR5K_RESET_CTL, 0);
385 break;
388 /******************************************************************
390 * interrupt handling
392 ******************************************************************/
394 case AR5K_IER:
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;
409 } else {
410 DEBUG_PRINT(("setting interrupt-enable to undefined value!!\n"));
412 break;
414 case AR5K_GPIODO:
415 if (val == 0x2) {
416 SET_MEM_L(s->mem, AR5K_GPIODI, 0x3);
418 break;
420 case AR5K_GPIODI: /* new */
421 if (val == 0x2) {
422 SET_MEM_L(s->mem, AR5K_GPIODO, 0x3);
424 break;
426 case AR5K_PIMR:
427 /* ath5k_hw.c: 1668 */
428 DEBUG_PRINT(("setting primary interrupt-mask to 0x%x (%u)\n",
429 val, val));
430 s->interrupt_p_mask = val;
432 SET_MEM_L(s->mem, addr, val);
433 break;
435 case AR5K_SIMR0:
436 DEBUG_PRINT(("setting secondary interrupt-mask 0 to 0x%x (%u)\n",
437 val, val));
438 s->interrupt_s_mask[0] = val;
439 break;
440 case AR5K_SIMR1:
441 DEBUG_PRINT(("setting secondary interrupt-mask 1 to 0x%x (%u)\n",
442 val, val));
443 s->interrupt_s_mask[1] = val;
444 break;
445 case AR5K_SIMR2:
446 DEBUG_PRINT(("setting secondary interrupt-mask 2 to 0x%x (%u)\n",
447 val, val));
448 s->interrupt_s_mask[2] = val;
449 break;
450 case AR5K_SIMR3:
451 DEBUG_PRINT(("setting secondary interrupt-mask 3 to 0x%x (%u)\n",
452 val, val));
453 s->interrupt_s_mask[3] = val;
454 break;
455 case AR5K_SIMR4:
456 DEBUG_PRINT(("setting secondary interrupt-mask 4 to 0x%x (%u)\n",
457 val, val));
458 s->interrupt_s_mask[4] = val;
459 break;
461 /******************************************************************
463 * ath5k queuing (for transmit and receive buffers)
465 ******************************************************************/
467 case AR5K_QCU_TXE:
468 /* ath5k_hw.c: 1423ff */
470 /* enable specified queue (nr in val) */
471 val = FASTBINLOG(val);
473 DEBUG_PRINT(("queue %u enabled\n", val));
474 if (val < 16) {
475 s->transmit_queue_enabled[val] = 1;
476 Atheros_WLAN_handleTxBuffer(s, val);
477 } else {
478 DEBUG_PRINT(("unknown queue 0x%x (%u)\n", val, val));
480 break;
482 case AR5K_QCU_TXD:
483 /* ath5k_hw.c: 1423ff */
485 /* disable specified queue (nr in val) */
486 val = FASTBINLOG(val);
488 DEBUG_PRINT(("queue %u disabled\n", val));
489 if (val < 16) {
490 s->transmit_queue_enabled[val] = 0;
491 } else {
492 DEBUG_PRINT(("unknown queue 0x%x (%u)\n", val, val));
494 break;
496 case AR5K_IFS0:
497 case AR5K_IFS1:
498 DEBUG_PRINT(("TODO: find out what inter frame spacing registers are used for...\n"));
499 break;
501 case AR5K_CFG:
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);
507 break;
509 case AR5K_TXCFG:
510 /* ath5k_hw.c: 1122 */
511 DEBUG_PRINT(("Setting transmit queue size to %u byte\n",
512 (1 << (val + 2))));
514 s->transmit_queue_size = (1 << (val + 2));
515 break;
517 case AR5K_CR:
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"));
534 } else {
535 DEBUG_PRINT(("Undefined TX/RX en/disable\n"));
537 break;
539 case AR5K_RXDP:
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",
546 val, val));
549 * This address will be queried again
550 * later... store it!!
552 if (val == 0) {
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;
563 break;
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",
587 val, val));
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;
596 addr /= 4;
597 if (addr < 16) {
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;
606 } else {
607 DEBUG_PRINT(("unknown queue " TARGET_FMT_plx "\n", addr));
609 break;
611 case AR5K_RXCFG:
612 /* ath5k_hw.c: 1124 */
613 DEBUG_PRINT(("Setting receive queue size to %u byte\n",
614 (1 << (val + 2))));
615 SET_MEM_L(s->mem, addr, val);
616 break;
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));
635 break;
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",
654 val, val));
655 break;
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",
674 val, val));
675 break;
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));
694 break;
696 case AR5K_SLEEP_CTL:
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"));
702 * yes, we are awake
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);
711 #if 0
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);
716 #endif
717 } else if (val == AR5K_SLEEP_CTL_SLE_SLP) {
718 DEBUG_PRINT(("putting device to sleep\n"));
719 } else {
720 DEBUG_PRINT(("unknown SLEEP command %u\n", val));
722 break;
724 case AR5K_PHY_PLL:
726 * ...set the PHY operating mode after reset
729 /* ath5k_hw.c: 632 */
730 DEBUG_PRINT(("setting PHY operating mode (PLL)\n"));
731 break;
733 case AR5K_PHY_MODE:
735 * ...set the PHY operating mode after reset
738 /* ath5k_hw.c: 635 */
739 DEBUG_PRINT(("setting PHY operating mode (mode)\n"));
740 break;
742 case AR5K_PHY_TURBO:
744 * ...set the PHY operating mode after reset
747 /* ath5k_hw.c: 636 */
748 DEBUG_PRINT(("setting PHY operating mode (turbo)\n"));
749 break;
752 /******************************************************************
754 * ath5k_hw_init ---> ath5k_hw_radio_revision
756 ******************************************************************/
758 case AR5K_PHY(0):
760 * Unknown
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);
773 break;
775 case AR5K_PHY(0x20):
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...) */
798 #if 0
799 SET_MEM_L(s->mem, 0x9c00, 0x8e026023);
800 #endif
801 SET_MEM_L(s->mem, 0x9c00, 0x8e000000);
803 SET_MEM_L(s->mem, 0x9c00, 0x4c047000);
806 break;
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
821 * been received)!!
823 case AR5K_PHY(0x27):
824 #if 0
825 fprintf(stderr, "0x%04x => 0x%08x (27)\n", addr, val);
826 #endif
827 SET_MEM_L(s->mem, addr, val);
828 s->current_frequency_partial_data[0] = val;
829 updateFrequency(s);
830 break;
832 case AR5K_PHY(0x34):
833 #if 0
834 fprintf(stderr, "0x%04x => 0x%08x (34)\n", addr, val);
835 #endif
836 SET_MEM_L(s->mem, addr, val);
837 s->current_frequency_partial_data[1] = val;
838 updateFrequency(s);
839 break;
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 :-(
846 case AR5K_PHY(0x30):
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;
850 updateFrequency(s);
851 break;
852 case AR5K_PHY(0x36):
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;
856 updateFrequency(s);
857 break;
861 case AR5K_PHY(0x21):
862 case AR5K_PHY(0x22):
863 case AR5K_PHY(0x23):
864 case AR5K_PHY(0x24):
865 case AR5K_PHY(0x25):
866 case AR5K_PHY(0x26):
867 case AR5K_PHY(0x28):
868 case AR5K_PHY(0x29):
869 case AR5K_PHY(0x31):
870 case AR5K_PHY(0x32):
871 case AR5K_PHY(0x33):
872 case AR5K_PHY(0x35):
873 case AR5K_PHY(0x37):
874 case AR5K_PHY(0x38):
875 case AR5K_PHY(0x39):
876 case AR5K_PHY(0x40):
877 case AR5K_PHY(0x41):
878 case AR5K_PHY(0x42):
879 case AR5K_PHY(0x43):
880 case AR5K_PHY(0x44):
881 case AR5K_PHY(0x45):
882 case AR5K_PHY(0x46):
883 case AR5K_PHY(0x47):
884 case AR5K_PHY(0x48):
885 case AR5K_PHY(0x49):
886 case AR5K_PHY(0x50):
887 fprintf(stderr, "0x%04x => 0x%08x\n", addr, val);
888 break;*/
890 /******************************************************************
892 * ath5k_hw_init ---> ath5k_hw_set_associd (aka. set BSSID)
894 ******************************************************************/
896 case AR5K_BSS_IDM0:
897 case AR5K_BSS_IDM1:
899 * Set simple BSSID mask on 5212
902 /* ath5k_hw.c: 2420 */
903 DEBUG_PRINT(("setting bssid mask\n"));
904 break;
906 case AR5K_BSS_ID0:
907 case AR5K_BSS_ID1:
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));
916 break;
918 case AR5K_STA_ID0:
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));
929 /* ext */
930 SET_MEM_L(s->mem, addr, val);
932 break;
934 case AR5K_STA_ID1:
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"));
957 } else {
958 DEBUG_PRINT(("setting device into unknown mode\n"));
960 break;
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
982 switch (val) {
983 #if 0
984 case AR5K_EEPROM_MAGIC:
985 WRITE_EEPROM(s->mem, AR5K_EEPROM_MAGIC_VALUE);
986 break;
988 case AR5K_EEPROM_PROTECT:
989 WRITE_EEPROM(s->mem, 0);
990 break;
992 case AR5K_EEPROM_REG_DOMAIN:
994 * reg-domain central europe ???
996 WRITE_EEPROM(s->mem, 96);
997 break;
999 case AR5K_EEPROM_VERSION:
1000 WRITE_EEPROM(s->mem, AR5K_EEPROM_VERSION_3_4);
1001 break;
1003 case AR5K_EEPROM_HDR:
1004 WRITE_EEPROM(s->mem, 23046);
1005 break;
1007 case 195:
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);
1016 break;
1018 case 0x20:
1020 * before we read the MAC addr, we read this (???)
1022 * ATTENTION: this value is present in the EEPROM!!
1025 /* ath5k_hw.c : 2185 */
1026 break;
1028 case 0x1f:
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]);
1034 break;
1036 case 0x1e:
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]);
1042 break;
1044 case 0x1d:
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]);
1050 break;
1051 #endif
1053 * ATTENTION: if we modify anything in the
1054 * eeprom, we might get (at least in linux we
1055 * do) an EEPROM-checksum error!!
1058 case 0x0:
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);
1064 break;
1066 default:
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);
1073 } else {
1074 DEBUG_PRINT(("EEPROM request at %08x is unknown\n", val));
1075 WRITE_EEPROM(s->mem, 0);
1077 break;
1079 break;
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
1099 } else {
1100 DEBUG_PRINT(("the EEPROM access will be UNKNOWN\n"));
1101 fprintf(stderr, "Is this a write to the eeprom??\n");
1103 break;
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);
1115 break;
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));
1123 break;
1125 default:
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"));
1133 } else {
1134 DEBUG_PRINT(("Unknown call to memory!!\n"));
1136 break;
1140 #endif /* CONFIG_WIN32 */