[haiku-commits] r34507 - in haiku/trunk/src/add-ons/kernel/drivers/network/wlan: . ralinkwifi ralinkwifi/dev ralinkwifi/dev/ral

Author: colin
Date: 2009-12-05 15:24:30 +0100 (Sat, 05 Dec 2009)
New Revision: 34507
Changeset: http://dev.haiku-os.org/changeset/34507/haiku

Added:
   haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/
   haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/Jamfile
   haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/
   haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/
   
haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/if_ral_pci.c
   
haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560.c
   
haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560reg.h
   
haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560var.h
   
haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661.c
   
haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661reg.h
   
haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2661var.h
Modified:
   haiku/trunk/src/add-ons/kernel/drivers/network/wlan/Jamfile
Log:
Adding ralinkwifi driver. This driver compiles, only, as there is a glue.c
is missing atm. If someone wanne add it go ahead.


Modified: haiku/trunk/src/add-ons/kernel/drivers/network/wlan/Jamfile
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/network/wlan/Jamfile 2009-12-05 
14:06:45 UTC (rev 34506)
+++ haiku/trunk/src/add-ons/kernel/drivers/network/wlan/Jamfile 2009-12-05 
14:24:30 UTC (rev 34507)
@@ -8,3 +8,4 @@
 SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi3945 ;
 SubInclude HAIKU_TOP src add-ons kernel drivers network wlan iprowifi4965 ;
 SubInclude HAIKU_TOP src add-ons kernel drivers network wlan marvell88w8363 ;
+SubInclude HAIKU_TOP src add-ons kernel drivers network wlan ralinkwifi ;


Property changes on: 
haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi
___________________________________________________________________
Added: svn:mergeinfo
   + 

Added: haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/Jamfile
===================================================================
--- haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/Jamfile      
                        (rev 0)
+++ haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/Jamfile      
2009-12-05 14:24:30 UTC (rev 34507)
@@ -0,0 +1,24 @@
+SubDir HAIKU_TOP src add-ons kernel drivers network wlan ralinkwifi ;
+
+UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ] : 
true ;
+UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_wlan ] : true ;
+UsePrivateHeaders net system ;
+UsePrivateKernelHeaders ;
+
+SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 ] 
+       -Wno-format 
+       -Wno-unused 
+       -Wno-uninitialized ;
+
+UseHeaders [ FDirName $(SUBDIR) ] : true ;
+
+SEARCH_SOURCE += [ FDirName $(SUBDIR) dev ral ] ;
+
+KernelAddon ralinkwifi :
+       if_ral_pci.c
+       rt2560.c
+       rt2661.c
+       :
+       libfreebsd_wlan.a
+       libfreebsd_network.a
+       ;

Added: 
haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/if_ral_pci.c
===================================================================
--- 
haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/if_ral_pci.c
                         (rev 0)
+++ 
haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/if_ral_pci.c
 2009-12-05 14:24:30 UTC (rev 34507)
