[drivers rtl8180] First shot at an rtl8180/8185 driver
authorJoshua Oreman <oremanj@xenon.get-linux.org>
Tue, 2 Jun 2009 03:48:50 +0000 (20:48 -0700)
committerJoshua Oreman <oremanj@xenon.get-linux.org>
Tue, 2 Jun 2009 03:48:50 +0000 (20:48 -0700)
I trimmed and ported the Linux rtl8180 driver, supporting the 8180
and 8185 chipsets, to gPXE's fledgling 802.11 layer. The result
compiles but does not yet link because none of the generic 802.11
functions have been written yet. Code size is 3k for the card and
up to 8k for the RF initialization (lots of constants).

This chipset is often bundled with different RF modules; I've
included support for the four supported by the Linux driver using
gPXE's linker tables. The rtl8225 chip supports 802.11g on 8185
cards; the other three are similar and support 802.11b on 8180
cards.

# Please enter the commit message for your changes.
# (Comment lines starting with '#' will not be included)
# On branch wireless
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
# modified:   Makefile
# new file:   drivers/net/rtl818x/rtl8180.c
# modified:   drivers/net/rtl818x/rtl8180.h
# deleted:    drivers/net/rtl818x/rtl8180_dev.c
# modified:   drivers/net/rtl818x/rtl8180_grf5101.c
# deleted:    drivers/net/rtl818x/rtl8180_grf5101.h
# modified:   drivers/net/rtl818x/rtl8180_max2820.c
# deleted:    drivers/net/rtl818x/rtl8180_max2820.h
# modified:   drivers/net/rtl818x/rtl8180_rtl8225.c
# deleted:    drivers/net/rtl818x/rtl8180_rtl8225.h
# modified:   drivers/net/rtl818x/rtl8180_sa2400.c
# deleted:    drivers/net/rtl818x/rtl8180_sa2400.h
# modified:   drivers/net/rtl818x/rtl818x.h
# modified:   include/gpxe/errfile.h
# modified:   include/gpxe/ieee80211.h
# modified:   include/gpxe/net80211.h
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
# ../#foo#
# ../._linux-2.6.29
# ../80211-notes.txt
# ../atheros/
# ../b43-tools/
# ../core
# ../dhcp-capture.pcap
# ../fireproxy-0.34.tar.gz
# ../fireproxy-0.34/
# ../firewire-chainload.patch
# ../flashrom/
# ../gdb-firewire-v2-v3-incr.patch
# ../gdb-firewire-v2.patch
# ../gdb-firewire-v3-v4-incr.patch
# ../gdb-firewire-v3.patch
# ../gdb-firewire-v4.patch
# ../gdb-firewire.patch
# ../gpxe.lkrn
# ../ieee1394_types.h
# ../lin-ohci1394.c
# ../lin-skge.c
# ../lin-skge.h
# ../lin-sky2.c
# ../lin-sky2.h
# ../linux-2.6.29/
# ../ohci1394.h
# ../ohci1394_dma_early-v3.diff
# ../pxe-ohci1394.c
# ../pxe-ohci1394.h
# ../pxe-skge.c
# ../pxe-skge.h
# ../pxe-sky2.c
# ../pxe-sky2.h
# ../sky2-incr-v1-v2.patch
# ../sky2-v2.patch
# ../sky2.patch
# drivers/net/rtl818x/#rtl8180_max2820.c#
# drivers/net/rtl818x/.#rtl8180_max2820.c
# ../wpa_supplicant-0.6.9.tar.gz
# ../wpa_supplicant-0.6.9/

13 files changed:
src/Makefile
src/drivers/net/rtl818x/rtl8180.h
src/drivers/net/rtl818x/rtl8180_dev.c
src/drivers/net/rtl818x/rtl8180_grf5101.c
src/drivers/net/rtl818x/rtl8180_grf5101.h [deleted file]
src/drivers/net/rtl818x/rtl8180_max2820.c
src/drivers/net/rtl818x/rtl8180_max2820.h [deleted file]
src/drivers/net/rtl818x/rtl8180_rtl8225.c
src/drivers/net/rtl818x/rtl8180_rtl8225.h [deleted file]
src/drivers/net/rtl818x/rtl8180_sa2400.c
src/drivers/net/rtl818x/rtl8180_sa2400.h [deleted file]
src/drivers/net/rtl818x/rtl818x.h
src/include/gpxe/errfile.h

index add582a..0dd60f9 100644 (file)
@@ -55,12 +55,13 @@ SRCDIRS             :=
 SRCDIRS                += libgcc
 SRCDIRS                += core
 SRCDIRS                += proto
-SRCDIRS                += net net/tcp net/udp
+SRCDIRS                += net net/tcp net/udp net/80211
 SRCDIRS                += image
 SRCDIRS                += drivers/bus
 SRCDIRS                += drivers/net
 SRCDIRS                += drivers/net/e1000
 SRCDIRS                += drivers/net/phantom
+SRCDIRS                += drivers/net/rtl818x
 SRCDIRS                += drivers/block
 SRCDIRS                += drivers/nvs
 SRCDIRS                += drivers/bitbash
index 8721282..557cf3d 100644 (file)
@@ -1,9 +1,12 @@
 #ifndef RTL8180_H
 #define RTL8180_H
 
+#include <gpxe/spi_bit.h>
 #include "rtl818x.h"
 
-#define MAX_RX_SIZE IEEE80211_MAX_RTS_THRESHOLD
+FILE_LICENCE(GPL2_ONLY);
+
+#define MAX_RX_SIZE IEEE80211_MAX_FRAME_LEN
 
 #define RF_PARAM_ANALOGPHY     (1 << 0)
 #define RF_PARAM_ANTBDEFAULT   (1 << 1)
 #define ANAPARAM_PWR1_SHIFT    20
 #define ANAPARAM_PWR1_MASK     (0x7F << ANAPARAM_PWR1_SHIFT)
 
+#define RTL8180_RX_RING_SIZE   16 /* doesn't have to be a power of 2 */
+#define RTL8180_TX_RING_SIZE   16 /* nor this [but 2^n is very slightly faster] */
+#define RTL8180_RING_ALIGN     256
+
+#define RTL8180_MAX_RETRIES     4
+
 struct rtl8180_tx_desc {
-       __le32 flags;
-       __le16 rts_duration;
-       __le16 plcp_len;
-       __le32 tx_buf;
-       __le32 frame_len;
-       __le32 next_tx_desc;
+       u32 flags;
+       u16 rts_duration;
+       u16 plcp_len;
+       u32 tx_buf;
+       u32 frame_len;
+       u32 next_tx_desc;
        u8 cw;
        u8 retry_limit;
        u8 agc;
@@ -39,82 +48,81 @@ struct rtl8180_tx_desc {
 } __attribute__ ((packed));
 
 struct rtl8180_rx_desc {
-       __le32 flags;
-       __le32 flags2;
+       u32 flags;
+       u32 flags2;
        union {
-               __le32 rx_buf;
-               __le64 tsft;
+               u32 rx_buf;
+               u64 tsft;
        };
 } __attribute__ ((packed));
 
-struct rtl8180_tx_ring {
-       struct rtl8180_tx_desc *desc;
-       dma_addr_t dma;
-       unsigned int idx;
-       unsigned int entries;
-       struct sk_buff_head queue;
-};
-
 struct rtl8180_priv {
        /* common between rtl818x drivers */
-       struct rtl818x_csr __iomem *map;
+       struct rtl818x_csr *map;
        const struct rtl818x_rf_ops *rf;
-       struct ieee80211_vif *vif;
-       int mode;
+       int rf_flag; /* whatever RF driver wishes to use it for */
+       int hw_rate;
+
+       struct spi_bit_basher spibit;
+       struct spi_device eeprom;
 
        /* rtl8180 driver specific */
-       spinlock_t lock;
        struct rtl8180_rx_desc *rx_ring;
-       dma_addr_t rx_ring_dma;
-       unsigned int rx_idx;
-       struct sk_buff *rx_buf[32];
-       struct rtl8180_tx_ring tx_ring[4];
-       struct ieee80211_channel channels[14];
-       struct ieee80211_rate rates[12];
-       struct ieee80211_supported_band band;
-       struct pci_dev *pdev;
+       u32 rx_ring_dma;
+       unsigned int rx_idx;    /* next desc to be filled by card */
+       struct io_buffer *rx_buf[RTL8180_RX_RING_SIZE];
+
+       struct rtl8180_tx_desc *tx_ring;
+       u32 tx_ring_dma;
+       unsigned int tx_cons;   /* next desc to be filled by card */
+       unsigned int tx_prod;   /* next desc to be filled by driver */
+       struct io_buffer *tx_buf[RTL8180_TX_RING_SIZE];
+
+       struct pci_device *pdev;
        u32 rx_conf;
 
+       u16 txpower[14];
+
        int r8185;
        u32 anaparam;
        u16 rfparam;
        u8 csthreshold;
 };
 
-void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
+void rtl8180_write_phy(struct net80211_device *dev, u8 addr, u32 data);
 void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam);
 
-static inline u8 rtl818x_ioread8(struct rtl8180_priv *priv, u8 __iomem *addr)
+static inline u8 rtl818x_ioread8(struct rtl8180_priv *priv __unused, u8 *addr)
 {
-       return ioread8(addr);
+       return inb(addr);
 }
 
-static inline u16 rtl818x_ioread16(struct rtl8180_priv *priv, __le16 __iomem *addr)
+static inline u16 rtl818x_ioread16(struct rtl8180_priv *priv __unused, u16 *addr)
 {
-       return ioread16(addr);
+       return inw(addr);
 }
 
-static inline u32 rtl818x_ioread32(struct rtl8180_priv *priv, __le32 __iomem *addr)
+static inline u32 rtl818x_ioread32(struct rtl8180_priv *priv __unused, u32 *addr)
 {
-       return ioread32(addr);
+       return inl(addr);
 }
 
-static inline void rtl818x_iowrite8(struct rtl8180_priv *priv,
-                                   u8 __iomem *addr, u8 val)
+static inline void rtl818x_iowrite8(struct rtl8180_priv *priv __unused,
+                                   u8 *addr, u8 val)
 {
-       iowrite8(val, addr);
+       outb(val, addr);
 }
 
-static inline void rtl818x_iowrite16(struct rtl8180_priv *priv,
-                                    __le16 __iomem *addr, u16 val)
+static inline void rtl818x_iowrite16(struct rtl8180_priv *priv __unused,
+                                    u16 *addr, u16 val)
 {
-       iowrite16(val, addr);
+       outw(val, addr);
 }
 
-static inline void rtl818x_iowrite32(struct rtl8180_priv *priv,
-                                    __le32 __iomem *addr, u32 val)
+static inline void rtl818x_iowrite32(struct rtl8180_priv *priv __unused,
+                                    u32 *addr, u32 val)
 {
-       iowrite32(val, addr);
+       outl(val, addr);
 }
 
 #endif /* RTL8180_H */
index 387c133..635f8f8 100644 (file)
@@ -5,6 +5,8 @@
  * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
  *
+ * Modified for gPXE, June 2009, by Joshua Oreman <oremanj@rwcr.net>
+ *
  * Based on the r8180 driver, which is:
  * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
  *
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/eeprom_93cx6.h>
-#include <net/mac80211.h>
+FILE_LICENCE(GPL2_ONLY);
 
-#include "rtl8180.h"
-#include "rtl8180_rtl8225.h"
-#include "rtl8180_sa2400.h"
-#include "rtl8180_max2820.h"
-#include "rtl8180_grf5101.h"
-
-MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
-MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
-MODULE_DESCRIPTION("RTL8180 / RTL8185 PCI wireless driver");
-MODULE_LICENSE("GPL");
-
-static struct pci_device_id rtl8180_table[] __devinitdata = {
-       /* rtl8185 */
-       { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185) },
-       { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x700f) },
-       { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x701f) },
-
-       /* rtl8180 */
-       { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8180) },
-       { PCI_DEVICE(0x1799, 0x6001) },
-       { PCI_DEVICE(0x1799, 0x6020) },
-       { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x3300) },
-       { }
-};
+#include <stdint.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <byteswap.h>
+#include <gpxe/iobuf.h>
+#include <gpxe/malloc.h>
+#include <gpxe/pci.h>
+#include <gpxe/net80211.h>
+#include <gpxe/netdevice.h>
+#include <gpxe/threewire.h>
 
-MODULE_DEVICE_TABLE(pci, rtl8180_table);
-
-static const struct ieee80211_rate rtl818x_rates[] = {
-       { .bitrate = 10, .hw_value = 0, },
-       { .bitrate = 20, .hw_value = 1, },
-       { .bitrate = 55, .hw_value = 2, },
-       { .bitrate = 110, .hw_value = 3, },
-       { .bitrate = 60, .hw_value = 4, },
-       { .bitrate = 90, .hw_value = 5, },
-       { .bitrate = 120, .hw_value = 6, },
-       { .bitrate = 180, .hw_value = 7, },
-       { .bitrate = 240, .hw_value = 8, },
-       { .bitrate = 360, .hw_value = 9, },
-       { .bitrate = 480, .hw_value = 10, },
-       { .bitrate = 540, .hw_value = 11, },
-};
+#include "rtl8180.h"
 
