qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] Re: Re: Re: Atheros Wireless Device Emulation


From: Clemens Kolbitsch
Subject: [Qemu-devel] Re: Re: Re: Atheros Wireless Device Emulation
Date: Tue, 18 Mar 2008 08:54:29 +0100
User-agent: KMail/1.9.6 (enterprise 0.20070907.709405)

Patch #2:

Setup code for the device




diff -Naur qemu/hw/atheros_wlan.c qemu-altered/hw/atheros_wlan.c
--- qemu/hw/atheros_wlan.c      1970-01-01 01:00:00.000000000 +0100
+++ qemu-altered/hw/atheros_wlan.c      2008-03-01 12:33:11.000000000 +0100
@@ -0,0 +1,348 @@
+/**
+ * QEMU WLAN device emulation
+ * 
+ * Copyright (c) 2008 Clemens Kolbitsch
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a 
copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the 
rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * Modifications:
+ *  2008-February-24  Clemens Kolbitsch :
+ *                                  New implementation based on ne2000.c
+ *
+ */
+
+#include "hw.h"
+#include "pci.h"
+#include "pc.h"
+#include "net.h"
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/mman.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <signal.h>
+
+#include <time.h>
+#include <sys/time.h>
+
+/*
+ * PCI and EEPROM definitions
+ */
+#include "hw/atheros_wlan.h"
+#include "hw/atheros_wlan_io.h"
+#include "hw/atheros_wlan_ap.h"
+#include "hw/atheros_wlan_eeprom.h"
+
+/*
+ * MadWifi OPENHAL atheros constants
+ */
+#include "hw/ath5k_hw.h"
+#include "hw/ath5kreg.h"
+#include "hw/ath5k.h"
+
+
+static void Atheros_WLAN_reset(NICInfo *nd, Atheros_WLANState *s)
+{
+       DEBUG_PRINT(("reset\n"));
+
+       /*
+        * Restore mac address
+        */
+       memcpy(s->macaddr, nd->macaddr, 6);
+
+       /*
+        * data from my local AR5212 device
+        */
+       SET_MEM_L(s->mem, 12, 0);
+       SET_MEM_L(s->mem, AR5K_SREV, 86);
+       SET_MEM_L(s->mem, AR5K_PCICFG, 0x00010014);
+       SET_MEM_L(s->mem, AR5K_PHY_CHIP_ID, 65);
+       SET_MEM_L(s->mem, AR5K_SLEEP_CTL, 0x00010000);
+       SET_MEM_L(s->mem, 0x9820, 0x02020200);
+
+       Atheros_WLAN_update_irq(s);
+}
+
+void Atheros_WLAN_setup_type(NICInfo *nd, PCIAtheros_WLANState *d)
+{
+       // create buffer large enough to
+       // do all checks
+       char *device_name;
+       char nd_model[128];
+       uint8_t *pci_conf;
+       Atheros_WLANState *s;
+
+       device_name = nd_model;
+       pci_conf = d->dev.config;
+       s = &d->Atheros_WLAN;
+
+       snprintf(nd_model, sizeof(nd_model), "%s", nd->model);
+       
+
+       // skip "atheros_wlan"
+       // if it had not been part of nd->model, this
+       // module would not be loaded anyways!!
+       device_name += 12;
+       DEBUG_PRINT_AP(("Loading virtual wlan-pci device...\n"));
+       if (strncmp(device_name, "_winxp", 6) == 0)
+       {
+               s->device_driver_type = WINXP_DRIVER;
+               DEBUG_PRINT_AP((" * Make sure you are using a MS Windows 
driver!!\n"));
+
+               // skip "_winxp"
+               device_name += 6;
+       }
+       else if (strncmp(device_name, "_linux", 6) == 0)
+       {
+               s->device_driver_type = LINUX_DRIVER;
+               DEBUG_PRINT_AP((" * Make sure you are using a MadWifi 
driver!!\n"));
+
+               // skip "_linux"
+               device_name += 6;
+       }
+       else
+       {
+               s->device_driver_type = LINUX_DRIVER;
+               DEBUG_PRINT_AP((" * Unknown driver type '%s'... defaulting to 
Linux... Make 
sure you are using a MadWifi driver!!\n", nd->model));
+       }
+
+       if (strncmp(device_name, "_HPW400", 7) == 0)
+       {
+               s->eeprom_data = (u_int32_t*)Atheros_WLAN_eeprom_data_HPW400;
+               s->eeprom_size = sizeof(Atheros_WLAN_eeprom_data_HPW400);
+
+               memcpy(pci_conf, Atheros_WLAN_pci_config_HPW400, 256);
+
+               DEBUG_PRINT_AP((" * Using EEPROM and device configuration of HP 
W400!!
\n"));
+
+               // skip "_HPW400"
+               device_name += 7;
+       }
+       else if (strncmp(device_name, "_MacBook", 8) == 0)
+       {
+               s->eeprom_data = (u_int32_t*)Atheros_WLAN_eeprom_data_MacBook;
+               s->eeprom_size = sizeof(Atheros_WLAN_eeprom_data_MacBook);
+
+               memcpy(pci_conf, Atheros_WLAN_pci_config_MacBook, 256);
+               
+               DEBUG_PRINT_AP((" * Using EEPROM and device configuration of 
Mac Book!!
\n"));
+
+               // skip "_MacBook"
+               device_name += 8;
+       }
+       else if (strncmp(device_name, "_AR5001XPlus", 12) == 0)
+       {
+               s->eeprom_data = (u_int32_t*)Atheros_WLAN_eeprom_data_HPW400;
+               s->eeprom_size = sizeof(Atheros_WLAN_eeprom_data_HPW400);
+
+               memcpy(pci_conf, Atheros_WLAN_pci_config_AR5001XPlus, 256);
+               
+               DEBUG_PRINT_AP((" * Using EEPROM and device configuration of 
AR5001X+ (e.g. 
Toshiba A100)!!\n"));
+
+               // skip "_AR5001XPlus"
+               device_name += 12;
+       }
+       else if (strncmp(device_name, "_John", 5) == 0)
+       {
+               s->eeprom_data = (u_int32_t*)Atheros_WLAN_eeprom_data_HPW400;
+               s->eeprom_size = sizeof(Atheros_WLAN_eeprom_data_HPW400);
+
+               memcpy(pci_conf, Atheros_WLAN_pci_config_JOHN, 256);
+               
+               DEBUG_PRINT_AP((" * Using EEPROM and device configuration of 
John!!\n"));
+
+               // skip "_John"
+               device_name += 5;
+       }
+       else if (strncmp(device_name, "_TPLinkWN651G", 13) == 0)
+       {
+               s->eeprom_data = (u_int32_t*)Atheros_WLAN_eeprom_data_HPW400;
+               s->eeprom_size = sizeof(Atheros_WLAN_eeprom_data_HPW400);
+
+               memcpy(pci_conf, Atheros_WLAN_pci_config_TP_Link_WN651G, 64);
+               
+               DEBUG_PRINT_AP((" * Using EEPROM and device configuration of 
TP-Link 
WN651G!!\n"));
+
+               // skip "_TPLinkWN651G"
+               device_name += 13;
+       }
+       else
+       {
+               s->eeprom_data = (u_int32_t*)Atheros_WLAN_eeprom_data_HPW400;
+               s->eeprom_size = sizeof(Atheros_WLAN_eeprom_data_HPW400);
+
+               memcpy(pci_conf, Atheros_WLAN_pci_config_HPW400, 256);
+
+               DEBUG_PRINT_AP((" * Unknown EEPROM type '%s'... defaulting to 
HP W400!!\n", 
nd->model));
+       }
+}
+
+
+static void Atheros_WLAN_save(QEMUFile* f, void* opaque)
+{
+       int i;
+       uint32_t direct_value;
+       Atheros_WLANState *s = (Atheros_WLANState *)opaque;
+
+       if (s->pci_dev)
+       {
+               pci_device_save(s->pci_dev, f);
+       }
+
+       qemu_put_be32s(f, &s->device_driver_type);
+
+       qemu_put_buffer(f, s->ipaddr, 4);
+       qemu_put_buffer(f, s->macaddr, 6);
+
+       qemu_put_buffer(f, s->ap_ipaddr, 4);
+       qemu_put_buffer(f, s->ap_macaddr, 6);
+
+
+       qemu_put_be32s(f, &s->interrupt_p_mask);
+       for (i=0; i<5; qemu_put_be32s(f, &s->interrupt_s_mask[i++]));
+       qemu_put_8s(f, &s->interrupt_enabled);
+
+       qemu_put_be32s(f, &s->current_frequency);
+
+       direct_value = (uint32_t)s->receive_queue_address;
+       qemu_put_be32s(f, &direct_value);
+       qemu_put_be32s(f, &s->receive_queue_count);
+
+       qemu_put_be32s(f, &s->transmit_queue_size);
+       for (i=0; i<16; i++)
+       {
+               qemu_put_8s(f, &s->transmit_queue_enabled[i]);
+               direct_value = (uint32_t)s->transmit_queue_address[i];
+               qemu_put_be32s(f, &direct_value);
+               qemu_put_be32s(f, &s->transmit_queue_processed[i]);
+       }
+
+       qemu_put_be32s(f, &s->ap_state);
+       qemu_put_be32s(f, &s->inject_sequence_number);
+
+       qemu_put_buffer(f, (uint8_t *)s->mem, Atheros_WLAN_MEM_SIZE);
+}
+
+static int Atheros_WLAN_load(QEMUFile* f, void* opaque, int version_id)
+{
+       int i, ret;
+       uint32_t direct_value;
+       Atheros_WLANState *s = (Atheros_WLANState *)opaque;
+
+       // everyone has version 3... and the pci
+       // stuff should be there as well, I think
+       //
+       // let's just claim this has been around
+       // for quite some time ;-)
+       if (version_id != 3)
+               return -EINVAL;
+
+       if (s->pci_dev && version_id >= 3) {
+               ret = pci_device_load(s->pci_dev, f);
+               if (ret < 0)
+                       return ret;
+       }
+
+       qemu_get_be32s(f, &s->device_driver_type);
+
+       qemu_get_buffer(f, s->ipaddr, 4);
+       qemu_get_buffer(f, s->macaddr, 6);
+
+       qemu_get_buffer(f, s->ap_ipaddr, 4);
+       qemu_get_buffer(f, s->ap_macaddr, 6);
+
+
+       qemu_get_be32s(f, &s->interrupt_p_mask);
+       for (i=0; i<5; qemu_get_be32s(f, &s->interrupt_s_mask[i++]));
+       qemu_get_8s(f, &s->interrupt_enabled);
+
+       qemu_get_be32s(f, &s->current_frequency);
+       qemu_get_be32s(f, &direct_value);
+       s->receive_queue_address = (uint32_t*)direct_value;
+       qemu_get_be32s(f, &s->receive_queue_count);
+
+       qemu_get_be32s(f, &s->transmit_queue_size);
+       for (i=0; i<16; i++)
+       {
+               qemu_get_8s(f, &s->transmit_queue_enabled[i]);
+               qemu_get_be32s(f, &direct_value);
+               s->transmit_queue_address[i] = (uint32_t*)direct_value;
+               qemu_get_be32s(f, &s->transmit_queue_processed[i]);
+       }
+
+       qemu_get_be32s(f, &s->ap_state);
+       qemu_get_be32s(f, &s->inject_sequence_number);
+
+       qemu_get_buffer(f, (uint8_t *)s->mem, Atheros_WLAN_MEM_SIZE);
+
+
+       s->inject_timer_running = 0;
+       s->inject_queue_size = 0;
+       s->inject_queue = NULL;
+
+       return 0;
+}
+
+
+void pci_Atheros_WLAN_init(PCIBus *bus, NICInfo *nd, int devfn)
+{
+       PCIAtheros_WLANState *d;
+       Atheros_WLANState *s;
+
+       /*
+        * currently, we have to use this mac-address.
+        * it is hardcoded in the eeprom/io-stuff
+        */
+       nd->macaddr[0] = 0x00;
+       nd->macaddr[1] = 0x11;
+       nd->macaddr[2] = 0x0a;
+       nd->macaddr[3] = 0x80;
+       nd->macaddr[4] = 0x2e;
+       nd->macaddr[5] = 0x9e;
+
+       d = (PCIAtheros_WLANState *)pci_register_device(bus, "Atheros_WLAN", 
sizeof(PCIAtheros_WLANState), devfn,  NULL, NULL);
+       s = &d->Atheros_WLAN;
+
+       // s->irq = 9; /* PCI interrupt */
+       s->irq = d->dev.irq[0];
+       s->pci_dev = (PCIDevice *)d;
+       s->pending_interrupts = NULL;
+       memcpy(s->macaddr, nd->macaddr, 6);
+
+       Atheros_WLAN_setup_type(nd, d);
+       Atheros_WLAN_setup_io(d);
+       Atheros_WLAN_setup_ap(nd, d);
+
+       /* TODO: we don't support multiple instance yet!! */
+       register_savevm("Atheros_WLAN", 0, 3, Atheros_WLAN_save, 
Atheros_WLAN_load, 
s);
+
+       Atheros_WLAN_reset(nd, s);
+}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]