Merge tag 'v9.1.0'
[qemu/ar7.git] / hw / net / atheros_wlan_ap.c
blob7a6c2ac0f02aba0b5690312b68a2d1b2066b5490
1 /**
2 * QEMU WLAN access point emulation
4 * Copyright (c) 2008 Clemens Kolbitsch
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
24 * Modifications:
25 * 2008-February-24 Clemens Kolbitsch :
26 * New implementation based on ne2000.c
30 #include "qemu/osdep.h"
32 #if defined(CONFIG_WIN32)
33 #warning("not compiled for Windows host")
34 #else
36 #include "hw.h"
37 #include "pci/pci.h"
38 #include "pc.h"
39 #include "net/net.h"
40 #include "qemu/timer.h"
42 #include <sys/shm.h>
43 #include <sys/socket.h>
44 #include <sys/ipc.h>
45 #include <sys/sem.h>
46 #include <sys/mman.h>
47 #include <netinet/in.h>
48 #include <netdb.h>
53 * PCI and EEPROM definitions
55 #include "hw/atheros_wlan.h"
56 #include "hw/atheros_wlan_ap.h"
57 #include "hw/atheros_wlan_io.h"
58 #include "hw/atheros_wlan_packet.h"
61 * MadWifi OPENHAL atheros constants
63 #include "hw/ath5k_hw.h"
64 #include "hw/ath5kreg.h"
65 #include "hw/ath5k.h"
67 static int semaphore_helper(int semaphore, int sem_op, int semaphore_nr, short flags)
69 struct sembuf semp;
70 semp.sem_num = semaphore_nr;
71 semp.sem_op = sem_op;
72 semp.sem_flg = flags;
74 if (semaphore == -1) {
76 * We don't have a semaphore... probably not
77 * that bad, but having one is better :-)
79 return -1;
82 int ret;
83 while ((ret = semop(semaphore, &semp, 1)) < 0) {
84 if (errno == EAGAIN && flags == IPC_NOWAIT) {
85 return errno;
86 } else if (errno != EINTR) {
87 fprintf(stderr, "Semaphore error: 0x%x / %u\n", errno, errno);
88 return errno;
92 return ret;
96 static int signal_semaphore(int semaphore, int semaphore_nr)
98 return semaphore_helper(semaphore, 1, semaphore_nr, 0);
100 static int wait_semaphore(int semaphore, int semaphore_nr)
102 return semaphore_helper(semaphore, -1, semaphore_nr, 0);
105 void Atheros_WLAN_insert_frame(Atheros_WLANState *s, struct mac80211_frame *frame)
107 struct mac80211_frame *i_frame;
109 wait_semaphore(s->access_semaphore, 0);
111 s->inject_queue_size++;
112 i_frame = s->inject_queue;
113 if (!i_frame) {
114 s->inject_queue = frame;
115 } else {
116 while (i_frame->next_frame) {
117 i_frame = i_frame->next_frame;
120 i_frame->next_frame = frame;
123 if (!s->inject_timer_running) {
124 // if the injection timer is not
125 // running currently, let's schedule
126 // one run...
127 s->inject_timer_running = 1;
128 timer_mod(s->inject_timer, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + 5);
131 signal_semaphore(s->access_semaphore, 0);
134 static void Atheros_WLAN_beacon_timer(void *opaque)
136 struct mac80211_frame *frame;
137 Atheros_WLANState *s = (Atheros_WLANState *)opaque;
139 frame = Atheros_WLAN_create_beacon_frame();
140 if (frame) {
141 Atheros_WLAN_init_frame(s, frame);
142 Atheros_WLAN_insert_frame(s, frame);
145 timer_mod(s->beacon_timer, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + 500);
148 static void Atheros_WLAN_inject_timer(void *opaque)
150 Atheros_WLANState *s = (Atheros_WLANState *)opaque;
151 struct mac80211_frame *frame;
153 wait_semaphore(s->access_semaphore, 0);
155 frame = s->inject_queue;
156 if (frame) {
157 // remove from queue
158 s->inject_queue_size--;
159 s->inject_queue = frame->next_frame;
161 signal_semaphore(s->access_semaphore, 0);
163 if (!frame) {
164 goto timer_done;
167 if (s->receive_queue_address == 0) {
168 // we drop the packet
169 } else {
170 Atheros_WLAN_handleRxBuffer(s, frame, frame->frame_length);
173 free(frame);
175 timer_done:
176 wait_semaphore(s->access_semaphore, 0);
178 if (s->inject_queue_size > 0) {
179 // there are more packets... schedule
180 // the timer for sending them as well
181 timer_mod(s->inject_timer, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + 25);
182 } else {
183 // we wait until a new packet schedules
184 // us again
185 s->inject_timer_running = 0;
188 signal_semaphore(s->access_semaphore, 0);
192 static int Atheros_WLAN_can_receive(NetClientState *ncs)
194 Atheros_WLANState *s = qemu_get_nic_opaque(ncs);
196 if (s->ap_state != Atheros_WLAN__STATE_ASSOCIATED) {
197 // we are currently not connected
198 // to the access point
199 return 0;
202 if (s->inject_queue_size > Atheros_WLAN__MAX_INJECT_QUEUE_SIZE) {
203 // overload, please give me some time...
204 return 0;
207 return 1;
210 static ssize_t Atheros_WLAN_receive(NetClientState *ncs,
211 const uint8_t *buf, size_t size)
213 Atheros_WLANState *s = qemu_get_nic_opaque(ncs);
214 struct mac80211_frame *frame;
216 if (!Atheros_WLAN_can_receive(ncs)) {
217 // this should not happen, but in
218 // case it does, let's simply drop
219 // the packet
220 return -1;
223 if (!s) {
224 return -1;
228 * A 802.3 packet comes from the qemu network. The
229 * access points turns it into a 802.11 frame and
230 * forwards it to the wireless device
232 frame = Atheros_WLAN_create_data_packet(s, buf, size);
233 if (frame) {
234 Atheros_WLAN_init_frame(s, frame);
235 Atheros_WLAN_insert_frame(s, frame);
237 return size;
240 static void Atheros_WLAN_cleanup(NetClientState *ncs)
242 #if 0
243 Atheros_WLANState *d = ncs->opaque;
244 timer_del(d->poll_timer);
245 timer_free(d->poll_timer);
246 #endif
249 static NetClientInfo net_info = {
250 .type = NET_CLIENT_DRIVER_NIC,
251 .size = sizeof(NICState),
252 .can_receive = Atheros_WLAN_can_receive,
253 .receive = Atheros_WLAN_receive,
254 .cleanup = Atheros_WLAN_cleanup,
257 void Atheros_WLAN_setup_ap(NICInfo *nd, PCIAtheros_WLANState *d)
259 Atheros_WLANState *s;
260 s = &d->Atheros_WLAN;
262 s->ap_state = Atheros_WLAN__STATE_NOT_AUTHENTICATED;
263 s->ap_macaddr[0] = 0x00;
264 s->ap_macaddr[1] = 0x13;
265 s->ap_macaddr[2] = 0x46;
266 s->ap_macaddr[3] = 0xbf;
267 s->ap_macaddr[4] = 0x31;
268 s->ap_macaddr[5] = 0x59;
270 s->inject_timer_running = 0;
271 s->inject_sequence_number = 0;
273 s->inject_queue = NULL;
274 s->inject_queue_size = 0;
276 s->access_semaphore = semget(ATHEROS_WLAN_ACCESS_SEM_KEY, 1, 0666 | IPC_CREAT);
277 semctl(s->access_semaphore, 0, SETVAL, 1);
279 s->beacon_timer = timer_new_ns(QEMU_CLOCK_REALTIME, Atheros_WLAN_beacon_timer, s);
280 timer_mod(s->beacon_timer, qemu_clock_get_ns(QEMU_CLOCK_REALTIME));
282 // setup the timer but only schedule
283 // it when necessary...
284 s->inject_timer = timer_new_ns(QEMU_CLOCK_REALTIME, Atheros_WLAN_inject_timer, s);
286 s->nic = qemu_new_nic(&net_info, &s->conf, nd->model, nd->name, s);
288 qemu_format_nic_info_str(qemu_get_queue(s->nic), s->macaddr);
291 void Atheros_WLAN_disable_irq(void *arg)
293 Atheros_WLANState *s = (Atheros_WLANState *)arg;
294 SET_MEM_L(s->mem, ATH_HW_IRQ_PENDING, ATH_HW_IRQ_PENDING_FALSE);
295 qemu_set_irq(s->irq, 0);
296 DEBUG_PRINT((">> Disabling irq\n"));
299 void Atheros_WLAN_enable_irq(void *arg)
301 Atheros_WLANState *s = (Atheros_WLANState *)arg;
303 if (!s->interrupt_enabled) {
304 DEBUG_PRINT((">> Wanted to enable irq, but they are disabled\n"));
305 Atheros_WLAN_disable_irq(s);
306 return;
309 DEBUG_PRINT((">> Enabling irq\n"));
310 SET_MEM_L(s->mem, ATH_HW_IRQ_PENDING, ATH_HW_IRQ_PENDING_TRUE);
311 qemu_set_irq(s->irq, 1);
315 void Atheros_WLAN_update_irq(void *arg)
317 Atheros_WLANState *s = (Atheros_WLANState *)arg;
318 DEBUG_PRINT((">> Updating... irq-enabled is %u\n", s->interrupt_enabled));
320 * NOTE: Since we use shared interrupts
321 * the device driver will check if the
322 * interrupt really comes from this hardware
324 * This is done by checking the
325 * ATH_HW_IRQ_PENDING memory...
327 if (/*(!s->interrupt_enabled) ||*/
328 (s->pending_interrupts == NULL)) {
329 SET_MEM_L(s->mem, AR5K_RAC_PISR, 0);
330 goto disable_further_interrupts;
334 * Make sure this is done atomically!!
336 wait_semaphore(s->access_semaphore, 0);
337 uint32_t status = 0x0;
338 struct pending_interrupt *i = s->pending_interrupts;
339 struct pending_interrupt *next;
341 s->pending_interrupts = NULL;
342 while (i != NULL) {
343 next = i->next;
344 if (1) { //(s->interrupt_p_mask & i->status)
345 status |= i->status;
347 free(i);
349 i = next;
352 SET_MEM_L(s->mem, AR5K_RAC_PISR, status);
353 DEBUG_PRINT((">> Status set to %u\n", status));
355 * Atomic part done...
357 signal_semaphore(s->access_semaphore, 0);
360 disable_further_interrupts:
362 * NOTE: At last, it will check if any
363 * more interrupts are pending. The call
364 * to check what type of interrupt was
365 * pending already put down the interrupt_pending
366 * bit for us (check the readl function for RAC)
368 * if_ath.c: 921
370 Atheros_WLAN_disable_irq(s);
374 void Atheros_WLAN_append_irq(Atheros_WLANState *s, struct pending_interrupt intr)
376 struct pending_interrupt *new_intr;
377 new_intr = (struct pending_interrupt *)malloc(sizeof(struct pending_interrupt));
378 memcpy(new_intr, &intr, sizeof(intr));
381 * Make sure this is done atomically!!
383 wait_semaphore(s->access_semaphore, 0);
385 if (s->pending_interrupts == NULL) {
386 s->pending_interrupts = new_intr;
387 } else {
389 * Insert at the end of the
390 * list to assure correct order
391 * of interrupts!
393 struct pending_interrupt *i = s->pending_interrupts;
394 while (i->next != NULL) {
395 i = i->next;
398 new_intr->next = NULL;
399 i->next = new_intr;
403 * Atomic part done...
405 signal_semaphore(s->access_semaphore, 0);
415 void Atheros_WLAN_handleRxBuffer(Atheros_WLANState *s, struct mac80211_frame *frame, uint32_t frame_length)
417 struct ath_desc desc;
418 struct ath5k_ar5212_rx_status *rx_status;
419 rx_status = (struct ath5k_ar5212_rx_status *)&desc.ds_hw[0];
421 if (s->receive_queue_address == 0) {
422 return;
425 cpu_physical_memory_read(s->receive_queue_address, (uint8_t *)&desc, sizeof(desc));
428 * Put some good base-data into
429 * the descriptor. Length & co
430 * will be modified below...
432 * NOTE: Better set everything correctly
434 * Look at ath5k_hw.c: proc_tx_desc
436 desc.ds_ctl0 = 0x0;
437 desc.ds_ctl1 = 0x9c0;
438 desc.ds_hw[0] = 0x126d806a;
439 desc.ds_hw[1] = 0x49860003;
440 desc.ds_hw[2] = 0x0;
441 desc.ds_hw[3] = 0x0;
445 * Filter out old length and put in correct value...
447 rx_status->rx_status_0 &= ~AR5K_AR5212_DESC_RX_STATUS0_DATA_LEN;
448 rx_status->rx_status_0 |= frame_length;
449 rx_status->rx_status_0 &= ~AR5K_AR5211_DESC_RX_STATUS0_MORE;
452 * Write descriptor and packet back to DMA memory...
454 cpu_physical_memory_write(s->receive_queue_address, (uint8_t *)&desc, sizeof(desc));
455 cpu_physical_memory_write((hwaddr)desc.ds_data, (uint8_t *)frame, sizeof(struct mac80211_frame));
458 * Set address to next position
459 * in single-linked list
461 * The receive list's last element
462 * points to itself to avoid overruns.
463 * This way, at some point no more
464 * packets will be received, but (I
465 * ASSUME) that it is the drivers
466 * responsibility to reset the address
467 * list!
470 * NOTE: It seems the real madwifi cannot
471 * handle multiple packets at once. so we
472 * set the buffer to NULL to make the injection
473 * fail next time until an interrupt was
474 * received by the driver and a new buffer
475 * is registered!!
477 s->receive_queue_address =
478 ((++s->receive_queue_count) > MAX_CONCURRENT_RX_FRAMES)
480 : (hwaddr)desc.ds_link;
483 DEBUG_PRINT((">> Enabling rx\n"));
485 * Notify the driver about the new packet
487 struct pending_interrupt intr;
488 intr.status = AR5K_INT_RX;
489 Atheros_WLAN_append_irq(s, intr);
490 Atheros_WLAN_enable_irq(s);
495 void Atheros_WLAN_handleTxBuffer(Atheros_WLANState *s, uint32_t queue)
497 struct ath_desc desc;
498 struct mac80211_frame frame;
500 if (s->transmit_queue_address[queue] == 0) {
501 return;
504 cpu_physical_memory_read(s->transmit_queue_address[queue], (uint8_t *)&desc, sizeof(desc));
506 if (s->transmit_queue_processed[queue]) {
508 * Maybe we already processed the frame
509 * and have not gotten the address of the
510 * next frame buffer but still got a call
511 * to send the next frame
513 * this way we have to process the next
514 * frame in the single linked list!!
516 s->transmit_queue_address[queue] = (hwaddr)desc.ds_link;
519 * And now get the frame we really have to process...
521 cpu_physical_memory_read(s->transmit_queue_address[queue], (uint8_t *)&desc, sizeof(desc));
524 uint32_t segment_len, frame_length = 0, more;
525 uint8_t *frame_pos = (uint8_t *)&frame;
526 struct ath5k_ar5212_tx_desc *tx_desc;
527 tx_desc = (struct ath5k_ar5212_tx_desc *)&desc.ds_ctl0;
528 do {
529 more = tx_desc->tx_control_1 & AR5K_AR5211_DESC_TX_CTL1_MORE;
530 segment_len = tx_desc->tx_control_1 & AR5K_AR5212_DESC_TX_CTL1_BUF_LEN;
532 cpu_physical_memory_read((hwaddr)desc.ds_data, frame_pos, segment_len);
533 frame_pos += segment_len;
534 frame_length += segment_len;
538 * Notify successful transmission
540 * NOTE: It'd be better to leave the
541 * descriptor as it is and only modify
542 * the transmit-ok-bits --> this way
543 * the timestamp and co. would stay
544 * valid...
546 * Look at ath5k_hw.c: proc_tx_desc
548 * NOTE: Not sure if this acknowledgement
549 * must be copied back for every single
550 * descriptor in a multi-segment frame,
551 * but better safe than sorry!!
553 desc.ds_ctl0 = 0x213f002f;
554 desc.ds_ctl1 = 0x2b;
555 desc.ds_hw[0] = 0xf0000;
556 desc.ds_hw[1] = 0x1b;
557 desc.ds_hw[2] = 0xab640001;
558 desc.ds_hw[3] = 0x4a019;
562 * struct ath5k_tx_status *tx_status = (struct ath5k_tx_status*)&desc.ds_hw[2];
563 * tx_status->tx_status_1 |= AR5K_DESC_TX_STATUS1_DONE;
564 * tx_status->tx_status_0 |= AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK;
567 * Write descriptor back to DMA memory...
569 cpu_physical_memory_write(s->transmit_queue_address[queue], (uint8_t *)&desc, sizeof(desc));
571 if (more && frame_length < sizeof(frame)) {
573 * This is done at the end of the loop
574 * since sometimes the next-link is not
575 * yet set (assuming frame is a 1-segment
576 * frame)!!
578 * This is very strange (and maybe obsolete
579 * by this version) but let's do it the safe
580 * way and not mess it up :-)
582 s->transmit_queue_address[queue] = (hwaddr)desc.ds_link;
583 cpu_physical_memory_read(s->transmit_queue_address[queue], (uint8_t *)&desc, sizeof(desc));
585 } while (more && frame_length < sizeof(frame));
588 struct pending_interrupt intr;
589 intr.status = AR5K_INT_TX;
590 Atheros_WLAN_append_irq(s, intr);
591 Atheros_WLAN_enable_irq(s);
594 * Set address to next position
595 * in single-linked list
597 * The transmit list's last element
598 * points to itself to avoid overruns.
599 * This way, at some point no more
600 * packets will be received, but (I
601 * ASSUME) that it is the drivers
602 * responsibility to reset the address
603 * list!
605 s->transmit_queue_processed[queue] = 1;
607 frame.frame_length = frame_length + 4;
608 Atheros_WLAN_handle_frame(s, &frame);
612 void Atheros_WLAN_handle_frame(Atheros_WLANState *s, struct mac80211_frame *frame)
614 struct mac80211_frame *reply = NULL;
615 unsigned long ethernet_frame_size;
616 unsigned char ethernet_frame[1518];
618 if ((frame->frame_control.type == IEEE80211_TYPE_MGT) &&
619 (frame->frame_control.sub_type == IEEE80211_TYPE_MGT_SUBTYPE_PROBE_REQ)) {
620 reply = Atheros_WLAN_create_probe_response();
621 } else if ((frame->frame_control.type == IEEE80211_TYPE_MGT) &&
622 (frame->frame_control.sub_type == IEEE80211_TYPE_MGT_SUBTYPE_AUTHENTICATION)) {
623 DEBUG_PRINT_AP(("Received authentication!\n"));
624 reply = Atheros_WLAN_create_authentication();
626 if (s->ap_state == Atheros_WLAN__STATE_NOT_AUTHENTICATED) {
627 // if everything is going according to
628 // the state machine, let's jump into the
629 // next state
630 s->ap_state = Atheros_WLAN__STATE_AUTHENTICATED;
632 } else if ((frame->frame_control.type == IEEE80211_TYPE_MGT) &&
633 (frame->frame_control.sub_type == IEEE80211_TYPE_MGT_SUBTYPE_DEAUTHENTICATION)) {
634 DEBUG_PRINT_AP(("Received deauthentication!\n"));
635 reply = Atheros_WLAN_create_deauthentication();
637 // some systems (e.g. WinXP) won't send a
638 // disassociation. just believe that the
639 // deauthentication is ok... nothing bad
640 // can happen anyways ;-)
641 s->ap_state = Atheros_WLAN__STATE_NOT_AUTHENTICATED;
642 } else if ((frame->frame_control.type == IEEE80211_TYPE_MGT) &&
643 (frame->frame_control.sub_type == IEEE80211_TYPE_MGT_SUBTYPE_ASSOCIATION_REQ)) {
644 DEBUG_PRINT_AP(("Received association request!\n"));
645 reply = Atheros_WLAN_create_association_response();
647 if (s->ap_state == Atheros_WLAN__STATE_AUTHENTICATED) {
648 // if everything is going according to
649 // the state machine, let's jump into the
650 // next state
651 s->ap_state = Atheros_WLAN__STATE_ASSOCIATED;
653 } else if ((frame->frame_control.type == IEEE80211_TYPE_MGT) &&
654 (frame->frame_control.sub_type == IEEE80211_TYPE_MGT_SUBTYPE_DISASSOCIATION)) {
655 DEBUG_PRINT_AP(("Received disassociation!\n"));
656 reply = Atheros_WLAN_create_disassociation();
658 if (s->ap_state == Atheros_WLAN__STATE_ASSOCIATED) {
659 // if everything is going according to
660 // the state machine, let's jump into the
661 // next state
662 s->ap_state = Atheros_WLAN__STATE_AUTHENTICATED;
664 } else if ((frame->frame_control.type == IEEE80211_TYPE_DATA) &&
665 (s->ap_state == Atheros_WLAN__STATE_ASSOCIATED)) {
667 * The access point uses the 802.11 frame
668 * and sends a 802.3 frame into the network...
669 * This packet is then understandable by
670 * qemu-slirp
672 * If we ever want the access point to offer
673 * some services, it can be added here!!
675 // ethernet header type
676 ethernet_frame[12] = frame->data_and_fcs[6];
677 ethernet_frame[13] = frame->data_and_fcs[7];
679 // the new originator of the packet is
680 // the access point
681 memcpy(&ethernet_frame[6], s->ap_macaddr, 6);
683 if (ethernet_frame[12] == 0x08 && ethernet_frame[13] == 0x06) {
684 // for arp request, we use a broadcast
685 memset(&ethernet_frame[0], 0xff, 6);
686 } else {
687 // otherwise we forward the packet to
688 // where it really belongs
689 memcpy(&ethernet_frame[0], frame->destination_address, 6);
692 // add packet content
693 ethernet_frame_size = frame->frame_length - 24 - 4 - 8;
695 // for some reason, the packet is 22 bytes too small (??)
696 ethernet_frame_size += 22;
697 if (ethernet_frame_size > sizeof(ethernet_frame)) {
698 ethernet_frame_size = sizeof(ethernet_frame);
700 memcpy(&ethernet_frame[14], &frame->data_and_fcs[8], ethernet_frame_size);
702 // add size of ethernet header
703 ethernet_frame_size += 14;
706 * Send 802.3 frame
708 qemu_send_packet(qemu_get_queue(s->nic), ethernet_frame, ethernet_frame_size);
711 if (reply) {
712 memcpy(reply->destination_address, frame->source_address, 6);
713 Atheros_WLAN_init_frame(s, reply);
714 Atheros_WLAN_insert_frame(s, reply);
718 #endif /* CONFIG_WIN32 */