-static const struct ieee80211_channel rtl818x_channels[] = {
-       { .center_freq = 2412 },
-       { .center_freq = 2417 },
-       { .center_freq = 2422 },
-       { .center_freq = 2427 },
-       { .center_freq = 2432 },
-       { .center_freq = 2437 },
-       { .center_freq = 2442 },
-       { .center_freq = 2447 },
-       { .center_freq = 2452 },
-       { .center_freq = 2457 },
-       { .center_freq = 2462 },
-       { .center_freq = 2467 },
-       { .center_freq = 2472 },
-       { .center_freq = 2484 },
+/* rtl818x_rates[hw rate number] = rate in 100kbps units */
+static const u16 rtl818x_rates[] = {
+       10, 20, 55, 110, /* 802.11b */
+       60, 90, 120, 180, 240, 360, 480, 540, /* 802.11g */
 };
+#define RTL818X_NR_RATES 12
 
-
-
-
-void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
+/* used by RF drivers */
+void rtl8180_write_phy(struct net80211_device *dev, u8 addr, u32 data)
 {
        struct rtl8180_priv *priv = dev->priv;
        int i = 10;
@@ -92,216 +49,148 @@ void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
 
        buf = (data << 8) | addr;
 
-       rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->PHY[0], buf | 0x80);
+       rtl818x_iowrite32(priv, (u32 *)&priv->map->PHY[0], buf | 0x80);
        while (i--) {
-               rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->PHY[0], buf);
+               rtl818x_iowrite32(priv, (u32 *)&priv->map->PHY[0], buf);
                if (rtl818x_ioread8(priv, &priv->map->PHY[2]) == (data & 0xFF))
                        return;
        }
 }
 
-static void rtl8180_handle_rx(struct ieee80211_hw *dev)
+static void rtl8180_handle_rx(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
-       unsigned int count = 32;
+       unsigned int count = RTL8180_RX_RING_SIZE;
 
        while (count--) {
                struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx];
-               struct sk_buff *skb = priv->rx_buf[priv->rx_idx];
+               struct io_buffer *iob = priv->rx_buf[priv->rx_idx];
                u32 flags = le32_to_cpu(entry->flags);
 
                if (flags & RTL818X_RX_DESC_FLAG_OWN)
                        return;
 
-               if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL |
-                                     RTL818X_RX_DESC_FLAG_FOF |
-                                     RTL818X_RX_DESC_FLAG_RX_ERR)))
-                       goto done;
-               else {
+               if (flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL |
+                            RTL818X_RX_DESC_FLAG_FOF |
+                            RTL818X_RX_DESC_FLAG_RX_ERR |
+                            RTL818X_RX_DESC_FLAG_CRC32_ERR)) {
+                       net80211_rx_err(dev, NULL, EIO);
+               } else {
                        u32 flags2 = le32_to_cpu(entry->flags2);
-                       struct ieee80211_rx_status rx_status = {0};
-                       struct sk_buff *new_skb = dev_alloc_skb(MAX_RX_SIZE);
-
-                       if (unlikely(!new_skb))
+                       struct io_buffer *new_iob = alloc_iob(MAX_RX_SIZE);
+                       if (!new_iob) {
+                               net80211_rx_err(dev, NULL, ENOMEM);
                                goto done;
+                       }
+
+                       iob_put(iob, flags & 0xFFF);
+                       dev->signal = (flags2 >> 8) & 0x7f;
+
+                       net80211_rx(dev, iob);
 
-                       pci_unmap_single(priv->pdev,
-                                        *((dma_addr_t *)skb->cb),
-                                        MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
-                       skb_put(skb, flags & 0xFFF);
-
-                       rx_status.antenna = (flags2 >> 15) & 1;
-                       /* TODO: improve signal/rssi reporting */
-                       rx_status.qual = flags2 & 0xFF;
-                       rx_status.signal = (flags2 >> 8) & 0x7F;
-                       /* XXX: is this correct? */
-                       rx_status.rate_idx = (flags >> 20) & 0xF;
-                       rx_status.freq = dev->conf.channel->center_freq;
-                       rx_status.band = dev->conf.channel->band;
-                       rx_status.mactime = le64_to_cpu(entry->tsft);
-                       rx_status.flag |= RX_FLAG_TSFT;
-                       if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
-                               rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
-
-                       ieee80211_rx_irqsafe(dev, skb, &rx_status);
-
-                       skb = new_skb;
-                       priv->rx_buf[priv->rx_idx] = skb;
-                       *((dma_addr_t *) skb->cb) =
-                               pci_map_single(priv->pdev, skb_tail_pointer(skb),
-                                              MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
+                       iob = new_iob;
+                       priv->rx_buf[priv->rx_idx] = iob;
                }
 
        done:
-               entry->rx_buf = cpu_to_le32(*((dma_addr_t *)skb->cb));
-               entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN |
-                                          MAX_RX_SIZE);
-               if (priv->rx_idx == 31)
+               entry->rx_buf = cpu_to_le32(virt_to_bus(iob->data));
+               entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN | MAX_RX_SIZE);
+
+               if (priv->rx_idx == RTL8180_RX_RING_SIZE - 1)
                        entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR);
-               priv->rx_idx = (priv->rx_idx + 1) % 32;
+
+               priv->rx_idx = (priv->rx_idx + 1) % RTL8180_RX_RING_SIZE;
        }
 }
 
-static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio)
+static void rtl8180_handle_tx(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
-       struct rtl8180_tx_ring *ring = &priv->tx_ring[prio];
-
-       while (skb_queue_len(&ring->queue)) {
-               struct rtl8180_tx_desc *entry = &ring->desc[ring->idx];
-               struct sk_buff *skb;
-               struct ieee80211_tx_info *info;
+       unsigned int count = RTL8180_TX_RING_SIZE;
+       
+       while (count--) {
+               struct rtl8180_tx_desc *entry = &priv->tx_ring[priv->tx_cons];
+               struct io_buffer *iob = priv->tx_buf[priv->tx_cons];
                u32 flags = le32_to_cpu(entry->flags);
+               int rc;
 
                if (flags & RTL818X_TX_DESC_FLAG_OWN)
                        return;
 
-               ring->idx = (ring->idx + 1) % ring->entries;
-               skb = __skb_dequeue(&ring->queue);
-               pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf),
-                                skb->len, PCI_DMA_TODEVICE);
-
-               info = IEEE80211_SKB_CB(skb);
-               ieee80211_tx_info_clear_status(info);
-
-               if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
-                   (flags & RTL818X_TX_DESC_FLAG_TX_OK))
-                       info->flags |= IEEE80211_TX_STAT_ACK;
+               rc = 0;
+               if (!(flags & RTL818X_TX_DESC_FLAG_TX_OK)) {
+                       /* our packet was not ACKed properly */
+                       rc = EBUSY;
+               }
 
-               info->status.rates[0].count = (flags & 0xFF) + 1;
+               net80211_tx_complete(dev, iob, rc);
 
-               ieee80211_tx_status_irqsafe(dev, skb);
-               if (ring->entries - skb_queue_len(&ring->queue) == 2)
-                       ieee80211_wake_queue(dev, prio);
+               priv->tx_buf[priv->tx_cons] = NULL;
+               priv->tx_cons = (priv->tx_cons + 1) % RTL8180_TX_RING_SIZE;
        }
 }
 
-static irqreturn_t rtl8180_interrupt(int irq, void *dev_id)
+static void rtl8180_poll(struct net80211_device *dev)
 {
-       struct ieee80211_hw *dev = dev_id;
        struct rtl8180_priv *priv = dev->priv;
-       u16 reg;
-
-       spin_lock(&priv->lock);
-       reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS);
-       if (unlikely(reg == 0xFFFF)) {
-               spin_unlock(&priv->lock);
-               return IRQ_HANDLED;
-       }
+       u16 reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS);
 
        rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg);
 
-       if (reg & (RTL818X_INT_TXB_OK | RTL818X_INT_TXB_ERR))
-               rtl8180_handle_tx(dev, 3);
-
-       if (reg & (RTL818X_INT_TXH_OK | RTL818X_INT_TXH_ERR))
-               rtl8180_handle_tx(dev, 2);
-
        if (reg & (RTL818X_INT_TXN_OK | RTL818X_INT_TXN_ERR))
-               rtl8180_handle_tx(dev, 1);
-
-       if (reg & (RTL818X_INT_TXL_OK | RTL818X_INT_TXL_ERR))
-               rtl8180_handle_tx(dev, 0);
+               rtl8180_handle_tx(dev);
 
        if (reg & (RTL818X_INT_RX_OK | RTL818X_INT_RX_ERR))
                rtl8180_handle_rx(dev);
-
-       spin_unlock(&priv->lock);
-
-       return IRQ_HANDLED;
 }
 
-static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
+#define DIV_ROUND_UP(n,d) (((n)+(d)-1)/(d))
+
+static int rtl8180_tx(struct net80211_device *dev, struct io_buffer *iob)
 {
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct rtl8180_priv *priv = dev->priv;
-       struct rtl8180_tx_ring *ring;
        struct rtl8180_tx_desc *entry;
-       unsigned long flags;
-       unsigned int idx, prio;
-       dma_addr_t mapping;
        u32 tx_flags;
-       u8 rc_flags;
        u16 plcp_len = 0;
-       __le16 rts_duration = 0;
-
-       prio = skb_get_queue_mapping(skb);
-       ring = &priv->tx_ring[prio];
-
-       mapping = pci_map_single(priv->pdev, skb->data,
-                                skb->len, PCI_DMA_TODEVICE);
-
+       int len = iob_len(iob);
+       
        tx_flags = RTL818X_TX_DESC_FLAG_OWN | RTL818X_TX_DESC_FLAG_FS |
-                  RTL818X_TX_DESC_FLAG_LS |
-                  (ieee80211_get_tx_rate(dev, info)->hw_value << 24) |
-                  skb->len;
+               RTL818X_TX_DESC_FLAG_LS | (priv->hw_rate << 24) | len;
 
-       if (priv->r8185)
+       if (priv->r8185) {
                tx_flags |= RTL818X_TX_DESC_FLAG_DMA |
                            RTL818X_TX_DESC_FLAG_NO_ENC;
-
-       rc_flags = info->control.rates[0].flags;
-       if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
-               tx_flags |= RTL818X_TX_DESC_FLAG_RTS;
-               tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
-       } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
-               tx_flags |= RTL818X_TX_DESC_FLAG_CTS;
-               tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
-       }
-
-       if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS)
-               rts_duration = ieee80211_rts_duration(dev, priv->vif, skb->len,
-                                                     info);
-
-       if (!priv->r8185) {
+       } else {
                unsigned int remainder;
 
-               plcp_len = DIV_ROUND_UP(16 * (skb->len + 4),
-                               (ieee80211_get_tx_rate(dev, info)->bitrate * 2) / 10);
-               remainder = (16 * (skb->len + 4)) %
-                           ((ieee80211_get_tx_rate(dev, info)->bitrate * 2) / 10);
+               plcp_len = DIV_ROUND_UP(16 * (len + 4),
+                                       (dev->rates[dev->rate] * 2) / 10);
+               remainder = (16 * (len + 4)) %
+                           ((dev->rates[dev->rate] * 2) / 10);
+
                if (remainder > 0 && remainder <= 6)
                        plcp_len |= 1 << 15;
        }
 
-       spin_lock_irqsave(&priv->lock, flags);
-       idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries;
-       entry = &ring->desc[idx];
+       entry = &priv->tx_ring[priv->tx_prod];
+
+       if (entry->flags & RTL818X_TX_DESC_FLAG_OWN) {
+               /* card hasn't processed the old packet yet! */
+               return -EBUSY;
+       }
+
+       priv->tx_buf[priv->tx_prod] = iob;
+       priv->tx_prod = (priv->tx_prod + 1) % RTL8180_TX_RING_SIZE;
 
-       entry->rts_duration = rts_duration;
+       entry->rts_duration = 0;
        entry->plcp_len = cpu_to_le16(plcp_len);
-       entry->tx_buf = cpu_to_le32(mapping);
-       entry->frame_len = cpu_to_le32(skb->len);
-       entry->flags2 = info->control.rates[1].idx >= 0 ?
-               ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0;
-       entry->retry_limit = info->control.rates[0].count;
+       entry->tx_buf = cpu_to_le32(virt_to_bus(iob->data));
+       entry->frame_len = cpu_to_le32(len);
+       entry->flags2 = /* alternate retry rate in 100kbps << 4 */ 0;
+       entry->retry_limit = RTL8180_MAX_RETRIES;
        entry->flags = cpu_to_le32(tx_flags);
-       __skb_queue_tail(&ring->queue, skb);
-       if (ring->entries - skb_queue_len(&ring->queue) < 2)
-               ieee80211_stop_queue(dev, skb_get_queue_mapping(skb));
-       spin_unlock_irqrestore(&priv->lock, flags);
 
-       rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4)));
+       rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << 5));
 
        return 0;
 }
@@ -320,14 +209,14 @@ void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam)
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
 }
 