@@ -0,0 +1,272 @@
+/*     $FreeBSD$       */
+
+/*-
+ * Copyright (c) 2005, 2006
+ *     Damien Bergamini <damien.bergamini@xxxxxxx>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * PCI/Cardbus front-end for the Ralink RT2560/RT2561/RT2561S/RT2661 driver.
+ */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
+#include <net80211/ieee80211_amrr.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/ral/rt2560var.h>
+#include <dev/ral/rt2661var.h>
+
+MODULE_DEPEND(ral, pci, 1, 1, 1);
+MODULE_DEPEND(ral, firmware, 1, 1, 1);
+MODULE_DEPEND(ral, wlan, 1, 1, 1);
+MODULE_DEPEND(ral, wlan_amrr, 1, 1, 1);
+
+struct ral_pci_ident {
+       uint16_t        vendor;
+       uint16_t        device;
+       const char      *name;
+};
+
+static const struct ral_pci_ident ral_pci_ids[] = {
+       { 0x1814, 0x0201, "Ralink Technology RT2560" },
+       { 0x1814, 0x0301, "Ralink Technology RT2561S" },
+       { 0x1814, 0x0302, "Ralink Technology RT2561" },
+       { 0x1814, 0x0401, "Ralink Technology RT2661" },
+
+       { 0, 0, NULL }
+};
+
+static struct ral_opns {
+       int     (*attach)(device_t, int);
+       int     (*detach)(void *);
+       void    (*shutdown)(void *);
+       void    (*suspend)(void *);
+       void    (*resume)(void *);
+       void    (*intr)(void *);
+
+}  ral_rt2560_opns = {
+       rt2560_attach,
+       rt2560_detach,
+       rt2560_stop,
+       rt2560_stop,
+       rt2560_resume,
+       rt2560_intr
+
+}, ral_rt2661_opns = {
+       rt2661_attach,
+       rt2661_detach,
+       rt2661_shutdown,
+       rt2661_suspend,
+       rt2661_resume,
+       rt2661_intr
+};
+
+struct ral_pci_softc {
+       union {
+               struct rt2560_softc sc_rt2560;
+               struct rt2661_softc sc_rt2661;
+       } u;
+
+       struct ral_opns         *sc_opns;
+       int                     irq_rid;
+       int                     mem_rid;
+       struct resource         *irq;
+       struct resource         *mem;
+       void                    *sc_ih;
+};
+
+static int ral_pci_probe(device_t);
+static int ral_pci_attach(device_t);
+static int ral_pci_detach(device_t);
+static int ral_pci_shutdown(device_t);
+static int ral_pci_suspend(device_t);
+static int ral_pci_resume(device_t);
+
+static device_method_t ral_pci_methods[] = {
+       /* Device interface */
+       DEVMETHOD(device_probe,         ral_pci_probe),
+       DEVMETHOD(device_attach,        ral_pci_attach),
+       DEVMETHOD(device_detach,        ral_pci_detach),
+       DEVMETHOD(device_shutdown,      ral_pci_shutdown),
+       DEVMETHOD(device_suspend,       ral_pci_suspend),
+       DEVMETHOD(device_resume,        ral_pci_resume),
+
+       { 0, 0 }
+};
+
+static driver_t ral_pci_driver = {
+       "ral",
+       ral_pci_methods,
+       sizeof (struct ral_pci_softc)
+};
+
+static devclass_t ral_devclass;
+
+DRIVER_MODULE(ral, pci, ral_pci_driver, ral_devclass, 0, 0);
+
+static int
+ral_pci_probe(device_t dev)
+{
+       const struct ral_pci_ident *ident;
+
+       for (ident = ral_pci_ids; ident->name != NULL; ident++) {
+               if (pci_get_vendor(dev) == ident->vendor &&
+                   pci_get_device(dev) == ident->device) {
+                       device_set_desc(dev, ident->name);
+                       return 0;
+               }
+       }
+       return ENXIO;
+}
+
+/* Base Address Register */
+#define RAL_PCI_BAR0   0x10
+
+static int
+ral_pci_attach(device_t dev)
+{
+       struct ral_pci_softc *psc = device_get_softc(dev);
+       struct rt2560_softc *sc = &psc->u.sc_rt2560;
+       int error;
+
+       if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
+               device_printf(dev, "chip is in D%d power mode "
+                   "-- setting to D0\n", pci_get_powerstate(dev));
+               pci_set_powerstate(dev, PCI_POWERSTATE_D0);
+       }
+
+       /* enable bus-mastering */
+       pci_enable_busmaster(dev);
+
+       psc->sc_opns = (pci_get_device(dev) == 0x0201) ? &ral_rt2560_opns :
+           &ral_rt2661_opns;
+
+       psc->mem_rid = RAL_PCI_BAR0;
+       psc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &psc->mem_rid,
+           RF_ACTIVE);
+       if (psc->mem == NULL) {
+               device_printf(dev, "could not allocate memory resource\n");
+               return ENXIO;
+       }
+
+       sc->sc_st = rman_get_bustag(psc->mem);
+       sc->sc_sh = rman_get_bushandle(psc->mem);
+       sc->sc_invalid = 1;
+       
+       psc->irq_rid = 0;
+       psc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &psc->irq_rid,
+           RF_ACTIVE | RF_SHAREABLE);
+       if (psc->irq == NULL) {
+               device_printf(dev, "could not allocate interrupt resource\n");
+               return ENXIO;
+       }
+
+       error = (*psc->sc_opns->attach)(dev, pci_get_device(dev));
+       if (error != 0)
+               return error;
+
+       /*
+        * Hook our interrupt after all initialization is complete.
+        */
+       error = bus_setup_intr(dev, psc->irq, INTR_TYPE_NET | INTR_MPSAFE,
+           NULL, psc->sc_opns->intr, psc, &psc->sc_ih);
+       if (error != 0) {
+               device_printf(dev, "could not set up interrupt\n");
+               return error;
+       }
+       sc->sc_invalid = 0;
+       
+       return 0;
+}
+
+static int
+ral_pci_detach(device_t dev)
+{
+       struct ral_pci_softc *psc = device_get_softc(dev);
+       struct rt2560_softc *sc = &psc->u.sc_rt2560;
+       
+       /* check if device was removed */
+       sc->sc_invalid = !bus_child_present(dev);
+       
+       (*psc->sc_opns->detach)(psc);
+
+       bus_generic_detach(dev);
+       bus_teardown_intr(dev, psc->irq, psc->sc_ih);
+       bus_release_resource(dev, SYS_RES_IRQ, psc->irq_rid, psc->irq);
+
+       bus_release_resource(dev, SYS_RES_MEMORY, psc->mem_rid, psc->mem);
+
+       return 0;
+}
+
+static int
+ral_pci_shutdown(device_t dev)
+{
+       struct ral_pci_softc *psc = device_get_softc(dev);
+
+       (*psc->sc_opns->shutdown)(psc);
+
+       return 0;
+}
+
+static int
+ral_pci_suspend(device_t dev)
+{
+       struct ral_pci_softc *psc = device_get_softc(dev);
+
+       (*psc->sc_opns->suspend)(psc);
+
+       return 0;
+}
+
+static int
+ral_pci_resume(device_t dev)
+{
+       struct ral_pci_softc *psc = device_get_softc(dev);
+
+       (*psc->sc_opns->resume)(psc);
+
+       return 0;
+}