-static int rtl8180_init_hw(struct ieee80211_hw *dev)
+static int rtl8180_init_hw(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
        u16 reg;
 
        rtl818x_iowrite8(priv, &priv->map->CMD, 0);
        rtl818x_ioread8(priv, &priv->map->CMD);
-       msleep(10);
+       mdelay(10);
 
        /* reset */
        rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
@@ -338,17 +227,17 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev)
        reg |= RTL818X_CMD_RESET;
        rtl818x_iowrite8(priv, &priv->map->CMD, RTL818X_CMD_RESET);
        rtl818x_ioread8(priv, &priv->map->CMD);
-       msleep(200);
+       mdelay(200);
 
        /* check success of reset */
        if (rtl818x_ioread8(priv, &priv->map->CMD) & RTL818X_CMD_RESET) {
-               printk(KERN_ERR "%s: reset timeout!\n", wiphy_name(dev->wiphy));
+               DBG("rtl8180 %s: reset timeout!\n", dev->netdev->name);
                return -ETIMEDOUT;
        }
 
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD);
        rtl818x_ioread8(priv, &priv->map->CMD);
-       msleep(200);
+       mdelay(200);
 
        if (rtl818x_ioread8(priv, &priv->map->CONFIG3) & (1 << 3)) {
                /* For cardbus */
@@ -366,10 +255,7 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev)
                rtl8180_set_anaparam(priv, priv->anaparam);
 
        rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma);
-       rtl818x_iowrite32(priv, &priv->map->TBDA, priv->tx_ring[3].dma);
-       rtl818x_iowrite32(priv, &priv->map->THPDA, priv->tx_ring[2].dma);
-       rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring[1].dma);
-       rtl818x_iowrite32(priv, &priv->map->TLPDA, priv->tx_ring[0].dma);
+       rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring_dma);
 
        /* TODO: necessary? specs indicate not */
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
@@ -415,37 +301,31 @@ static int rtl8180_init_hw(struct ieee80211_hw *dev)
        return 0;
 }
 
-static int rtl8180_init_rx_ring(struct ieee80211_hw *dev)
+static int rtl8180_init_rx_ring(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
        struct rtl8180_rx_desc *entry;
        int i;
 
-       priv->rx_ring = pci_alloc_consistent(priv->pdev,
-                                            sizeof(*priv->rx_ring) * 32,
-                                            &priv->rx_ring_dma);
-
-       if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) {
-               printk(KERN_ERR "%s: Cannot allocate RX ring\n",
-                      wiphy_name(dev->wiphy));
+       priv->rx_ring = malloc_dma(sizeof(*priv->rx_ring) * RTL8180_RX_RING_SIZE,
+                                  RTL8180_RING_ALIGN);
+       priv->rx_ring_dma = virt_to_bus(priv->rx_ring);
+       if (!priv->rx_ring) {
+               DBG("rtl8180 %s: cannot allocate RX ring\n", dev->netdev->name);
                return -ENOMEM;
        }
 
-       memset(priv->rx_ring, 0, sizeof(*priv->rx_ring) * 32);
+       memset(priv->rx_ring, 0, sizeof(*priv->rx_ring) * RTL8180_RX_RING_SIZE);
        priv->rx_idx = 0;
 
-       for (i = 0; i < 32; i++) {
-               struct sk_buff *skb = dev_alloc_skb(MAX_RX_SIZE);
-               dma_addr_t *mapping;
+       for (i = 0; i < RTL8180_RX_RING_SIZE; i++) {
+               struct io_buffer *iob = alloc_iob(MAX_RX_SIZE);
                entry = &priv->rx_ring[i];
-               if (!skb)
-                       return 0;
-
-               priv->rx_buf[i] = skb;
-               mapping = (dma_addr_t *)skb->cb;
-               *mapping = pci_map_single(priv->pdev, skb_tail_pointer(skb),
-                                         MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
-               entry->rx_buf = cpu_to_le32(*mapping);
+               if (!iob)
+                       return -ENOMEM;
+
+               priv->rx_buf[i] = iob;
+               entry->rx_buf = cpu_to_le32(virt_to_bus(iob->data));
                entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN |
                                           MAX_RX_SIZE);
        }
@@ -453,109 +333,86 @@ static int rtl8180_init_rx_ring(struct ieee80211_hw *dev)
        return 0;
 }
 
-static void rtl8180_free_rx_ring(struct ieee80211_hw *dev)
+static void rtl8180_free_rx_ring(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
        int i;
 
-       for (i = 0; i < 32; i++) {
-               struct sk_buff *skb = priv->rx_buf[i];
-               if (!skb)
-                       continue;
-
-               pci_unmap_single(priv->pdev,
-                                *((dma_addr_t *)skb->cb),
-                                MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
-               kfree_skb(skb);
+       for (i = 0; i < RTL8180_RX_RING_SIZE; i++) {
+               free_iob(priv->rx_buf[i]);
+               priv->rx_buf[i] = NULL;
        }
 
-       pci_free_consistent(priv->pdev, sizeof(*priv->rx_ring) * 32,
-                           priv->rx_ring, priv->rx_ring_dma);
+       free_dma(priv->rx_ring, sizeof(*priv->rx_ring) * RTL8180_RX_RING_SIZE);
        priv->rx_ring = NULL;
 }
 
-static int rtl8180_init_tx_ring(struct ieee80211_hw *dev,
-                               unsigned int prio, unsigned int entries)
+static int rtl8180_init_tx_ring(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
-       struct rtl8180_tx_desc *ring;
-       dma_addr_t dma;
        int i;
 
-       ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma);
-       if (!ring || (unsigned long)ring & 0xFF) {
-               printk(KERN_ERR "%s: Cannot allocate TX ring (prio = %d)\n",
-                      wiphy_name(dev->wiphy), prio);
+       priv->tx_ring = malloc_dma(sizeof(*priv->tx_ring) * RTL8180_TX_RING_SIZE,
+                                  RTL8180_RING_ALIGN);
+       priv->tx_ring_dma = virt_to_bus(priv->tx_ring);
+       if (!priv->tx_ring) {
+               DBG("rtl8180 %s: cannot allocate TX ring\n", dev->netdev->name);
                return -ENOMEM;
        }
 
-       memset(ring, 0, sizeof(*ring)*entries);
-       priv->tx_ring[prio].desc = ring;
-       priv->tx_ring[prio].dma = dma;
-       priv->tx_ring[prio].idx = 0;
-       priv->tx_ring[prio].entries = entries;
-       skb_queue_head_init(&priv->tx_ring[prio].queue);
+       memset(priv->tx_ring, 0, sizeof(*priv->tx_ring) * RTL8180_TX_RING_SIZE);
+       priv->tx_prod = priv->tx_cons = 0;
 
-       for (i = 0; i < entries; i++)
-               ring[i].next_tx_desc =
-                       cpu_to_le32((u32)dma + ((i + 1) % entries) * sizeof(*ring));
+       for (i = 0; i < RTL8180_TX_RING_SIZE; i++)
+               priv->tx_ring[i].next_tx_desc = cpu_to_le32(priv->tx_ring_dma +
+                               ((i + 1) % RTL8180_TX_RING_SIZE) * sizeof(*priv->tx_ring));
 
        return 0;
 }
 
-static void rtl8180_free_tx_ring(struct ieee80211_hw *dev, unsigned int prio)
+static void rtl8180_free_tx_ring(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
-       struct rtl8180_tx_ring *ring = &priv->tx_ring[prio];
-
-       while (skb_queue_len(&ring->queue)) {
-               struct rtl8180_tx_desc *entry = &ring->desc[ring->idx];
-               struct sk_buff *skb = __skb_dequeue(&ring->queue);
-
-               pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf),
-                                skb->len, PCI_DMA_TODEVICE);
-               kfree_skb(skb);
-               ring->idx = (ring->idx + 1) % ring->entries;
+       int i;
+       
+       for (i = 0; i < RTL8180_TX_RING_SIZE; i++) {
+               if (priv->tx_buf[i])
+                       net80211_tx_complete(dev, priv->tx_buf[i], ECANCELED);
+               priv->tx_buf[i] = NULL;
        }
 
-       pci_free_consistent(priv->pdev, sizeof(*ring->desc)*ring->entries,
-                           ring->desc, ring->dma);
-       ring->desc = NULL;
+       free_dma(priv->tx_ring, sizeof(*priv->tx_ring) * RTL8180_TX_RING_SIZE);
+       priv->tx_ring = NULL;
 }
 
-static int rtl8180_start(struct ieee80211_hw *dev)
+static void rtl8180_irq(struct net80211_device *dev, int enable) 
 {
        struct rtl8180_priv *priv = dev->priv;
-       int ret, i;
+       rtl818x_iowrite16(priv, &priv->map->INT_MASK, enable? 0xFFFF : 0);
+}
+
+static int rtl8180_start(struct net80211_device *dev)
+{
+       struct rtl8180_priv *priv = dev->priv;
+       int ret;
        u32 reg;
 
        ret = rtl8180_init_rx_ring(dev);
        if (ret)
                return ret;
 
-       for (i = 0; i < 4; i++)
-               if ((ret = rtl8180_init_tx_ring(dev, i, 16)))
-                       goto err_free_rings;
+       ret = rtl8180_init_tx_ring(dev);
+       if (ret)
+               goto err_free_rings;
 
        ret = rtl8180_init_hw(dev);
        if (ret)
                goto err_free_rings;
 
        rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma);
-       rtl818x_iowrite32(priv, &priv->map->TBDA, priv->tx_ring[3].dma);
-       rtl818x_iowrite32(priv, &priv->map->THPDA, priv->tx_ring[2].dma);
-       rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring[1].dma);
-       rtl818x_iowrite32(priv, &priv->map->TLPDA, priv->tx_ring[0].dma);
-
-       ret = request_irq(priv->pdev->irq, &rtl8180_interrupt,
-                         IRQF_SHARED, KBUILD_MODNAME, dev);
-       if (ret) {
-               printk(KERN_ERR "%s: failed to register IRQ handler\n",
-                      wiphy_name(dev->wiphy));
-               goto err_free_rings;
-       }
+       rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring_dma);
 
-       rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
+       rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
 
        rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0);
        rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0);
@@ -593,7 +450,7 @@ static int rtl8180_start(struct ieee80211_hw *dev)
                rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
 
                /* disable early TX */
-               rtl818x_iowrite8(priv, (u8 __iomem *)priv->map + 0xec, 0x3f);
+               rtl818x_iowrite8(priv, (u8 *)priv->map + 0xec, 0x3f);
        }
 
        reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
@@ -615,27 +472,22 @@ static int rtl8180_start(struct ieee80211_hw *dev)
        reg |= RTL818X_CMD_TX_ENABLE;
        rtl818x_iowrite8(priv, &priv->map->CMD, reg);
 
-       priv->mode = NL80211_IFTYPE_MONITOR;
        return 0;
 
  err_free_rings:
        rtl8180_free_rx_ring(dev);
-       for (i = 0; i < 4; i++)
-               if (priv->tx_ring[i].desc)
-                       rtl8180_free_tx_ring(dev, i);
+       if (priv->tx_ring)
+               rtl8180_free_tx_ring(dev);
 
        return ret;
 }
 
-static void rtl8180_stop(struct ieee80211_hw *dev)
+static void rtl8180_stop(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
        u8 reg;
-       int i;
 
-       priv->mode = NL80211_IFTYPE_UNSPECIFIED;
-
-       rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+       rtl8180_irq(dev, 0);
 
        reg = rtl818x_ioread8(priv, &priv->map->CMD);
        reg &= ~RTL818X_CMD_TX_ENABLE;
@@ -649,446 +501,306 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
        rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF);
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
 
-       free_irq(priv->pdev->irq, dev);
-
        rtl8180_free_rx_ring(dev);
-       for (i = 0; i < 4; i++)
-               rtl8180_free_tx_ring(dev, i);
+       rtl8180_free_tx_ring(dev);
 }
 
-static int rtl8180_add_interface(struct ieee80211_hw *dev,
-                                struct ieee80211_if_init_conf *conf)
+/* Sets the MAC address of the card. */
+#if 0                          /* currently unused */
+static void rtl8180_set_hwaddr(struct net80211_device *dev, u8 *hwaddr)
 {
        struct rtl8180_priv *priv = dev->priv;
-
-       if (priv->mode != NL80211_IFTYPE_MONITOR)
-               return -EOPNOTSUPP;
-
-       switch (conf->type) {
-       case NL80211_IFTYPE_STATION:
-               priv->mode = conf->type;
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       priv->vif = conf->vif;
-
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
-       rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0],
-                         le32_to_cpu(*(__le32 *)conf->mac_addr));
-       rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4],
-                         le16_to_cpu(*(__le16 *)(conf->mac_addr + 4)));
+       rtl818x_iowrite32(priv, (u32 *)&priv->map->MAC[0],
+                         le32_to_cpu(*(u32 *)hwaddr));
+       rtl818x_iowrite16(priv, (u16 *)&priv->map->MAC[4],
+                         le16_to_cpu(*(u16 *)(hwaddr + 4)));
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
-
-       return 0;
 }
+#endif
 
-static void rtl8180_remove_interface(struct ieee80211_hw *dev,
-                                    struct ieee80211_if_init_conf *conf)
-{
-       struct rtl8180_priv *priv = dev->priv;
-       priv->mode = NL80211_IFTYPE_MONITOR;
-       priv->vif = NULL;
-}
-
-static int rtl8180_config(struct ieee80211_hw *dev, u32 changed)
-{
-       struct rtl8180_priv *priv = dev->priv;
-       struct ieee80211_conf *conf = &dev->conf;
-
-       priv->rf->set_chan(dev, conf);
-
-       return 0;
-}
-
-static int rtl8180_config_interface(struct ieee80211_hw *dev,
-                                   struct ieee80211_vif *vif,
-                                   struct ieee80211_if_conf *conf)
+static int rtl8180_config(struct net80211_device *dev, int changed)
 {
        struct rtl8180_priv *priv = dev->priv;
        int i;
 
-       for (i = 0; i < ETH_ALEN; i++)
-               rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
-
-       if (is_valid_ether_addr(conf->bssid))
-               rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA);
-       else
-               rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK);
-
-       return 0;
-}
+       if (changed & NET80211_CFG_CHANNEL)
+               priv->rf->set_chan(dev, &dev->channels[dev->channel]);
 
-static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
-                                    struct ieee80211_vif *vif,
-                                    struct ieee80211_bss_conf *info,
-                                    u32 changed)
-{
-       struct rtl8180_priv *priv = dev->priv;
-
-       if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp)
-               priv->rf->conf_erp(dev, info);
-}
-
-static void rtl8180_configure_filter(struct ieee80211_hw *dev,
-                                    unsigned int changed_flags,
-                                    unsigned int *total_flags,
-                                    int mc_count, struct dev_addr_list *mclist)
-{
-       struct rtl8180_priv *priv = dev->priv;
+       if (changed & NET80211_CFG_ASSOC) {
+               for (i = 0; i < ETH_ALEN; i++)
+                       rtl818x_iowrite8(priv, &priv->map->BSSID[i], dev->bssid[i]);
+               rtl818x_iowrite8(priv, &priv->map->MSR,
+                                dev->assoc? RTL818X_MSR_INFRA : RTL818X_MSR_NO_LINK);
+       }
 
-       if (changed_flags & FIF_FCSFAIL)
-               priv->rx_conf ^= RTL818X_RX_CONF_FCS;
-       if (changed_flags & FIF_CONTROL)
-               priv->rx_conf ^= RTL818X_RX_CONF_CTRL;
-       if (changed_flags & FIF_OTHER_BSS)
-               priv->rx_conf ^= RTL818X_RX_CONF_MONITOR;
-       if (*total_flags & FIF_ALLMULTI || mc_count > 0)
-               priv->rx_conf |= RTL818X_RX_CONF_MULTICAST;
-       else
-               priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST;
+       if (changed & NET80211_CFG_ERP_PARAMS)
+               priv->rf->conf_erp(dev);
 
-       *total_flags = 0;
+       if (changed & NET80211_CFG_RATE) {
+               /* figure out the hardware rate number for the new
+                  logical rate */
+               int hw_rate;
+               for (hw_rate = 0; hw_rate < RTL818X_NR_RATES &&
+                            rtl818x_rates[hw_rate] != dev->rates[dev->rate];
+                    hw_rate++)
+                       ;
+               if (hw_rate >= 16)
+                       return -EINVAL;
 
-       if (priv->rx_conf & RTL818X_RX_CONF_FCS)
-               *total_flags |= FIF_FCSFAIL;
-       if (priv->rx_conf & RTL818X_RX_CONF_CTRL)
-               *total_flags |= FIF_CONTROL;
-       if (priv->rx_conf & RTL818X_RX_CONF_MONITOR)
-               *total_flags |= FIF_OTHER_BSS;
-       if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST)
-               *total_flags |= FIF_ALLMULTI;
+               priv->hw_rate = hw_rate;
+       }
 
-       rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf);
+       return 0;
 }
 
-static const struct ieee80211_ops rtl8180_ops = {
-       .tx                     = rtl8180_tx,
-       .start                  = rtl8180_start,
-       .stop                   = rtl8180_stop,
-       .add_interface          = rtl8180_add_interface,
-       .remove_interface       = rtl8180_remove_interface,
-       .config                 = rtl8180_config,
-       .config_interface       = rtl8180_config_interface,
-       .bss_info_changed       = rtl8180_bss_info_changed,
-       .configure_filter       = rtl8180_configure_filter,
+static const u8 rtl8180_eeprom_bits[] = {
+       [SPI_BIT_SCLK] = RTL818X_EEPROM_CMD_CK,
+       [SPI_BIT_MOSI] = RTL818X_EEPROM_CMD_READ,
+       [SPI_BIT_MISO] = RTL818X_EEPROM_CMD_WRITE,
+       [SPI_BIT_SS(0)] = RTL818X_EEPROM_CMD_CS,
 };
 
-static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom)
+static int rtl8180_spi_read_bit(struct bit_basher *basher, unsigned int bit_id)
 {
-       struct ieee80211_hw *dev = eeprom->data;
-       struct rtl8180_priv *priv = dev->priv;
+       struct rtl8180_priv *priv = container_of(basher, struct rtl8180_priv,
+                                                spibit.basher);
+       
        u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
-
-       eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
-       eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
-       eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
-       eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
+       return reg & rtl8180_eeprom_bits[bit_id];
 }
 
-static void rtl8180_eeprom_register_write(struct eeprom_93cx6 *eeprom)
+static void rtl8180_spi_write_bit(struct bit_basher *basher,
+                                 unsigned int bit_id, unsigned long data) 
 {
-       struct ieee80211_hw *dev = eeprom->data;
-       struct rtl8180_priv *priv = dev->priv;
-       u8 reg = 2 << 6;
+       struct rtl8180_priv *priv = container_of(basher, struct rtl8180_priv,
+                                                spibit.basher);
 
-       if (eeprom->reg_data_in)
-               reg |= RTL818X_EEPROM_CMD_WRITE;
-       if (eeprom->reg_data_out)
-               reg |= RTL818X_EEPROM_CMD_READ;
-       if (eeprom->reg_data_clock)
-               reg |= RTL818X_EEPROM_CMD_CK;
-       if (eeprom->reg_chip_select)
-               reg |= RTL818X_EEPROM_CMD_CS;
+       u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+       u8 mask = rtl8180_eeprom_bits[bit_id];
+       reg = (reg & ~mask) | (data & mask);
 
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg);
+
        rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
        udelay(10);
 }
 
-static int __devinit rtl8180_probe(struct pci_dev *pdev,
-                                  const struct pci_device_id *id)
+static struct bit_basher_operations rtl8180_basher_ops = {
+       .read = rtl8180_spi_read_bit,
+       .write = rtl8180_spi_write_bit,
+};
+
+/* The net80211 code makes a copy of this, so we're OK modifying the
+   static version as we initialize the card, as long as we don't
+   depend on possibly-modified values in case there are multiple cards. */
+static struct net80211_hw_info rtl8180_hwinfo = {
+       /* MAC address filled in at runtime */
+       /* modes filled in at runtime */
+       .bands = NET80211_BAND_2GHZ,
+       .flags = NET80211_HW_RX_HAS_FCS,
+       .signal_type = NET80211_SIGNAL_ARBITRARY,
+       /* supported rates filled in at runtime */
+       .signal_max = 65,
+       .channel_change_time = 1000, /* no idea what the actual value is */
+};
+
+static const char *rtl8180_rf_names[] = {
+       NULL,                   /* no 0 */
+       "Intersil", "RFMD",     /* unsupported 1-2 */
+       "SA2400", "max2820", "GRF5101", /* supported 3-5 */
+       NULL, NULL, NULL,       /* no 6-8 */
+       "RTL8225",              /* supported 9 */
+       "RTL8255",              /* unsupported 10 */
+};
+#define RTL8180_NR_RF_NAMES 11
+
+struct net80211_device_operations rtl8180_operations = {
+       .open = rtl8180_start,
+       .close = rtl8180_stop,
+       .transmit = rtl8180_tx,
+       .poll = rtl8180_poll,
+       .irq = rtl8180_irq,
+       .config = rtl8180_config,
+};
+
+static int rtl8180_probe(struct pci_device *pdev,
+                        const struct pci_device_id *id __unused)
 {
-       struct ieee80211_hw *dev;
+       struct net80211_device *dev;
        struct rtl8180_priv *priv;
-       unsigned long mem_addr, mem_len;
-       unsigned int io_addr, io_len;
+       struct rtl818x_rf_ops *rf;
        int err, i;
-       struct eeprom_93cx6 eeprom;
-       const char *chip_name, *rf_name = NULL;
+       const char *chip_name;
        u32 reg;
        u16 eeprom_val;
 
-       err = pci_enable_device(pdev);
-       if (err) {
-               printk(KERN_ERR "%s (rtl8180): Cannot enable new PCI device\n",
-                      pci_name(pdev));
-               return err;
-       }
-
-       err = pci_request_regions(pdev, KBUILD_MODNAME);
-       if (err) {
-               printk(KERN_ERR "%s (rtl8180): Cannot obtain PCI resources\n",
-                      pci_name(pdev));
-               return err;
-       }
+       adjust_pci_device(pdev);
 
-       io_addr = pci_resource_start(pdev, 0);
-       io_len = pci_resource_len(pdev, 0);
-       mem_addr = pci_resource_start(pdev, 1);
-       mem_len = pci_resource_len(pdev, 1);
-
-       if (mem_len < sizeof(struct rtl818x_csr) ||
-           io_len < sizeof(struct rtl818x_csr)) {
-               printk(KERN_ERR "%s (rtl8180): Too short PCI resources\n",
-                      pci_name(pdev));
-               err = -ENOMEM;
-               goto err_free_reg;
-       }
-
-       if ((err = pci_set_dma_mask(pdev, 0xFFFFFF00ULL)) ||
-           (err = pci_set_consistent_dma_mask(pdev, 0xFFFFFF00ULL))) {
-               printk(KERN_ERR "%s (rtl8180): No suitable DMA available\n",
-                      pci_name(pdev));
-               goto err_free_reg;
-       }
-
-       pci_set_master(pdev);
-
-       dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8180_ops);
+       dev = net80211_alloc(sizeof(*priv));
        if (!dev) {
-               printk(KERN_ERR "%s (rtl8180): ieee80211 alloc failed\n",
-                      pci_name(pdev));
-               err = -ENOMEM;
-               goto err_free_reg;
+               DBG("rtl8180: net80211 alloc failed\n");
+               return -ENOMEM;
        }
 
        priv = dev->priv;
        priv->pdev = pdev;
 
-       dev->max_rates = 2;
-       SET_IEEE80211_DEV(dev, &pdev->dev);
-       pci_set_drvdata(pdev, dev);
-
-       priv->map = pci_iomap(pdev, 1, mem_len);
+       priv->map = (struct rtl818x_csr *)pdev->ioaddr;
        if (!priv->map)
-               priv->map = pci_iomap(pdev, 0, io_len);
+               priv->map = (struct rtl818x_csr *)pdev->membase;
 
        if (!priv->map) {
-               printk(KERN_ERR "%s (rtl8180): Cannot map device memory\n",
-                      pci_name(pdev));
+               DBG("rtl8180: cannot find device memory\n");
+               err = -ENXIO;
                goto err_free_dev;
        }
 
-       BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels));
-       BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates));
-
-       memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
-       memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
-
-       priv->band.band = IEEE80211_BAND_2GHZ;
-       priv->band.channels = priv->channels;
-       priv->band.n_channels = ARRAY_SIZE(rtl818x_channels);
-       priv->band.bitrates = priv->rates;
-       priv->band.n_bitrates = 4;
-       dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band;
-
-       dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-                    IEEE80211_HW_RX_INCLUDES_FCS |
-                    IEEE80211_HW_SIGNAL_UNSPEC;
-       dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
-       dev->queues = 1;
-       dev->max_signal = 65;
-
        reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
        reg &= RTL818X_TX_CONF_HWVER_MASK;
        switch (reg) {
        case RTL818X_TX_CONF_R8180_ABCD:
-               chip_name = "RTL8180";
+               chip_name = "0";
                break;
        case RTL818X_TX_CONF_R8180_F:
-               chip_name = "RTL8180vF";
+               chip_name = "0vF";
                break;
        case RTL818X_TX_CONF_R8185_ABC:
-               chip_name = "RTL8185";
+               chip_name = "5";
                break;
        case RTL818X_TX_CONF_R8185_D:
-               chip_name = "RTL8185vD";
+               chip_name = "5vD";
                break;
        default:
-               printk(KERN_ERR "%s (rtl8180): Unknown chip! (0x%x)\n",
-                      pci_name(pdev), reg >> 25);
-               goto err_iounmap;
+               DBG("rtl8180: Unknown chip! (0x%x)\n", reg >> 25);
+               err = -ENOSYS;
+               goto err_free_dev;
        }
 
        priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC;
+
+       memcpy(rtl8180_hwinfo.supported_rates, rtl818x_rates,
+              sizeof(*rtl818x_rates) * RTL818X_NR_RATES);
+
        if (priv->r8185) {
-               priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates);
-               pci_try_set_mwi(pdev);
+               rtl8180_hwinfo.modes = NET80211_MODE_B | NET80211_MODE_G;
+               rtl8180_hwinfo.nr_supported_rates = RTL818X_NR_RATES;
+       } else {
+               rtl8180_hwinfo.modes = NET80211_MODE_B;
+               rtl8180_hwinfo.nr_supported_rates = 4; /* 802.11b rates only */
        }
 
-       eeprom.data = dev;
-       eeprom.register_read = rtl8180_eeprom_register_read;
-       eeprom.register_write = rtl8180_eeprom_register_write;
+       priv->spibit.basher.op = &rtl8180_basher_ops;
+       priv->spibit.bus.mode = SPI_MODE_THREEWIRE;
+       init_spi_bit_basher(&priv->spibit);
+
        if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6))
-               eeprom.width = PCI_EEPROM_WIDTH_93C66;
+               init_at93c66(&priv->eeprom, 16);
        else
-               eeprom.width = PCI_EEPROM_WIDTH_93C46;
+               init_at93c46(&priv->eeprom, 16);
+       priv->eeprom.bus = &priv->spibit.bus;
 
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_PROGRAM);
        rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
        udelay(10);
 
-       eeprom_93cx6_read(&eeprom, 0x06, &eeprom_val);
+       nvs_read(&priv->eeprom.nvs, 0x06, &eeprom_val, 2);
        eeprom_val &= 0xFF;
-       switch (eeprom_val) {
-       case 1: rf_name = "Intersil";
-               break;
-       case 2: rf_name = "RFMD";
-               break;
-       case 3: priv->rf = &sa2400_rf_ops;
-               break;
-       case 4: priv->rf = &max2820_rf_ops;
-               break;
-       case 5: priv->rf = &grf5101_rf_ops;
-               break;
-       case 9: priv->rf = rtl8180_detect_rf(dev);
-               break;
-       case 10:
-               rf_name = "RTL8255";
-               break;
-       default:
-               printk(KERN_ERR "%s (rtl8180): Unknown RF! (0x%x)\n",
-                      pci_name(pdev), eeprom_val);
-               goto err_iounmap;
+
+       priv->rf = NULL;
+       for_each_table_entry(rf, RTL818X_RF_DRIVERS) {
+               if (rf->id == eeprom_val) {
+                       priv->rf = rf;
+                       break;
+               }
        }
 
        if (!priv->rf) {
-               printk(KERN_ERR "%s (rtl8180): %s RF frontend not supported!\n",
-                      pci_name(pdev), rf_name);
-               goto err_iounmap;
+               if (eeprom_val < RTL8180_NR_RF_NAMES &&
+                   rtl8180_rf_names[eeprom_val] != NULL)
+                       DBG("rtl8180: %s RF frontend not supported!\n",
+                           rtl8180_rf_names[eeprom_val]);
+               else
+                       DBG("rtl8180: RF frontend #%d not recognized!\n",
+                           eeprom_val);
+
+               err = -ENOSYS;
+               goto err_free_dev;
        }
 
-       eeprom_93cx6_read(&eeprom, 0x17, &eeprom_val);
+       nvs_read(&priv->eeprom.nvs, 0x17, &eeprom_val, 2);
        priv->csthreshold = eeprom_val >> 8;
        if (!priv->r8185) {
-               __le32 anaparam;
-               eeprom_93cx6_multiread(&eeprom, 0xD, (__le16 *)&anaparam, 2);
-               priv->anaparam = le32_to_cpu(anaparam);
-               eeprom_93cx6_read(&eeprom, 0x19, &priv->rfparam);
+               nvs_read(&priv->eeprom.nvs, 0xD, &priv->anaparam, 4);
+               nvs_read(&priv->eeprom.nvs, 0x19, &priv->rfparam, 2);
+               priv->anaparam = le32_to_cpu(priv->anaparam);
+               priv->rfparam = le16_to_cpu(priv->rfparam);
        }
 
-       eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)dev->wiphy->perm_addr, 3);
-       if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
-               printk(KERN_WARNING "%s (rtl8180): Invalid hwaddr! Using"
-                      " randomly generated MAC addr\n", pci_name(pdev));
-               random_ether_addr(dev->wiphy->perm_addr);
-       }
+       /* read the MAC address */
+       nvs_read(&priv->eeprom.nvs, 0x7, rtl8180_hwinfo.hwaddr, 6);
 
        /* CCK TX power */
        for (i = 0; i < 14; i += 2) {
                u16 txpwr;
-               eeprom_93cx6_read(&eeprom, 0x10 + (i >> 1), &txpwr);
-               priv->channels[i].hw_value = txpwr & 0xFF;
-               priv->channels[i + 1].hw_value = txpwr >> 8;
+               nvs_read(&priv->eeprom.nvs, 0x10 + (i >> 1), &txpwr, 2);
+               priv->txpower[i] = txpwr & 0xFF;
+               priv->txpower[i + 1] = txpwr >> 8;
        }
 
        /* OFDM TX power */
        if (priv->r8185) {
                for (i = 0; i < 14; i += 2) {
                        u16 txpwr;
-                       eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr);
-                       priv->channels[i].hw_value |= (txpwr & 0xFF) << 8;
-                       priv->channels[i + 1].hw_value |= txpwr & 0xFF00;
+                       nvs_read(&priv->eeprom.nvs, 0x20 + (i >> 1), &txpwr, 2);
+                       priv->txpower[i] |= (txpwr & 0xFF) << 8;
+                       priv->txpower[i + 1] |= txpwr & 0xFF00;
                }
        }
 
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
 
-       spin_lock_init(&priv->lock);
-
-       err = ieee80211_register_hw(dev);
+       err = net80211_register(dev, &rtl8180_operations, &rtl8180_hwinfo);
        if (err) {
-               printk(KERN_ERR "%s (rtl8180): Cannot register device\n",
-                      pci_name(pdev));
-               goto err_iounmap;
+               DBG("rtl8180: cannot register device\n");
+               goto err_free_dev;
        }
 
-       printk(KERN_INFO "%s: hwaddr %pM, %s + %s\n",
-              wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
-              chip_name, priv->rf->name);
+       DBG("rtl8180: Realtek RTL818%s (RF chip %s) with address %s\n",
+           chip_name, priv->rf->name, netdev_hwaddr(dev->netdev));
 
        return 0;
 
- err_iounmap:
-       iounmap(priv->map);
-
  err_free_dev:
        pci_set_drvdata(pdev, NULL);
-       ieee80211_free_hw(dev);
-
- err_free_reg:
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
+       net80211_free(dev);
        return err;
 }
 
-static void __devexit rtl8180_remove(struct pci_dev *pdev)
+static void rtl8180_remove(struct pci_device *pdev)
 {
-       struct ieee80211_hw *dev = pci_get_drvdata(pdev);
-       struct rtl8180_priv *priv;
+       struct net80211_device *dev = pci_get_drvdata(pdev);
 
        if (!dev)
                return;
 
-       ieee80211_unregister_hw(dev);
-
-       priv = dev->priv;
-
-       pci_iounmap(pdev, priv->map);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       ieee80211_free_hw(dev);
+       net80211_unregister(dev);
+       net80211_free(dev);
 }
 
-#ifdef CONFIG_PM
-static int rtl8180_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       pci_save_state(pdev);
-       pci_set_power_state(pdev, pci_choose_state(pdev, state));
-       return 0;
-}
-
-static int rtl8180_resume(struct pci_dev *pdev)
-{
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-       return 0;
-}
-
-#endif /* CONFIG_PM */
+static struct pci_device_id rtl8180_nics[] = {
+       PCI_ROM(0x10ec, 0x8185, "rtl8185", "Realtek 8185", 0),
+       PCI_ROM(0x1799, 0x700f, "f5d7000", "Belkin F5D7000", 0),
+       PCI_ROM(0x1799, 0x701f, "f5d7010", "Belkin F5D7010", 0),
+       
+       PCI_ROM(0x10ec, 0x8180, "rtl8180", "Realtek 8180", 0),
+       PCI_ROM(0x1799, 0x6001, "f5d6001", "Belkin F5D6001", 0),
+       PCI_ROM(0x1799, 0x6020, "f5d6020", "Belkin F5D6020", 0),
+       PCI_ROM(0x1186, 0x3300, "dwl510",  "D-Link DWL-510", 0),
+};
 
-static struct pci_driver rtl8180_driver = {
-       .name           = KBUILD_MODNAME,
-       .id_table       = rtl8180_table,
+struct pci_driver rtl8180_driver __pci_driver = {
+       .ids            = rtl8180_nics,
        .probe          = rtl8180_probe,
-       .remove         = __devexit_p(rtl8180_remove),
-#ifdef CONFIG_PM
-       .suspend        = rtl8180_suspend,
-       .resume         = rtl8180_resume,
-#endif /* CONFIG_PM */
+       .remove         = rtl8180_remove,
 };
-
-static int __init rtl8180_init(void)
-{
-       return pci_register_driver(&rtl8180_driver);
-}
-
-static void __exit rtl8180_exit(void)
-{
-       pci_unregister_driver(&rtl8180_driver);
-}
-
-module_init(rtl8180_init);
-module_exit(rtl8180_exit);
index 947ee55..70f8a94 100644 (file)
@@ -4,6 +4,8 @@
  *
  * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
  *
+ * Modified slightly for gPXE, June 2009 by Joshua Oreman.
+ *
  * Code from the BSD driver and the rtl8181 project have been
  * very useful to understand certain things
  *
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <net/mac80211.h>
+#include <unistd.h>
+#include <gpxe/pci.h>
+#include <gpxe/net80211.h>
 
 #include "rtl8180.h"
-#include "rtl8180_grf5101.h"
+
+FILE_LICENCE(GPL2_ONLY);
+
+#define GRF5101_ANTENNA 0xA3
 
 static const int grf5101_encode[] = {
        0x0, 0x8, 0x4, 0xC,
@@ -34,7 +38,7 @@ static const int grf5101_encode[] = {
        0x3, 0xB, 0x7, 0xF
 };
 
-static void write_grf5101(struct ieee80211_hw *dev, u8 addr, u32 data)
+static void write_grf5101(struct net80211_device *dev, u8 addr, u32 data)
 {
        struct rtl8180_priv *priv = dev->priv;
        u32 phy_config;
@@ -49,13 +53,15 @@ static void write_grf5101(struct ieee80211_hw *dev, u8 addr, u32 data)
        /* MAC will bang bits to the chip */
        phy_config |= 0x90000000;
 
-       rtl818x_iowrite32(priv,
-               (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config);
+       /* This was originally a 32-bit write to a typecast
+          RFPinsOutput, but gcc complained about aliasing rules. -JBO */
+       rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, phy_config & 0xffff);
+       rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, phy_config >> 16);
 
-       msleep(3);
+       mdelay(3);
 }
 
-static void grf5101_write_phy_antenna(struct ieee80211_hw *dev, short chan)
+static void grf5101_write_phy_antenna(struct net80211_device *dev, short chan)
 {
        struct rtl8180_priv *priv = dev->priv;
        u8 ant = GRF5101_ANTENNA;
@@ -69,12 +75,12 @@ static void grf5101_write_phy_antenna(struct ieee80211_hw *dev, short chan)
        rtl8180_write_phy(dev, 0x10, ant);
 }
 
-static void grf5101_rf_set_channel(struct ieee80211_hw *dev,
-                                  struct ieee80211_conf *conf)
+static void grf5101_rf_set_channel(struct net80211_device *dev,
+                                  struct net80211_channel *channelp)
 {
        struct rtl8180_priv *priv = dev->priv;
-       int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
-       u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
+       int channel = channelp->channel_nr;
+       u32 txpw = priv->txpower[channel - 1] & 0xFF;
        u32 chan = channel - 1;
 
        /* set TX power */
@@ -91,7 +97,7 @@ static void grf5101_rf_set_channel(struct ieee80211_hw *dev,
        grf5101_write_phy_antenna(dev, channel);
 }
 
-static void grf5101_rf_stop(struct ieee80211_hw *dev)
+static void grf5101_rf_stop(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
        u32 anaparam;
@@ -107,7 +113,7 @@ static void grf5101_rf_stop(struct ieee80211_hw *dev)
        write_grf5101(dev, 0x00, 0x8e4);
 }
 
-static void grf5101_rf_init(struct ieee80211_hw *dev)
+static void grf5101_rf_init(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
 
@@ -172,8 +178,9 @@ static void grf5101_rf_init(struct ieee80211_hw *dev)
        rtl8180_write_phy(dev, 0x1b, 0x44);
 }
 
-const struct rtl818x_rf_ops grf5101_rf_ops = {
-       .name           = "GCT",
+struct rtl818x_rf_ops grf5101_rf_ops __rtl818x_rf_driver = {
+       .name           = "GCT GRF5101",
+       .id             = 5,
        .init           = grf5101_rf_init,
        .stop           = grf5101_rf_stop,
        .set_chan       = grf5101_rf_set_channel
diff --git a/src/drivers/net/rtl818x/rtl8180_grf5101.h b/src/drivers/net/rtl818x/rtl8180_grf5101.h
deleted file mode 100644 (file)
index 7664711..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef RTL8180_GRF5101_H
-#define RTL8180_GRF5101_H
-
-/*
- * Radio tuning for GCT GRF5101 on RTL8180
- *
- * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
- *
- * Code from the BSD driver and the rtl8181 project have been
- * very useful to understand certain things
- *
- * I want to thanks the Authors of such projects and the Ndiswrapper
- * project Authors.
- *
- * A special Big Thanks also is for all people who donated me cards,
- * making possible the creation of the original rtl8180 driver
- * from which this code is derived!
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#define GRF5101_ANTENNA 0xA3
-
-extern const struct rtl818x_rf_ops grf5101_rf_ops;
-
-#endif /* RTL8180_GRF5101_H */
index 6c825fd..98291bc 100644 (file)
@@ -3,6 +3,8 @@
  *
  * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
  *
+ * Modified slightly for gPXE, June 2009 by Joshua Oreman.
+ *
  * Code from the BSD driver and the rtl8181 project have been
  * very useful to understand certain things
  *
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <net/mac80211.h>
+#include <unistd.h>
+#include <gpxe/pci.h>
+#include <gpxe/net80211.h>
 
 #include "rtl8180.h"
-#include "rtl8180_max2820.h"
+
+FILE_LICENCE(GPL2_ONLY);
+
+#define MAXIM_ANTENNA 0xb3
 
 static const u32 max2820_chan[] = {
        12, /* CH 1 */
@@ -43,7 +47,7 @@ static const u32 max2820_chan[] = {
        84, /* CH 14 */
 };
 
-static void write_max2820(struct ieee80211_hw *dev, u8 addr, u32 data)
+static void write_max2820(struct net80211_device *dev, u8 addr, u32 data)
 {
        struct rtl8180_priv *priv = dev->priv;
        u32 phy_config;
@@ -54,13 +58,15 @@ static void write_max2820(struct ieee80211_hw *dev, u8 addr, u32 data)
        phy_config <<= 8;
        phy_config += (data >> 4) & 0xff;
 
-       rtl818x_iowrite32(priv,
-               (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config);
+       /* This was originally a 32-bit write to a typecast
+          RFPinsOutput, but gcc complained about aliasing rules. -JBO */
+       rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, phy_config & 0xffff);
+       rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, phy_config >> 16);
 
-       msleep(1);
+       mdelay(1);
 }
 
-static void max2820_write_phy_antenna(struct ieee80211_hw *dev, short chan)
+static void max2820_write_phy_antenna(struct net80211_device *dev, short chan)
 {
        struct rtl8180_priv *priv = dev->priv;
        u8 ant;
@@ -74,14 +80,13 @@ static void max2820_write_phy_antenna(struct ieee80211_hw *dev, short chan)
        rtl8180_write_phy(dev, 0x10, ant);
 }
 
-static void max2820_rf_set_channel(struct ieee80211_hw *dev,
-                                  struct ieee80211_conf *conf)
+static void max2820_rf_set_channel(struct net80211_device *dev,
+                                  struct net80211_channel *channelp)
 {
        struct rtl8180_priv *priv = dev->priv;
-       int channel = conf ?
-               ieee80211_frequency_to_channel(conf->channel->center_freq) : 1;
+       int channel = channelp->channel_nr;
        unsigned int chan_idx = channel - 1;
-       u32 txpw = priv->channels[chan_idx].hw_value & 0xFF;
+       u32 txpw = priv->txpower[chan_idx] & 0xFF;
        u32 chan = max2820_chan[chan_idx];
 
        /* While philips SA2400 drive the PA bias from
@@ -92,14 +97,14 @@ static void max2820_rf_set_channel(struct ieee80211_hw *dev,
        write_max2820(dev, 3, chan);
 }
 
-static void max2820_rf_stop(struct ieee80211_hw *dev)
+static void max2820_rf_stop(struct net80211_device *dev)
 {
        rtl8180_write_phy(dev, 3, 0x8);
        write_max2820(dev, 1, 0);
 }
 
 
-static void max2820_rf_init(struct ieee80211_hw *dev)
+static void max2820_rf_init(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
 
@@ -144,8 +149,9 @@ static void max2820_rf_init(struct ieee80211_hw *dev)
        max2820_rf_set_channel(dev, NULL);
 }
 
-const struct rtl818x_rf_ops max2820_rf_ops = {
-       .name           = "Maxim",
+struct rtl818x_rf_ops max2820_rf_ops __rtl818x_rf_driver = {
+       .name           = "Maxim max2820",
+       .id             = 4,
        .init           = max2820_rf_init,
        .stop           = max2820_rf_stop,
        .set_chan       = max2820_rf_set_channel
diff --git a/src/drivers/net/rtl818x/rtl8180_max2820.h b/src/drivers/net/rtl818x/rtl8180_max2820.h
deleted file mode 100644 (file)
index 61cf6d1..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef RTL8180_MAX2820_H
-#define RTL8180_MAX2820_H
-
-/*
- * Radio tuning for Maxim max2820 on RTL8180
- *
- * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
- *
- * Code from the BSD driver and the rtl8181 project have been
- * very useful to understand certain things
- *
- * I want to thanks the Authors of such projects and the Ndiswrapper
- * project Authors.
- *
- * A special Big Thanks also is for all people who donated me cards,
- * making possible the creation of the original rtl8180 driver
- * from which this code is derived!
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#define MAXIM_ANTENNA 0xb3
-
-extern const struct rtl818x_rf_ops max2820_rf_ops;
-
-#endif /* RTL8180_MAX2820_H */
index 4d2be0d..97e9f72 100644 (file)
@@ -5,6 +5,8 @@
  * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
  *
+ * Modified slightly for gPXE, June 2009 by Joshua Oreman
+ *
  * Based on the r8180 driver, which is:
  * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
  *
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <net/mac80211.h>
+#include <unistd.h>
+#include <gpxe/pci.h>
+#include <gpxe/net80211.h>
 
 #include "rtl8180.h"
-#include "rtl8180_rtl8225.h"
 
-static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
+FILE_LICENCE(GPL2_ONLY);
+
+#define RTL8225_ANAPARAM_ON    0xa0000b59
+#define RTL8225_ANAPARAM2_ON   0x860dec11
+#define RTL8225_ANAPARAM_OFF   0xa00beb59
+#define RTL8225_ANAPARAM2_OFF  0x840dec11
+
+#define min(a,b) (((a)<(b))?(a):(b))
+#define ARRAY_SIZE(a) (int)(sizeof(a)/sizeof((a)[0]))
+
+static inline void rtl8225_write_phy_ofdm(struct net80211_device *dev,
+                                         u8 addr, u8 data)
+{
+       rtl8180_write_phy(dev, addr, data);
+}
+
+static inline void rtl8225_write_phy_cck(struct net80211_device *dev,
+                                        u8 addr, u8 data)
+{
+       rtl8180_write_phy(dev, addr, data | 0x10000);
+}
+
+static void rtl8225_write(struct net80211_device *dev, u8 addr, u16 data)
 {
        struct rtl8180_priv *priv = dev->priv;
        u16 reg80, reg84, reg82;
@@ -71,7 +93,7 @@ static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
        rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
 }
 
-static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
+static u16 rtl8225_read(struct net80211_device *dev, u8 addr)
 {
        struct rtl8180_priv *priv = dev->priv;
        u16 reg80, reg82, reg84, out;
@@ -253,7 +275,7 @@ static const u32 rtl8225_chan[] = {
        0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
 };
 
-static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+static void rtl8225_rf_set_tx_power(struct net80211_device *dev, int channel)
 {
        struct rtl8180_priv *priv = dev->priv;
        u8 cck_power, ofdm_power;
@@ -261,8 +283,8 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
        u32 reg;
        int i;
 
-       cck_power = priv->channels[channel - 1].hw_value & 0xFF;
-       ofdm_power = priv->channels[channel - 1].hw_value >> 8;
+       cck_power = priv->txpower[channel - 1] & 0xFF;
+       ofdm_power = priv->txpower[channel - 1] >> 8;
 
        cck_power = min(cck_power, (u8)35);
        ofdm_power = min(ofdm_power, (u8)35);
@@ -278,7 +300,7 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
        for (i = 0; i < 8; i++)
                rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
 
-       msleep(1); /* FIXME: optional? */
+       mdelay(1); /* FIXME: optional? */
 
        /* anaparam2 on */
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
@@ -296,10 +318,10 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
        rtl8225_write_phy_ofdm(dev, 5, *tmp);
        rtl8225_write_phy_ofdm(dev, 7, *tmp);
 
-       msleep(1);
+       mdelay(1);
 }
 
-static void rtl8225_rf_init(struct ieee80211_hw *dev)
+static void rtl8225_rf_init(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
        int i;
@@ -312,7 +334,7 @@ static void rtl8225_rf_init(struct ieee80211_hw *dev)
        rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
        rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
        rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
-       msleep(200);    /* FIXME: ehh?? */
+       mdelay(200);    /* FIXME: ehh?? */
        rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6));
 
        rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
@@ -340,9 +362,9 @@ static void rtl8225_rf_init(struct ieee80211_hw *dev)
        rtl8225_write(dev, 0xC, 0x050);
        rtl8225_write(dev, 0xD, 0x6DB);
        rtl8225_write(dev, 0xE, 0x029);
-       rtl8225_write(dev, 0xF, 0x914); msleep(1);
+       rtl8225_write(dev, 0xF, 0x914); mdelay(1);
 
-       rtl8225_write(dev, 0x2, 0xC4D); msleep(100);
+       rtl8225_write(dev, 0x2, 0xC4D); mdelay(100);
 
        rtl8225_write(dev, 0x0, 0x127);
 
@@ -357,90 +379,90 @@ static void rtl8225_rf_init(struct ieee80211_hw *dev)
 
        for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
                rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
-               msleep(1);
+               mdelay(1);
                rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
-               msleep(1);
+               mdelay(1);
        }
 
-       msleep(1);
-
-       rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x06, 0x00); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x08, 0x00); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x11, 0x03); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
-
-       rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+       mdelay(1);
+
+       rtl8225_write_phy_ofdm(dev, 0x00, 0x01); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x01, 0x02); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x02, 0x62); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x03, 0x00); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x04, 0x00); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x05, 0x00); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x06, 0x00); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x07, 0x00); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x08, 0x00); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x10, 0x84); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x11, 0x03); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x12, 0x20); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x13, 0x20); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x14, 0x00); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x15, 0x40); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x16, 0x00); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x17, 0x40); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x19, 0x19); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x21, 0x27); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x22, 0x16); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x24, 0x46); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x25, 0x20); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x27, 0x88); mdelay(1);
+
+       rtl8225_write_phy_cck(dev, 0x00, 0x98); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x03, 0x20); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x04, 0x7e); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x05, 0x12); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x06, 0xfc); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x07, 0x78); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x08, 0x2e); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x10, 0x93); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x11, 0x88); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x12, 0x47); mdelay(1);
        rtl8225_write_phy_cck(dev, 0x13, 0xd0);
        rtl8225_write_phy_cck(dev, 0x19, 0x00);
        rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
        rtl8225_write_phy_cck(dev, 0x1b, 0x08);
        rtl8225_write_phy_cck(dev, 0x40, 0x86);
-       rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
-
-       rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); msleep(1);
+       rtl8225_write_phy_cck(dev, 0x41, 0x8d); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x42, 0x15); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x43, 0x18); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x44, 0x1f); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x45, 0x1e); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x46, 0x1a); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x47, 0x15); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x48, 0x10); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x49, 0x0a); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x4a, 0x05); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x4b, 0x02); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x4c, 0x05); mdelay(1);
+
+       rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); mdelay(1);
 
        rtl8225_rf_set_tx_power(dev, 1);
 
        /* RX antenna default to A */
-       rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);      /* B: 0xDB */
-       rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);     /* B: 0x10 */
+       rtl8225_write_phy_cck(dev, 0x10, 0x9b); mdelay(1);      /* B: 0xDB */
+       rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);     /* B: 0x10 */
 
        rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
-       msleep(1);
-       rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002);
+       mdelay(1);
+       rtl818x_iowrite32(priv, (u32 *)((u8 *)priv->map + 0x94), 0x15c00002);
        rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
 
        rtl8225_write(dev, 0x0c, 0x50);
@@ -469,15 +491,15 @@ static const u8 rtl8225z2_tx_power_cck[] = {
        0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
 };
 
-static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+static void rtl8225z2_rf_set_tx_power(struct net80211_device *dev, int channel)
 {
        struct rtl8180_priv *priv = dev->priv;
        u8 cck_power, ofdm_power;
        const u8 *tmp;
        int i;
 
-       cck_power = priv->channels[channel - 1].hw_value & 0xFF;
-       ofdm_power = priv->channels[channel - 1].hw_value >> 8;
+       cck_power = priv->txpower[channel - 1] & 0xFF;
+       ofdm_power = priv->txpower[channel - 1] >> 8;
 
        if (channel == 14)
                tmp = rtl8225z2_tx_power_cck_ch14;
@@ -499,7 +521,7 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
 
        rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, cck_power);
        rtl818x_ioread8(priv, &priv->map->TX_GAIN_CCK);
-       msleep(1);
+       mdelay(1);
 
        ofdm_power = min(ofdm_power, (u8)35);
        rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, ofdm_power);
@@ -510,7 +532,7 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
        rtl8225_write_phy_ofdm(dev, 7, 0x00);
        rtl8225_write_phy_ofdm(dev, 8, 0x40);
 
-       msleep(1);
+       mdelay(1);
 }
 
 static const u16 rtl8225z2_rxgain[] = {
@@ -528,7 +550,7 @@ static const u16 rtl8225z2_rxgain[] = {
        0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
 };
 
-static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
+static void rtl8225z2_rf_init(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
        int i;
@@ -541,7 +563,7 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
        rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
        rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
        rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
-       msleep(200);    /* FIXME: ehh?? */
+       mdelay(200);    /* FIXME: ehh?? */
        rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6));
 
        rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00088008);
@@ -556,28 +578,28 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
 
        rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
 
-       rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
-       rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
-       rtl8225_write(dev, 0x2, 0x44D); msleep(1);
-       rtl8225_write(dev, 0x3, 0x441); msleep(1);
-       rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
-       rtl8225_write(dev, 0x5, 0xC72); msleep(1);
-       rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
-       rtl8225_write(dev, 0x7, 0x82A); msleep(1);
-       rtl8225_write(dev, 0x8, 0x03F); msleep(1);
-       rtl8225_write(dev, 0x9, 0x335); msleep(1);
-       rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
-       rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
-       rtl8225_write(dev, 0xc, 0x850); msleep(1);
-       rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
-       rtl8225_write(dev, 0xe, 0x02B); msleep(1);
-       rtl8225_write(dev, 0xf, 0x114); msleep(100);
+       rtl8225_write(dev, 0x0, 0x0B7); mdelay(1);
+       rtl8225_write(dev, 0x1, 0xEE0); mdelay(1);
+       rtl8225_write(dev, 0x2, 0x44D); mdelay(1);
+       rtl8225_write(dev, 0x3, 0x441); mdelay(1);
+       rtl8225_write(dev, 0x4, 0x8C3); mdelay(1);
+       rtl8225_write(dev, 0x5, 0xC72); mdelay(1);
+       rtl8225_write(dev, 0x6, 0x0E6); mdelay(1);
+       rtl8225_write(dev, 0x7, 0x82A); mdelay(1);
+       rtl8225_write(dev, 0x8, 0x03F); mdelay(1);
+       rtl8225_write(dev, 0x9, 0x335); mdelay(1);
+       rtl8225_write(dev, 0xa, 0x9D4); mdelay(1);
+       rtl8225_write(dev, 0xb, 0x7BB); mdelay(1);
+       rtl8225_write(dev, 0xc, 0x850); mdelay(1);
+       rtl8225_write(dev, 0xd, 0xCDF); mdelay(1);
+       rtl8225_write(dev, 0xe, 0x02B); mdelay(1);
+       rtl8225_write(dev, 0xf, 0x114); mdelay(100);
 
        if (!(rtl8225_read(dev, 6) & (1 << 7))) {
                rtl8225_write(dev, 0x02, 0x0C4D);
-               msleep(200);
+               mdelay(200);
                rtl8225_write(dev, 0x02, 0x044D);
-               msleep(100);
+               mdelay(100);
                /* TODO: readd calibration failure message when the calibration
                   check works */
        }
@@ -591,12 +613,12 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
                rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
        }
 
-       rtl8225_write(dev, 0x0, 0x0B7); msleep(100);
+       rtl8225_write(dev, 0x0, 0x0B7); mdelay(100);
        rtl8225_write(dev, 0x2, 0xC4D);
 
-       msleep(200);
+       mdelay(200);
        rtl8225_write(dev, 0x2, 0x44D);
-       msleep(100);
+       mdelay(100);
 
        rtl8225_write(dev, 0x00, 0x2BF);
        rtl8225_write(dev, 0xFF, 0xFFFF);
@@ -605,103 +627,130 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
 
        for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
                rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
-               msleep(1);
+               mdelay(1);
                rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
-               msleep(1);
+               mdelay(1);
        }
 
-       msleep(1);
-
-       rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+       mdelay(1);
+
+       rtl8225_write_phy_ofdm(dev, 0x00, 0x01); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x01, 0x02); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x02, 0x62); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x03, 0x00); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x04, 0x00); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x05, 0x00); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x06, 0x40); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x07, 0x00); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x08, 0x40); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1);
        rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
-       rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x1b, 0x11); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x1e, 0xb3); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); /* FIXME: not needed? */
-       rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
-       rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
-
-       rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+       rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x10, 0x84); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x11, 0x06); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x12, 0x20); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x13, 0x20); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x14, 0x00); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x15, 0x40); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x16, 0x00); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x17, 0x40); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x18, 0xef); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x19, 0x19); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x1b, 0x11); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x1e, 0xb3); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x21, 0x27); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x22, 0x16); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x23, 0x80); mdelay(1); /* FIXME: not needed? */
+       rtl8225_write_phy_ofdm(dev, 0x24, 0x46); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x25, 0x20); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);
+       rtl8225_write_phy_ofdm(dev, 0x27, 0x88); mdelay(1);
+
+       rtl8225_write_phy_cck(dev, 0x00, 0x98); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x03, 0x20); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x04, 0x7e); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x05, 0x12); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x06, 0xfc); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x07, 0x78); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x08, 0x2e); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x10, 0x93); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x11, 0x88); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x12, 0x47); mdelay(1);
        rtl8225_write_phy_cck(dev, 0x13, 0xd0);
        rtl8225_write_phy_cck(dev, 0x19, 0x00);
        rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
        rtl8225_write_phy_cck(dev, 0x1b, 0x08);
        rtl8225_write_phy_cck(dev, 0x40, 0x86);
-       rtl8225_write_phy_cck(dev, 0x41, 0x8a); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
-       rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
-
-       rtl818x_iowrite8(priv, (u8 __iomem *)((void __iomem *)priv->map + 0x5B), 0x0D); msleep(1);
+       rtl8225_write_phy_cck(dev, 0x41, 0x8a); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x42, 0x15); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x43, 0x18); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x44, 0x36); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x45, 0x35); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x46, 0x2e); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x47, 0x25); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x48, 0x1c); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x49, 0x12); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x4a, 0x09); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x4b, 0x04); mdelay(1);
+       rtl8225_write_phy_cck(dev, 0x4c, 0x05); mdelay(1);
+
+       rtl818x_iowrite8(priv, (u8 *)priv->map + 0x5B, 0x0D); mdelay(1);
 
        rtl8225z2_rf_set_tx_power(dev, 1);
 
        /* RX antenna default to A */
-       rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);      /* B: 0xDB */
-       rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);     /* B: 0x10 */
+       rtl8225_write_phy_cck(dev, 0x10, 0x9b); mdelay(1);      /* B: 0xDB */
+       rtl8225_write_phy_ofdm(dev, 0x26, 0x90); mdelay(1);     /* B: 0x10 */
 
        rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);   /* B: 0x00 */
-       msleep(1);
-       rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002);
+       mdelay(1);
+       rtl818x_iowrite32(priv, (u32 *)((u8 *)priv->map + 0x94), 0x15c00002);
        rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
 }
 
-static void rtl8225_rf_stop(struct ieee80211_hw *dev)
+static void rtl8225x_rf_init(struct net80211_device *dev) 
+{
+       struct rtl8180_priv *priv = dev->priv;
+       u16 reg8, reg9;
+
+       rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
+       rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
+       rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+       rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+       mdelay(100);
+
+       rtl8225_write(dev, 0, 0x1B7);
+
+       reg8 = rtl8225_read(dev, 8);
+       reg9 = rtl8225_read(dev, 9);
+
+       rtl8225_write(dev, 0, 0x0B7);
+
+       if (reg8 != 0x588 || reg9 != 0x700) {
+               priv->rf_flag = 0;
+               rtl8225_rf_init(dev);
+       } else {
+               priv->rf_flag = 1;
+               rtl8225z2_rf_init(dev);
+       }
+}
+
+static void rtl8225_rf_stop(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
        u8 reg;
 
-       rtl8225_write(dev, 0x4, 0x1f); msleep(1);
+       rtl8225_write(dev, 0x4, 0x1f); mdelay(1);
 
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
        reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
@@ -712,27 +761,26 @@ static void rtl8225_rf_stop(struct ieee80211_hw *dev)
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
 }
 
-static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
-                                  struct ieee80211_conf *conf)
+static void rtl8225_rf_set_channel(struct net80211_device *dev,
+                                  struct net80211_channel *channelp)
 {
        struct rtl8180_priv *priv = dev->priv;
-       int chan = ieee80211_frequency_to_channel(conf->channel->center_freq);
+       int chan = channelp->channel_nr;
 
-       if (priv->rf->init == rtl8225_rf_init)
-               rtl8225_rf_set_tx_power(dev, chan);
-       else
+       if (priv->rf_flag)
                rtl8225z2_rf_set_tx_power(dev, chan);
+       else
+               rtl8225_rf_set_tx_power(dev, chan);
 
        rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
-       msleep(10);
+       mdelay(10);
 }
 
-static void rtl8225_rf_conf_erp(struct ieee80211_hw *dev,
-                               struct ieee80211_bss_conf *info)
+static void rtl8225_rf_conf_erp(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
 
-       if (info->use_short_slot) {
+       if (dev->erp_flags & NET80211_ERP_USE_SHORT_SLOT) {
                rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
                rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
                rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
@@ -747,42 +795,12 @@ static void rtl8225_rf_conf_erp(struct ieee80211_hw *dev,
        }
 }
 
-static const struct rtl818x_rf_ops rtl8225_ops = {
+struct rtl818x_rf_ops rtl8225_ops __rtl818x_rf_driver = {
        .name           = "rtl8225",
-       .init           = rtl8225_rf_init,
-       .stop           = rtl8225_rf_stop,
-       .set_chan       = rtl8225_rf_set_channel,
-       .conf_erp       = rtl8225_rf_conf_erp,
-};
-
-static const struct rtl818x_rf_ops rtl8225z2_ops = {
-       .name           = "rtl8225z2",
-       .init           = rtl8225z2_rf_init,
+       .id             = 10,
+       .init           = rtl8225x_rf_init,
        .stop           = rtl8225_rf_stop,
        .set_chan       = rtl8225_rf_set_channel,
        .conf_erp       = rtl8225_rf_conf_erp,
 };
 
-const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev)
-{
-       struct rtl8180_priv *priv = dev->priv;
-       u16 reg8, reg9;
-
-       rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
-       rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
-       rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
-       rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
-       msleep(100);
-
-       rtl8225_write(dev, 0, 0x1B7);
-
-       reg8 = rtl8225_read(dev, 8);
-       reg9 = rtl8225_read(dev, 9);
-
-       rtl8225_write(dev, 0, 0x0B7);
-
-       if (reg8 != 0x588 || reg9 != 0x700)
-               return &rtl8225_ops;
-
-       return &rtl8225z2_ops;
-}
diff --git a/src/drivers/net/rtl818x/rtl8180_rtl8225.h b/src/drivers/net/rtl818x/rtl8180_rtl8225.h
deleted file mode 100644 (file)
index 310013a..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef RTL8180_RTL8225_H
-#define RTL8180_RTL8225_H
-
-#define RTL8225_ANAPARAM_ON    0xa0000b59
-#define RTL8225_ANAPARAM2_ON   0x860dec11
-#define RTL8225_ANAPARAM_OFF   0xa00beb59
-#define RTL8225_ANAPARAM2_OFF  0x840dec11
-
-const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *);
-
-static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
-                                         u8 addr, u8 data)
-{
-       rtl8180_write_phy(dev, addr, data);
-}
-
-static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev,
-                                        u8 addr, u8 data)
-{
-       rtl8180_write_phy(dev, addr, data | 0x10000);
-}
-
-#endif /* RTL8180_RTL8225_H */
index cea4e0c..fccfdfe 100644 (file)
@@ -4,6 +4,8 @@
  *
  * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
  *
+ * Modified slightly for gPXE, June 2009 by Joshua Oreman.
+ *
  * Code from the BSD driver and the rtl8181 project have been
  * very useful to understand certain things
  *
  * published by the Free Software Foundation.
  */
 
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <net/mac80211.h>
+#include <unistd.h>
+#include <gpxe/pci.h>
+#include <gpxe/net80211.h>
 
 #include "rtl8180.h"
-#include "rtl8180_sa2400.h"
+
+FILE_LICENCE(GPL2_ONLY);
+
+#define SA2400_ANTENNA 0x91
+#define SA2400_DIG_ANAPARAM_PWR1_ON 0x8
+#define SA2400_ANA_ANAPARAM_PWR1_ON 0x28
+#define SA2400_ANAPARAM_PWR0_ON 0x3
+
+/* RX sensitivity in dbm */
+#define SA2400_MAX_SENS 85
+
+#define SA2400_REG4_FIRDAC_SHIFT 7
 
 static const u32 sa2400_chan[] = {
        0x00096c, /* ch1 */
@@ -44,7 +56,7 @@ static const u32 sa2400_chan[] = {
        0x0009b4, /* ch 14 */
 };
 
-static void write_sa2400(struct ieee80211_hw *dev, u8 addr, u32 data)
+static void write_sa2400(struct net80211_device *dev, u8 addr, u32 data)
 {
        struct rtl8180_priv *priv = dev->priv;
        u32 phy_config;
@@ -55,13 +67,15 @@ static void write_sa2400(struct ieee80211_hw *dev, u8 addr, u32 data)
        phy_config |= ((u32)(addr & 0xf)) << 24;
        phy_config |= data & 0xffffff;
 
-       rtl818x_iowrite32(priv,
-               (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config);
+       /* This was originally a 32-bit write to a typecast
+          RFPinsOutput, but gcc complained about aliasing rules. -JBO */
+       rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, phy_config & 0xffff);
+       rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, phy_config >> 16);
 
-       msleep(3);
+       mdelay(3);
 }
 
-static void sa2400_write_phy_antenna(struct ieee80211_hw *dev, short chan)
+static void sa2400_write_phy_antenna(struct net80211_device *dev, short chan)
 {
        struct rtl8180_priv *priv = dev->priv;
        u8 ant = SA2400_ANTENNA;
@@ -76,12 +90,12 @@ static void sa2400_write_phy_antenna(struct ieee80211_hw *dev, short chan)
 
 }
 
-static void sa2400_rf_set_channel(struct ieee80211_hw *dev,
-                                 struct ieee80211_conf *conf)
+static void sa2400_rf_set_channel(struct net80211_device *dev,
+                                 struct net80211_channel *channelp)
 {
        struct rtl8180_priv *priv = dev->priv;
-       int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
-       u32 txpw = priv->channels[channel - 1].hw_value & 0xFF;
+       int channel = channelp->channel_nr;
+       u32 txpw = priv->txpower[channel - 1] & 0xFF;
        u32 chan = sa2400_chan[channel - 1];
 
        write_sa2400(dev, 7, txpw);
@@ -94,12 +108,12 @@ static void sa2400_rf_set_channel(struct ieee80211_hw *dev,
        write_sa2400(dev, 3, 0);
 }
 
-static void sa2400_rf_stop(struct ieee80211_hw *dev)
+static void sa2400_rf_stop(struct net80211_device *dev)
 {
        write_sa2400(dev, 4, 0);
 }
 
-static void sa2400_rf_init(struct ieee80211_hw *dev)
+static void sa2400_rf_init(struct net80211_device *dev)
 {
        struct rtl8180_priv *priv = dev->priv;
        u32 anaparam, txconf;
@@ -155,11 +169,12 @@ static void sa2400_rf_init(struct ieee80211_hw *dev)
 
                write_sa2400(dev, 4, 0x19341); /* calibrates DC */
 
-               /* a 5us sleep is required here,
+               /* a 5us delay is required here,
                 * we rely on the 3ms delay introduced in write_sa2400 */
+
                write_sa2400(dev, 4, 0x19345);
 
-               /* a 20us sleep is required here,
+               /* a 20us delay is required here,
                 * we rely on the 3ms delay introduced in write_sa2400 */
 
                rtl818x_iowrite32(priv, &priv->map->TX_CONF, txconf);
@@ -194,8 +209,9 @@ static void sa2400_rf_init(struct ieee80211_hw *dev)
        rtl8180_write_phy(dev, 0x1a, 0xa0);
 }
 
-const struct rtl818x_rf_ops sa2400_rf_ops = {
-       .name           = "Philips",
+struct rtl818x_rf_ops sa2400_rf_ops __rtl818x_rf_driver = {
+       .name           = "Philips SA2400",
+       .id             = 3,
        .init           = sa2400_rf_init,
        .stop           = sa2400_rf_stop,
        .set_chan       = sa2400_rf_set_channel
diff --git a/src/drivers/net/rtl818x/rtl8180_sa2400.h b/src/drivers/net/rtl818x/rtl8180_sa2400.h
deleted file mode 100644 (file)
index a4aaa0d..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef RTL8180_SA2400_H
-#define RTL8180_SA2400_H
-
-/*
- * Radio tuning for Philips SA2400 on RTL8180
- *
- * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
- *
- * Code from the BSD driver and the rtl8181 project have been
- * very useful to understand certain things
- *
- * I want to thanks the Authors of such projects and the Ndiswrapper
- * project Authors.
- *
- * A special Big Thanks also is for all people who donated me cards,
- * making possible the creation of the original rtl8180 driver
- * from which this code is derived!
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#define SA2400_ANTENNA 0x91
-#define SA2400_DIG_ANAPARAM_PWR1_ON 0x8
-#define SA2400_ANA_ANAPARAM_PWR1_ON 0x28
-#define SA2400_ANAPARAM_PWR0_ON 0x3
-
-/* RX sensitivity in dbm */
-#define SA2400_MAX_SENS 85
-
-#define SA2400_REG4_FIRDAC_SHIFT 7
-
-extern const struct rtl818x_rf_ops sa2400_rf_ops;
-
-#endif /* RTL8180_SA2400_H */
index 34a5555..cb81663 100644 (file)
@@ -4,6 +4,8 @@
  * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
  *
+ * Modified for gPXE, June 2009, by Joshua Oreman <oremanj@rwcr.net>
+ *
  * Based on the r8187 driver, which is:
  * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
  *
 #ifndef RTL818X_H
 #define RTL818X_H
 
+#include <gpxe/tables.h>
+
+FILE_LICENCE(GPL2_ONLY);
+
 struct rtl818x_csr {
        u8      MAC[6];
        u8      reserved_0[2];
-       __le32  MAR[2];
+       u32     MAR[2];
        u8      RX_FIFO_COUNT;
        u8      reserved_1;
        u8      TX_FIFO_COUNT;
        u8      BQREQ;
        u8      reserved_2[4];
-       __le32  TSFT[2];
-       __le32  TLPDA;
-       __le32  TNPDA;
-       __le32  THPDA;
-       __le16  BRSR;
+       u32     TSFT[2];
+       u32     TLPDA;
+       u32     TNPDA;
+       u32     THPDA;
+       u16     BRSR;
        u8      BSSID[6];
        u8      RESP_RATE;
        u8      EIFS;
@@ -38,8 +44,8 @@ struct rtl818x_csr {
 #define RTL818X_CMD_RX_ENABLE          (1 << 3)
 #define RTL818X_CMD_RESET              (1 << 4)
        u8      reserved_4[4];
-       __le16  INT_MASK;
-       __le16  INT_STATUS;
+       u16     INT_MASK;
+       u16     INT_STATUS;
 #define RTL818X_INT_RX_OK              (1 <<  0)
 #define RTL818X_INT_RX_ERR             (1 <<  1)
 #define RTL818X_INT_TXL_OK             (1 <<  2)
@@ -56,7 +62,7 @@ struct rtl818x_csr {
 #define RTL818X_INT_BEACON             (1 << 13)
 #define RTL818X_INT_TIME_OUT           (1 << 14)
 #define RTL818X_INT_TX_FO              (1 << 15)
-       __le32  TX_CONF;
+       u32     TX_CONF;
 #define RTL818X_TX_CONF_LOOPBACK_MAC   (1 << 17)
 #define RTL818X_TX_CONF_LOOPBACK_CONT  (3 << 17)
 #define RTL818X_TX_CONF_NO_ICV         (1 << 19)
@@ -73,7 +79,7 @@ struct rtl818x_csr {
 #define RTL818X_TX_CONF_PROBE_DTS      (1 << 29)
 #define RTL818X_TX_CONF_HW_SEQNUM      (1 << 30)
 #define RTL818X_TX_CONF_CW_MIN         (1 << 31)
-       __le32  RX_CONF;
+       u32     RX_CONF;
 #define RTL818X_RX_CONF_MONITOR                (1 <<  0)
 #define RTL818X_RX_CONF_NICMAC         (1 <<  1)
 #define RTL818X_RX_CONF_MULTICAST      (1 <<  2)
@@ -89,8 +95,8 @@ struct rtl818x_csr {
 #define RTL818X_RX_CONF_CSDM1          (1 << 29)
 #define RTL818X_RX_CONF_CSDM2          (1 << 30)
 #define RTL818X_RX_CONF_ONLYERLPKT     (1 << 31)
-       __le32  INT_TIMEOUT;
-       __le32  TBDA;
+       u32     INT_TIMEOUT;
+       u32     TBDA;
        u8      EEPROM_CMD;
 #define RTL818X_EEPROM_CMD_READ                (1 << 0)
 #define RTL818X_EEPROM_CMD_WRITE       (1 << 1)
@@ -104,7 +110,7 @@ struct rtl818x_csr {
        u8      CONFIG1;
        u8      CONFIG2;
 #define RTL818X_CONFIG2_ANTENNA_DIV    (1 << 6)
-       __le32  ANAPARAM;
+       u32     ANAPARAM;
        u8      MSR;
 #define RTL818X_MSR_NO_LINK            (0 << 2)
 #define RTL818X_MSR_ADHOC              (1 << 2)
@@ -121,26 +127,26 @@ struct rtl818x_csr {
        u8      reserved_9[2];
        u8      PGSELECT;
        u8      SECURITY;
-       __le32  ANAPARAM2;
+       u32     ANAPARAM2;
        u8      reserved_10[12];
-       __le16  BEACON_INTERVAL;
-       __le16  ATIM_WND;
-       __le16  BEACON_INTERVAL_TIME;
-       __le16  ATIMTR_INTERVAL;
+       u16     BEACON_INTERVAL;
+       u16     ATIM_WND;
+       u16     BEACON_INTERVAL_TIME;
+       u16     ATIMTR_INTERVAL;
        u8      PHY_DELAY;
        u8      CARRIER_SENSE_COUNTER;
        u8      reserved_11[2];
        u8      PHY[4];
-       __le16  RFPinsOutput;
-       __le16  RFPinsEnable;
-       __le16  RFPinsSelect;
-       __le16  RFPinsInput;
-       __le32  RF_PARA;
-       __le32  RF_TIMING;
+       u16     RFPinsOutput;
+       u16     RFPinsEnable;
+       u16     RFPinsSelect;
+       u16     RFPinsInput;
+       u32     RF_PARA;
+       u32     RF_TIMING;
        u8      GP_ENABLE;
        u8      GPIO;
        u8      reserved_12[2];
-       __le32  HSSI_PARA;
+       u32     HSSI_PARA;
        u8      reserved_13[4];
        u8      TX_AGC_CTL;
 #define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT                (1 << 0)
@@ -167,31 +173,35 @@ struct rtl818x_csr {
        u8      CONFIG5;
        u8      TX_DMA_POLLING;
        u8      reserved_18[2];
-       __le16  CWR;
+       u16     CWR;
        u8      RETRY_CTR;
        u8      reserved_19[3];
-       __le16  INT_MIG;
+       u16     INT_MIG;
 /* RTL818X_R8187B_*: magic numbers from ioregisters */
 #define RTL818X_R8187B_B       0
 #define RTL818X_R8187B_D       1
 #define RTL818X_R8187B_E       2
-       __le32  RDSAR;
-       __le16  TID_AC_MAP;
+       u32     RDSAR;
+       u16     TID_AC_MAP;
        u8      reserved_20[4];
        u8      ANAPARAM3;
        u8      reserved_21[5];
-       __le16  FEMR;
+       u16     FEMR;
        u8      reserved_22[4];
-       __le16  TALLY_CNT;
+       u16     TALLY_CNT;
        u8      TALLY_SEL;
 } __attribute__((packed));
 
+#define RTL818X_RF_DRIVERS __table(struct rtl818x_rf_ops, "rtl818x_rf_drivers")
+#define __rtl818x_rf_driver __table_entry(RTL818X_RF_DRIVERS, 01)
+
 struct rtl818x_rf_ops {
        char *name;
-       void (*init)(struct ieee80211_hw *);
-       void (*stop)(struct ieee80211_hw *);
-       void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *);
-       void (*conf_erp)(struct ieee80211_hw *, struct ieee80211_bss_conf *);
+       u8 id;                  /* as identified in EEPROM */
+       void (*init)(struct net80211_device *dev);
+       void (*stop)(struct net80211_device *dev);
+       void (*set_chan)(struct net80211_device *dev, struct net80211_channel *chan);
+       void (*conf_erp)(struct net80211_device *dev); /* set based on dev->erp_flags */
 };
 
 /* Tx/Rx flags are common between RTL818X chips */
index 7ca9c99..3a77113 100644 (file)
@@ -111,6 +111,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #define ERRFILE_ne2k_isa            ( ERRFILE_DRIVER | 0x004c0000 )
 #define ERRFILE_b44                 ( ERRFILE_DRIVER | 0x004d0000 )
 
+#define ERRFILE_rtl8180                     ( ERRFILE_DRIVER | 0x00500000 )
+
 #define ERRFILE_scsi                ( ERRFILE_DRIVER | 0x00700000 )
 #define ERRFILE_arbel               ( ERRFILE_DRIVER | 0x00710000 )
 #define ERRFILE_hermon              ( ERRFILE_DRIVER | 0x00720000 )