Added: 
haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560.c
===================================================================
--- 
haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560.c 
                            (rev 0)
+++ 
haiku/trunk/src/add-ons/kernel/drivers/network/wlan/ralinkwifi/dev/ral/rt2560.c 
    2009-12-05 14:24:30 UTC (rev 34507)
@@ -0,0 +1,2841 @@
+/*     $FreeBSD$       */
+
+/*-
+ * Copyright (c) 2005, 2006
+ *     Damien Bergamini <damien.bergamini@xxxxxxx>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*-
+ * Ralink Technology RT2560 chipset driver
+ * http://www.ralinktech.com/
+ */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
+#include <net80211/ieee80211_regdomain.h>
+#include <net80211/ieee80211_amrr.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+
+#include <dev/ral/rt2560reg.h>
+#include <dev/ral/rt2560var.h>
+
+#define RT2560_RSSI(sc, rssi)                                  \
+       ((rssi) > (RT2560_NOISE_FLOOR + (sc)->rssi_corr) ?      \
+        ((rssi) - RT2560_NOISE_FLOOR - (sc)->rssi_corr) : 0)
+
+#define RAL_DEBUG
+#ifdef RAL_DEBUG
+#define DPRINTF(sc, fmt, ...) do {                             \
+       if (sc->sc_debug > 0)                                   \
+               printf(fmt, __VA_ARGS__);                       \
+} while (0)
+#define DPRINTFN(sc, n, fmt, ...) do {                         \
+       if (sc->sc_debug >= (n))                                \
+               printf(fmt, __VA_ARGS__);                       \
+} while (0)
+#else
+#define DPRINTF(sc, fmt, ...)
+#define DPRINTFN(sc, n, fmt, ...)
+#endif
+
+static struct ieee80211vap *rt2560_vap_create(struct ieee80211com *,
+                           const char name[IFNAMSIZ], int unit, int opmode,
+                           int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
+                           const uint8_t mac[IEEE80211_ADDR_LEN]);
+static void            rt2560_vap_delete(struct ieee80211vap *);
+static void            rt2560_dma_map_addr(void *, bus_dma_segment_t *, int,
+                           int);
+static int             rt2560_alloc_tx_ring(struct rt2560_softc *,
+                           struct rt2560_tx_ring *, int);
+static void            rt2560_reset_tx_ring(struct rt2560_softc *,
+                           struct rt2560_tx_ring *);
+static void            rt2560_free_tx_ring(struct rt2560_softc *,
+                           struct rt2560_tx_ring *);
+static int             rt2560_alloc_rx_ring(struct rt2560_softc *,
+                           struct rt2560_rx_ring *, int);
+static void            rt2560_reset_rx_ring(struct rt2560_softc *,
+                           struct rt2560_rx_ring *);
+static void            rt2560_free_rx_ring(struct rt2560_softc *,
+                           struct rt2560_rx_ring *);
+static struct ieee80211_node *rt2560_node_alloc(struct ieee80211vap *,
+                           const uint8_t [IEEE80211_ADDR_LEN]);
+static void            rt2560_newassoc(struct ieee80211_node *, int);
+static int             rt2560_newstate(struct ieee80211vap *,
+                           enum ieee80211_state, int);
+static uint16_t                rt2560_eeprom_read(struct rt2560_softc *, 
uint8_t);
+static void            rt2560_encryption_intr(struct rt2560_softc *);
+static void            rt2560_tx_intr(struct rt2560_softc *);
+static void            rt2560_prio_intr(struct rt2560_softc *);
+static void            rt2560_decryption_intr(struct rt2560_softc *);
+static void            rt2560_rx_intr(struct rt2560_softc *);
+static void            rt2560_beacon_update(struct ieee80211vap *, int item);
+static void            rt2560_beacon_expire(struct rt2560_softc *);
+static void            rt2560_wakeup_expire(struct rt2560_softc *);
+static void            rt2560_scan_start(struct ieee80211com *);
+static void            rt2560_scan_end(struct ieee80211com *);
+static void            rt2560_set_channel(struct ieee80211com *);
+static void            rt2560_setup_tx_desc(struct rt2560_softc *,
+                           struct rt2560_tx_desc *, uint32_t, int, int, int,
+                           bus_addr_t);
+static int             rt2560_tx_bcn(struct rt2560_softc *, struct mbuf *,
+                           struct ieee80211_node *);
+static int             rt2560_tx_mgt(struct rt2560_softc *, struct mbuf *,
+                           struct ieee80211_node *);
+static int             rt2560_tx_data(struct rt2560_softc *, struct mbuf *,
+                           struct ieee80211_node *);
+static void            rt2560_start_locked(struct ifnet *);
+static void            rt2560_start(struct ifnet *);
+static void            rt2560_watchdog(void *);
+static int             rt2560_ioctl(struct ifnet *, u_long, caddr_t);
+static void            rt2560_bbp_write(struct rt2560_softc *, uint8_t,
+                           uint8_t);
+static uint8_t         rt2560_bbp_read(struct rt2560_softc *, uint8_t);
+static void            rt2560_rf_write(struct rt2560_softc *, uint8_t,
+                           uint32_t);
+static void            rt2560_set_chan(struct rt2560_softc *,
+                           struct ieee80211_channel *);
+#if 0
+static void            rt2560_disable_rf_tune(struct rt2560_softc *);
+#endif
+static void            rt2560_enable_tsf_sync(struct rt2560_softc *);
+static void            rt2560_enable_tsf(struct rt2560_softc *);
+static void            rt2560_update_plcp(struct rt2560_softc *);
+static void            rt2560_update_slot(struct ifnet *);
+static void            rt2560_set_basicrates(struct rt2560_softc *);
+static void            rt2560_update_led(struct rt2560_softc *, int, int);
+static void            rt2560_set_bssid(struct rt2560_softc *, const uint8_t 
*);
+static void            rt2560_set_macaddr(struct rt2560_softc *, uint8_t *);
+static void            rt2560_get_macaddr(struct rt2560_softc *, uint8_t *);
+static void            rt2560_update_promisc(struct ifnet *);
+static const char      *rt2560_get_rf(int);
+static void            rt2560_read_config(struct rt2560_softc *);
+static int             rt2560_bbp_init(struct rt2560_softc *);
+static void            rt2560_set_txantenna(struct rt2560_softc *, int);
+static void            rt2560_set_rxantenna(struct rt2560_softc *, int);
+static void            rt2560_init_locked(struct rt2560_softc *);
+static void            rt2560_init(void *);
+static void            rt2560_stop_locked(struct rt2560_softc *);
+static int             rt2560_raw_xmit(struct ieee80211_node *, struct mbuf *,
+                               const struct ieee80211_bpf_params *);
+
+static const struct {
+       uint32_t        reg;
+       uint32_t        val;
+} rt2560_def_mac[] = {
+       RT2560_DEF_MAC
+};
+
+static const struct {
+       uint8_t reg;
+       uint8_t val;
+} rt2560_def_bbp[] = {
+       RT2560_DEF_BBP
+};
+
+static const uint32_t rt2560_rf2522_r2[]    = RT2560_RF2522_R2;
+static const uint32_t rt2560_rf2523_r2[]    = RT2560_RF2523_R2;
+static const uint32_t rt2560_rf2524_r2[]    = RT2560_RF2524_R2;
+static const uint32_t rt2560_rf2525_r2[]    = RT2560_RF2525_R2;
+static const uint32_t rt2560_rf2525_hi_r2[] = RT2560_RF2525_HI_R2;
+static const uint32_t rt2560_rf2525e_r2[]   = RT2560_RF2525E_R2;
+static const uint32_t rt2560_rf2526_r2[]    = RT2560_RF2526_R2;
+static const uint32_t rt2560_rf2526_hi_r2[] = RT2560_RF2526_HI_R2;
+
+static const struct {
+       uint8_t         chan;
+       uint32_t        r1, r2, r4;
+} rt2560_rf5222[] = {
+       RT2560_RF5222
+};
+
+int
+rt2560_attach(device_t dev, int id)
+{
+       struct rt2560_softc *sc = device_get_softc(dev);
+       struct ieee80211com *ic;
+       struct ifnet *ifp;
+       int error;
+       uint8_t bands;
+       uint8_t macaddr[IEEE80211_ADDR_LEN];
+
+       sc->sc_dev = dev;
+
+       mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
+           MTX_DEF | MTX_RECURSE);
+
+       callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
+
+       /* retrieve RT2560 rev. no */
+       sc->asic_rev = RAL_READ(sc, RT2560_CSR0);
+
+       /* retrieve RF rev. no and various other things from EEPROM */
+       rt2560_read_config(sc);
+
+       device_printf(dev, "MAC/BBP RT2560 (rev 0x%02x), RF %s\n",
+           sc->asic_rev, rt2560_get_rf(sc->rf_rev));
+
+       /*
+        * Allocate Tx and Rx rings.
+        */
+       error = rt2560_alloc_tx_ring(sc, &sc->txq, RT2560_TX_RING_COUNT);
+       if (error != 0) {
+               device_printf(sc->sc_dev, "could not allocate Tx ring\n");
+               goto fail1;
+       }
+
+       error = rt2560_alloc_tx_ring(sc, &sc->atimq, RT2560_ATIM_RING_COUNT);
+       if (error != 0) {
+               device_printf(sc->sc_dev, "could not allocate ATIM ring\n");
+               goto fail2;
+       }
+
+       error = rt2560_alloc_tx_ring(sc, &sc->prioq, RT2560_PRIO_RING_COUNT);
+       if (error != 0) {
+               device_printf(sc->sc_dev, "could not allocate Prio ring\n");
+               goto fail3;
+       }
+
+       error = rt2560_alloc_tx_ring(sc, &sc->bcnq, RT2560_BEACON_RING_COUNT);
+       if (error != 0) {
+               device_printf(sc->sc_dev, "could not allocate Beacon ring\n");
+               goto fail4;
+       }
+
+       error = rt2560_alloc_rx_ring(sc, &sc->rxq, RT2560_RX_RING_COUNT);
+       if (error != 0) {
+               device_printf(sc->sc_dev, "could not allocate Rx ring\n");
+               goto fail5;
+       }
+
+       ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
+       if (ifp == NULL) {
+               device_printf(sc->sc_dev, "can not if_alloc()\n");
+               goto fail6;
+       }
+       ic = ifp->if_l2com;
+
+       /* retrieve MAC address */
+       rt2560_get_macaddr(sc, macaddr);
+
+       ifp->if_softc = sc;
+       if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+       ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+       ifp->if_init = rt2560_init;
+       ifp->if_ioctl = rt2560_ioctl;
+       ifp->if_start = rt2560_start;
+       IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+       ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+       IFQ_SET_READY(&ifp->if_snd);
+
+       ic->ic_ifp = ifp;
+       ic->ic_opmode = IEEE80211_M_STA;
+       ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
+
+       /* set device capabilities */
+       ic->ic_caps =
+                 IEEE80211_C_STA               /* station mode */
+               | IEEE80211_C_IBSS              /* ibss, nee adhoc, mode */
+               | IEEE80211_C_HOSTAP            /* hostap mode */
+               | IEEE80211_C_MONITOR           /* monitor mode */
+               | IEEE80211_C_AHDEMO            /* adhoc demo mode */
+               | IEEE80211_C_WDS               /* 4-address traffic works */
+               | IEEE80211_C_MBSS              /* mesh point link mode */
+               | IEEE80211_C_SHPREAMBLE        /* short preamble supported */
+               | IEEE80211_C_SHSLOT            /* short slot time supported */
+               | IEEE80211_C_WPA               /* capable of WPA1+WPA2 */
+               | IEEE80211_C_BGSCAN            /* capable of bg scanning */
+#ifdef notyet
+               | IEEE80211_C_TXFRAG            /* handle tx frags */
+#endif
+               ;
+
+       bands = 0;
+       setbit(&bands, IEEE80211_MODE_11B);
+       setbit(&bands, IEEE80211_MODE_11G);
+       if (sc->rf_rev == RT2560_RF_5222)
+               setbit(&bands, IEEE80211_MODE_11A);
+       ieee80211_init_channels(ic, NULL, &bands);
+
+       ieee80211_ifattach(ic, macaddr);
+       ic->ic_newassoc = rt2560_newassoc;
+       ic->ic_raw_xmit = rt2560_raw_xmit;
+       ic->ic_updateslot = rt2560_update_slot;
+       ic->ic_update_promisc = rt2560_update_promisc;
+       ic->ic_node_alloc = rt2560_node_alloc;
+       ic->ic_scan_start = rt2560_scan_start;
+       ic->ic_scan_end = rt2560_scan_end;
+       ic->ic_set_channel = rt2560_set_channel;
+
+       ic->ic_vap_create = rt2560_vap_create;
+       ic->ic_vap_delete = rt2560_vap_delete;
+
+       ieee80211_radiotap_attach(ic,
+           &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
+               RT2560_TX_RADIOTAP_PRESENT,
+           &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
+               RT2560_RX_RADIOTAP_PRESENT);
+
+       /*
+        * Add a few sysctl knobs.
+        */
+#ifdef RAL_DEBUG
+       SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+           "debug", CTLFLAG_RW, &sc->sc_debug, 0, "debug msgs");
+#endif
+       SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+           "txantenna", CTLFLAG_RW, &sc->tx_ant, 0, "tx antenna (0=auto)");
+
+       SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
+           "rxantenna", CTLFLAG_RW, &sc->rx_ant, 0, "rx antenna (0=auto)");
+
+       if (bootverbose)
+               ieee80211_announce(ic);
+
+       return 0;
+
+fail6: rt2560_free_rx_ring(sc, &sc->rxq);
+fail5: rt2560_free_tx_ring(sc, &sc->bcnq);
+fail4: rt2560_free_tx_ring(sc, &sc->prioq);
+fail3: rt2560_free_tx_ring(sc, &sc->atimq);
+fail2: rt2560_free_tx_ring(sc, &sc->txq);
+fail1: mtx_destroy(&sc->sc_mtx);
+
+       return ENXIO;
+}
+
+int
+rt2560_detach(void *xsc)
+{
+       struct rt2560_softc *sc = xsc;
+       struct ifnet *ifp = sc->sc_ifp;
+       struct ieee80211com *ic = ifp->if_l2com;
+       
+       rt2560_stop(sc);
+
+       ieee80211_ifdetach(ic);
+
+       rt2560_free_tx_ring(sc, &sc->txq);
+       rt2560_free_tx_ring(sc, &sc->atimq);
+       rt2560_free_tx_ring(sc, &sc->prioq);
+       rt2560_free_tx_ring(sc, &sc->bcnq);
+       rt2560_free_rx_ring(sc, &sc->rxq);
+
+       if_free(ifp);
+
+       mtx_destroy(&sc->sc_mtx);
+
+       return 0;
+}
+
+static struct ieee80211vap *
+rt2560_vap_create(struct ieee80211com *ic,
+       const char name[IFNAMSIZ], int unit, int opmode, int flags,
+       const uint8_t bssid[IEEE80211_ADDR_LEN],
+       const uint8_t mac[IEEE80211_ADDR_LEN])
+{
+       struct ifnet *ifp = ic->ic_ifp;
+       struct rt2560_vap *rvp;
+       struct ieee80211vap *vap;
+
+       switch (opmode) {
+       case IEEE80211_M_STA:
+       case IEEE80211_M_IBSS:
+       case IEEE80211_M_AHDEMO:
+       case IEEE80211_M_MONITOR:
+       case IEEE80211_M_HOSTAP:
+       case IEEE80211_M_MBSS:
+               /* XXXRP: TBD */
+               if (!TAILQ_EMPTY(&ic->ic_vaps)) {
+                       if_printf(ifp, "only 1 vap supported\n");
+                       return NULL;
+               }
+               if (opmode == IEEE80211_M_STA)
+                       flags |= IEEE80211_CLONE_NOBEACONS;
+               break;
+       case IEEE80211_M_WDS:
+               if (TAILQ_EMPTY(&ic->ic_vaps) ||
+                   ic->ic_opmode != IEEE80211_M_HOSTAP) {
+                       if_printf(ifp, "wds only supported in ap mode\n");
+                       return NULL;
+               }
+               /*
+                * Silently remove any request for a unique
+                * bssid; WDS vap's always share the local
+                * mac address.
+                */
+               flags &= ~IEEE80211_CLONE_BSSID;
+               break;
+       default:
+               if_printf(ifp, "unknown opmode %d\n", opmode);
+               return NULL;
+       }
+       rvp = (struct rt2560_vap *) malloc(sizeof(struct rt2560_vap),
+           M_80211_VAP, M_NOWAIT | M_ZERO);
+       if (rvp == NULL)
+               return NULL;
+       vap = &rvp->ral_vap;
+       ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
+
+       /* override state transition machine */
+       rvp->ral_newstate = vap->iv_newstate;
+       vap->iv_newstate = rt2560_newstate;
+       vap->iv_update_beacon = rt2560_beacon_update;
+
+       ieee80211_amrr_init(&rvp->amrr, vap,
+           IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
+           IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
+           500 /* ms */);
+
+       /* complete setup */
+       ieee80211_vap_attach(vap, ieee80211_media_change, 
ieee80211_media_status);
+       if (TAILQ_FIRST(&ic->ic_vaps) == vap)
+               ic->ic_opmode = opmode;
+       return vap;
+}
+
+static void
+rt2560_vap_delete(struct ieee80211vap *vap)
+{
+       struct rt2560_vap *rvp = RT2560_VAP(vap);
+
+       ieee80211_amrr_cleanup(&rvp->amrr);
+       ieee80211_vap_detach(vap);
+       free(rvp, M_80211_VAP);
+}
+
+void
+rt2560_resume(void *xsc)
+{
+       struct rt2560_softc *sc = xsc;
+       struct ifnet *ifp = sc->sc_ifp;
+
+       if (ifp->if_flags & IFF_UP)
+               rt2560_init(sc);
+}
+
+static void
+rt2560_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+       if (error != 0)
+               return;
+
+       KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg));
+
+       *(bus_addr_t *)arg = segs[0].ds_addr;
+}
+
+static int
+rt2560_alloc_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring,
+    int count)
+{
+       int i, error;
+
+       ring->count = count;
+       ring->queued = 0;
+       ring->cur = ring->next = 0;
+       ring->cur_encrypt = ring->next_encrypt = 0;
+
+       error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0, 
+           BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+           count * RT2560_TX_DESC_SIZE, 1, count * RT2560_TX_DESC_SIZE,
+           0, NULL, NULL, &ring->desc_dmat);
+       if (error != 0) {
+               device_printf(sc->sc_dev, "could not create desc DMA tag\n");
+               goto fail;
+       }
+
+       error = bus_dmamem_alloc(ring->desc_dmat, (void **)&ring->desc,
+           BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ring->desc_map);
+       if (error != 0) {
+               device_printf(sc->sc_dev, "could not allocate DMA memory\n");
+               goto fail;
+       }
+
+       error = bus_dmamap_load(ring->desc_dmat, ring->desc_map, ring->desc,
+           count * RT2560_TX_DESC_SIZE, rt2560_dma_map_addr, &ring->physaddr,
+           0);
+       if (error != 0) {
+               device_printf(sc->sc_dev, "could not load desc DMA map\n");
+               goto fail;
+       }
+
+       ring->data = malloc(count * sizeof (struct rt2560_tx_data), M_DEVBUF,
+           M_NOWAIT | M_ZERO);
+       if (ring->data == NULL) {
+               device_printf(sc->sc_dev, "could not allocate soft data\n");
+               error = ENOMEM;
+               goto fail;
+       }
+
+       error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 
+           BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+           MCLBYTES, RT2560_MAX_SCATTER, MCLBYTES, 0, NULL, NULL,
+           &ring->data_dmat);
+       if (error != 0) {
+               device_printf(sc->sc_dev, "could not create data DMA tag\n");
+               goto fail;
+       }
+
+       for (i = 0; i < count; i++) {
+               error = bus_dmamap_create(ring->data_dmat, 0,
+                   &ring->data[i].map);
+               if (error != 0) {
+                       device_printf(sc->sc_dev, "could not create DMA map\n");
+                       goto fail;
+               }
+       }
+
+       return 0;
+
+fail:  rt2560_free_tx_ring(sc, ring);
+       return error;
+}
+
+static void
+rt2560_reset_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring)
+{
+       struct rt2560_tx_desc *desc;
+       struct rt2560_tx_data *data;
+       int i;
+
+       for (i = 0; i < ring->count; i++) {
+               desc = &ring->desc[i];
+               data = &ring->data[i];
+
+               if (data->m != NULL) {
+                       bus_dmamap_sync(ring->data_dmat, data->map,
+                           BUS_DMASYNC_POSTWRITE);
+                       bus_dmamap_unload(ring->data_dmat, data->map);
+                       m_freem(data->m);
+                       data->m = NULL;
+               }
+
+               if (data->ni != NULL) {
+                       ieee80211_free_node(data->ni);
+                       data->ni = NULL;
+               }
+
+               desc->flags = 0;
+       }
+
+       bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_PREWRITE);
+
+       ring->queued = 0;
+       ring->cur = ring->next = 0;
+       ring->cur_encrypt = ring->next_encrypt = 0;
+}
+
+static void
+rt2560_free_tx_ring(struct rt2560_softc *sc, struct rt2560_tx_ring *ring)
+{
+       struct rt2560_tx_data *data;
+       int i;
+
+       if (ring->desc != NULL) {
+               bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
+                   BUS_DMASYNC_POSTWRITE);
+               bus_dmamap_unload(ring->desc_dmat, ring->desc_map);
+               bus_dmamem_free(ring->desc_dmat, ring->desc, ring->desc_map);
+       }
+
+       if (ring->desc_dmat != NULL)
+               bus_dma_tag_destroy(ring->desc_dmat);
+
+       if (ring->data != NULL) {
+               for (i = 0; i < ring->count; i++) {
+                       data = &ring->data[i];
+
+                       if (data->m != NULL) {
+                               bus_dmamap_sync(ring->data_dmat, data->map,
+                                   BUS_DMASYNC_POSTWRITE);
+                               bus_dmamap_unload(ring->data_dmat, data->map);
+                               m_freem(data->m);
+                       }
+
+                       if (data->ni != NULL)
+                               ieee80211_free_node(data->ni);
+
+                       if (data->map != NULL)
+                               bus_dmamap_destroy(ring->data_dmat, data->map);
+               }
+
+               free(ring->data, M_DEVBUF);
+       }
+
+       if (ring->data_dmat != NULL)
+               bus_dma_tag_destroy(ring->data_dmat);
+}
+
+static int
+rt2560_alloc_rx_ring(struct rt2560_softc *sc, struct rt2560_rx_ring *ring,
+    int count)
+{
+       struct rt2560_rx_desc *desc;
+       struct rt2560_rx_data *data;
+       bus_addr_t physaddr;
+       int i, error;
+
+       ring->count = count;
+       ring->cur = ring->next = 0;
+       ring->cur_decrypt = 0;
+
+       error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 4, 0, 
+           BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+           count * RT2560_RX_DESC_SIZE, 1, count * RT2560_RX_DESC_SIZE,
+           0, NULL, NULL, &ring->desc_dmat);
+       if (error != 0) {
+               device_printf(sc->sc_dev, "could not create desc DMA tag\n");
+               goto fail;
+       }
+
+       error = bus_dmamem_alloc(ring->desc_dmat, (void **)&ring->desc,
+           BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ring->desc_map);
+       if (error != 0) {
+               device_printf(sc->sc_dev, "could not allocate DMA memory\n");
+               goto fail;
+       }
+
+       error = bus_dmamap_load(ring->desc_dmat, ring->desc_map, ring->desc,
+           count * RT2560_RX_DESC_SIZE, rt2560_dma_map_addr, &ring->physaddr,
+           0);
+       if (error != 0) {
+               device_printf(sc->sc_dev, "could not load desc DMA map\n");
+               goto fail;
+       }
+
+       ring->data = malloc(count * sizeof (struct rt2560_rx_data), M_DEVBUF,
+           M_NOWAIT | M_ZERO);
+       if (ring->data == NULL) {
+               device_printf(sc->sc_dev, "could not allocate soft data\n");
+               error = ENOMEM;
+               goto fail;
+       }
+
+       /*
+        * Pre-allocate Rx buffers and populate Rx ring.
+        */
+       error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 
+           BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
+           1, MCLBYTES, 0, NULL, NULL, &ring->data_dmat);
+       if (error != 0) {
+               device_printf(sc->sc_dev, "could not create data DMA tag\n");
+               goto fail;

[... truncated: 6411 lines follow ...]

Other related posts: