linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] rtl8187: Adding Realtek rtl8187B support
@ 2008-07-08  6:26 Hin-Tak Leung
  2008-07-08  6:30 ` [PATCH 1/6] " Hin-Tak Leung
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Hin-Tak Leung @ 2008-07-08  6:26 UTC (permalink / raw)
  To: linux-wireless, John W. Linville, flamingice, Andrea Merello
  Cc: Herton Ronaldo Krzesinski, Larry Finger, Pavel Roskin

There was a problem with the integrated patch posted by Pavel on May 22 -
for those who did not get good result, please retry; We identified some code
for detecting early 8187B's with an 8187 id which seems to have a weaker
chip and Larry is working on a 7th patch for it - people having 8187B's with an
0x8187 id should get in touch.

Each of the 6 passes checkpatch.pl, and compiles cleanly with wireless-testing 
head one after the other. The first two modifies the header files, the 3rd adds
radio routines. 4th and 5th modifies the main driver code and the division
is somewhat arbitrary; the 6th updates Kconfig.

---------
rtl8187: Adding Realtek rtl8187B support

Herton wrote most of this based on the Realtek vendor driver, with
contributions from John W. Linville and feedbacks from Pavel. Hin-Tak
fixed tranmission of management frames and got it to work. Pavel removed
procfs support and tidied up the patch. Larry split the patch into 6 parts.

HTL, 2008-07-01:
There is occasional problem with unloading - modprobe -r and ksoftirqd
takes up all CPU time (on x86_64, dual core).

HRK, 2008-04-09:
Rate control doesn't work for 8187b, for 8187 it never worked either.
If you set rate manually to something lower (I found that for 2-3 meters
from AP 11M seems to be the best setting) it works much better (there aren't
stalls/packet drops).

PR, 2008-05-22:
The driver loads and initializes the device successfully.  Bringing the
interface up is very slow (10 to 20 seconds), but it works.  Scanning
works, ... [Edited] Association to APs without encryption works ...
[Edited] Unloading the module is working.

Matthew Garrett wrote on 2008-06-23:
Some vendors are shipping 8187bs with the 0x8187 product id, so the driver
really needs to probe rather than having a static setup of which is which.

Hauke Mehrtens wrote on 2008-01-12 regarding 8187 rate control:
If the rate goes over 11M no TCP/IP traffic goes through the wireless
connecting. If rate is set to auto and the rate control algorithm changes
it to something less than 11M TCP/IP traffic goes through, but if it is more
than 11M no TCP/IP traffic goes through the wireless link. With
"iwconfig wlan0 rate 11M" everything works.

Michael Wu wrote on 6 Nov 2007 on 8187 rate control:
.... you can find the specs for the 8186 floating around on the net
which tells you a bit about the registers. Doesn't tell you anything about
the rx/tx path of the usb variant, which is a bit inferior to the rx/tx path
of the pci chips. There's no easy way to do tx ack reporting on the rtl8187.
The only solutions that could work involve some polling or a different rate
control algorithm.



^ permalink raw reply	[flat|nested] 10+ messages in thread
* [PATCH 5/6] rtl8187: change part 2 of rtl8187_dev.c to support RTL8187B
@ 2008-07-08 11:36 Hin-Tak Leung
  0 siblings, 0 replies; 10+ messages in thread
From: Hin-Tak Leung @ 2008-07-08 11:36 UTC (permalink / raw)
  To: linux-wireless, linville, flamingice, andreamrl
  Cc: herton, Larry.Finger, proski

rtl8187: change part 2 of rtl8187_dev.c to support RTL8187B

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
Signed-off-by: Hin-Tak Leung <htl10@users.sourceforge.net>
Signed-off-by: Pavel Roskin <proski@gnu.org>
---
diff --git a/drivers/net/wireless/rtl8187_dev.c
b/drivers/net/wireless/rtl8187_dev.c
index b17f237..e013eee 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -155,9 +155,11 @@ static void rtl8187_tx_cb(struct urb *urb)
 	struct sk_buff *skb = (struct sk_buff *)urb->context;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_hw *hw = info->driver_data[0];
+	struct rtl8187_priv *priv = hw->priv;

 	usb_free_urb(info->driver_data[1]);
-	skb_pull(skb, sizeof(struct rtl8187_tx_hdr));
+	skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) :
+					  sizeof(struct rtl8187_tx_hdr));
 	memset(&info->status, 0, sizeof(info->status));
 	info->flags |= IEEE80211_TX_STAT_ACK;
 	ieee80211_tx_status_irqsafe(hw, skb);
@@ -167,7 +169,8 @@ static int rtl8187_tx(struct ieee80211_hw *dev,
struct sk_buff *skb)
 {
 	struct rtl8187_priv *priv = dev->priv;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct rtl8187_tx_hdr *hdr;
+	unsigned int ep;
+	void *buf;
 	struct urb *urb;
 	__le16 rts_dur = 0;
 	u32 flags;
@@ -195,16 +198,47 @@ static int rtl8187_tx(struct ieee80211_hw *dev,
struct sk_buff *skb)
 		flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
 	}

-	hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
-	hdr->flags = cpu_to_le32(flags);
-	hdr->len = 0;
-	hdr->rts_duration = rts_dur;
-	hdr->retry = cpu_to_le32(info->control.retry_limit << 8);
+	if (!priv->is_rtl8187b) {
+		struct rtl8187_tx_hdr *hdr =
+			(struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr));
+		hdr->flags = cpu_to_le32(flags);
+		hdr->len = 0;
+		hdr->rts_duration = rts_dur;
+		hdr->retry = cpu_to_le32(info->control.retry_limit << 8);
+		buf = hdr;
+
+		ep = 2;
+	} else {
+		/* fc needs to be calculated before skb_push() */
+		unsigned int epmap[4] = { 6, 7, 5, 4 };
+		struct ieee80211_hdr *tx_hdr =
+			(struct ieee80211_hdr *)(skb->data);
+		u16 fc = le16_to_cpu(tx_hdr->frame_control);
+
+		struct rtl8187b_tx_hdr *hdr =
+			(struct rtl8187b_tx_hdr *)skb_push(skb, sizeof(*hdr));
+		struct ieee80211_rate *txrate =
+			ieee80211_get_tx_rate(dev, info);
+		memset(hdr, 0, sizeof(*hdr));
+		hdr->flags = cpu_to_le32(flags);
+		hdr->rts_duration = rts_dur;
+		hdr->retry = cpu_to_le32(info->control.retry_limit << 8);
+		hdr->tx_duration =
+			ieee80211_generic_frame_duration(dev, priv->vif,
+							 skb->len, txrate);
+		buf = hdr;
+
+		if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)
+			ep = 12;
+		else
+			ep = epmap[skb_get_queue_mapping(skb)];
+	}

 	info->driver_data[0] = dev;
 	info->driver_data[1] = urb;
-	usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2),
-			  hdr, skb->len, rtl8187_tx_cb, skb);
+
+	usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep),
+			  buf, skb->len, rtl8187_tx_cb, skb);
 	rc = usb_submit_urb(urb, GFP_ATOMIC);
 	if (rc < 0) {
 		usb_free_urb(urb);
@@ -220,7 +254,6 @@ static void rtl8187_rx_cb(struct urb *urb)
 	struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb;
 	struct ieee80211_hw *dev = info->dev;
 	struct rtl8187_priv *priv = dev->priv;
-	struct rtl8187_rx_hdr *hdr;
 	struct ieee80211_rx_status rx_status = { 0 };
 	int rate, signal;
 	u32 flags;
@@ -241,11 +274,33 @@ static void rtl8187_rx_cb(struct urb *urb)
 	}

 	skb_put(skb, urb->actual_length);
-	hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr));
-	flags = le32_to_cpu(hdr->flags);
-	skb_trim(skb, flags & 0x0FFF);
+	if (!priv->is_rtl8187b) {
+		struct rtl8187_rx_hdr *hdr =
+			(typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
+		flags = le32_to_cpu(hdr->flags);
+		signal = hdr->signal & 0x7f;
+		rx_status.antenna = (hdr->signal >> 7) & 1;
+		rx_status.signal = signal;
+		rx_status.noise = hdr->noise;
+		rx_status.mactime = le64_to_cpu(hdr->mac_time);
+		priv->signal = signal;
+		priv->quality = signal;
+		priv->noise = hdr->noise;
+	} else {
+		struct rtl8187b_rx_hdr *hdr =
+			(typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
+		flags = le32_to_cpu(hdr->flags);
+		signal = hdr->agc >> 1;
+		rx_status.antenna = (hdr->signal >> 7) & 1;
+		rx_status.signal = 64 - min(hdr->noise, (u8)64);
+		rx_status.noise = hdr->noise;
+		rx_status.mactime = le64_to_cpu(hdr->mac_time);
+		priv->signal = hdr->signal;
+		priv->quality = hdr->agc >> 1;
+		priv->noise = hdr->noise;
+	}

-	signal = hdr->agc >> 1;
+	skb_trim(skb, flags & 0x0FFF);
 	rate = (flags >> 20) & 0xF;
 	if (rate > 3) {	/* OFDM rate */
 		if (signal > 90)
@@ -261,13 +316,11 @@ static void rtl8187_rx_cb(struct urb *urb)
 		signal = 95 - signal;
 	}

-	rx_status.antenna = (hdr->signal >> 7) & 1;
-	rx_status.qual = 64 - min(hdr->noise, (u8)64);
+	rx_status.qual = priv->quality;
 	rx_status.signal = signal;
 	rx_status.rate_idx = rate;
 	rx_status.freq = dev->conf.channel->center_freq;
 	rx_status.band = dev->conf.channel->band;
-	rx_status.mactime = le64_to_cpu(hdr->mac_time);
 	rx_status.flag |= RX_FLAG_TSFT;
 	if (flags & (1 << 13))
 		rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
@@ -307,7 +360,8 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev)
 			break;
 		}
 		usb_fill_bulk_urb(entry, priv->udev,
-				  usb_rcvbulkpipe(priv->udev, 1),
+				  usb_rcvbulkpipe(priv->udev,
+				  priv->is_rtl8187b ? 3 : 1),
 				  skb_tail_pointer(skb),
 				  RTL8187_MAX_RX, rtl8187_rx_cb, skb);
 		info = (struct rtl8187_rx_info *)skb->cb;
@@ -786,18 +840,20 @@ static int rtl8187_config(struct ieee80211_hw
*dev, struct ieee80211_conf *conf)
 	msleep(10);
 	rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);

-	rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
-
-	if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
-		rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
-		rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
-		rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
-		rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
-	} else {
-		rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
-		rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
-		rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
-		rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
+	if (!priv->is_rtl8187b) {
+		rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
+
+		if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
+			rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
+			rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
+			rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
+			rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
+		} else {
+			rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
+			rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
+			rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
+			rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
+		}
 	}

 	rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
@@ -813,14 +869,20 @@ static int rtl8187_config_interface(struct
ieee80211_hw *dev,
 {
 	struct rtl8187_priv *priv = dev->priv;
 	int i;
+	u8 reg;

 	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);
+	if (is_valid_ether_addr(conf->bssid)) {
+		reg = RTL818X_MSR_INFRA;
+		if (priv->is_rtl8187b)
+			reg |= RTL818X_MSR_ENEDCA;
+		rtl818x_iowrite8(priv, &priv->map->MSR, reg);
+	} else {
+		reg = RTL818X_MSR_NO_LINK;
+		rtl818x_iowrite8(priv, &priv->map->MSR, reg);
+	}

 	return 0;
 }
@@ -907,6 +969,7 @@ static int __devinit rtl8187_probe(struct
usb_interface *intf,
 	struct rtl8187_priv *priv;
 	struct eeprom_93cx6 eeprom;
 	struct ieee80211_channel *channel;
+	const char *chip_name;
 	u16 txpwr, reg;
 	int err, i;
 	DECLARE_MAC_BUF(mac);
@@ -918,6 +981,8 @@ static int __devinit rtl8187_probe(struct
usb_interface *intf,
 	}

 	priv = dev->priv;
+	priv->is_rtl8187b = (id->driver_info == DEVICE_RTL8187B) ||
+			    !memcmp(udev->product, "RTL8187B", 8);

 	SET_IEEE80211_DEV(dev, &intf->dev);
 	usb_set_intfdata(intf, dev);
@@ -946,8 +1011,13 @@ static int __devinit rtl8187_probe(struct
usb_interface *intf,
 	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 		     IEEE80211_HW_RX_INCLUDES_FCS |
 		     IEEE80211_HW_SIGNAL_UNSPEC;
-	dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr);
-	dev->queues = 1;
+	dev->extra_tx_headroom = (!priv->is_rtl8187b) ?
+				  sizeof(struct rtl8187_tx_hdr) :
+				  sizeof(struct rtl8187b_tx_hdr);
+	if (!priv->is_rtl8187b)
+		dev->queues = 1;
+	else
+		dev->queues = 4;
 	dev->max_signal = 65;

 	eeprom.data = dev;
@@ -982,10 +1052,24 @@ static int __devinit rtl8187_probe(struct
usb_interface *intf,
 		(*channel++).hw_value = txpwr & 0xFF;
 		(*channel++).hw_value = txpwr >> 8;
 	}
-	for (i = 0; i < 2; i++) {
-		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i,
+	if (!priv->is_rtl8187b) {
+		for (i = 0; i < 2; i++) {
+			eeprom_93cx6_read(&eeprom,
+					  RTL8187_EEPROM_TXPWR_CHAN_6 + i,
+					  &txpwr);
+			(*channel++).hw_value = txpwr & 0xFF;
+			(*channel++).hw_value = txpwr >> 8;
+		}
+	} else {
+		eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6,
 				  &txpwr);
 		(*channel++).hw_value = txpwr & 0xFF;
+
+		eeprom_93cx6_read(&eeprom, 0x0A, &txpwr);
+		(*channel++).hw_value = txpwr & 0xFF;
+
+		eeprom_93cx6_read(&eeprom, 0x1C, &txpwr);
+		(*channel++).hw_value = txpwr & 0xFF;
 		(*channel++).hw_value = txpwr >> 8;
 	}

@@ -1001,6 +1085,50 @@ static int __devinit rtl8187_probe(struct
usb_interface *intf,
 	rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
 	rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);

+	if (!priv->is_rtl8187b) {
+		u32 reg32;
+		reg32 = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+		reg32 &= RTL818X_TX_CONF_HWVER_MASK;
+		switch (reg32) {
+		case RTL818X_TX_CONF_R8187vD_1:
+		case RTL818X_TX_CONF_R8187vD_2:
+			chip_name = "RTL8187vD";
+			break;
+		default:
+			chip_name = "RTL8187vB (default)";
+		}
+       } else {
+		printk(KERN_WARNING "rtl8187: 8187B chip detected. Support "
+			"is EXPERIMENTAL, and could damage your\n"
+			"         hardware, use at your own risk\n");
+		/*
+		 * Force USB request to write radio registers for 8187B, Realtek
+		 * only uses it in their sources
+		 */
+		/*if (priv->asic_rev == 0) {
+			printk(KERN_WARNING "rtl8187: Forcing use of USB "
+			       "requests to write to radio registers\n");
+			priv->asic_rev = 1;
+		}*/
+		switch (rtl818x_ioread8(priv, (u8 *)0xFFE1)) {
+		case RTL818X_R8187B_B:
+			chip_name = "RTL8187BvB";
+			priv->hw_rev = RTL8187BvB;
+			break;
+		case RTL818X_R8187B_D:
+			chip_name = "RTL8187BvD";
+			priv->hw_rev = RTL8187BvD;
+			break;
+		case RTL818X_R8187B_E:
+			chip_name = "RTL8187BvE";
+			priv->hw_rev = RTL8187BvE;
+			break;
+		default:
+			chip_name = "RTL8187BvB (default)";
+			priv->hw_rev = RTL8187BvB;
+		}
+	}
+
 	priv->rf = rtl8187_detect_rf(dev);

 	err = ieee80211_register_hw(dev);
@@ -1009,9 +1137,9 @@ static int __devinit rtl8187_probe(struct
usb_interface *intf,
 		goto err_free_dev;
 	}

-	printk(KERN_INFO "%s: hwaddr %s, rtl8187 V%d + %s\n",
+	printk(KERN_INFO "%s: hwaddr %s, %s V%d + %s\n",
 	       wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
-	       priv->asic_rev, priv->rf->name);
+	       chip_name, priv->asic_rev, priv->rf->name);

 	return 0;

^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH 1/6] rtl8187: updating rtl8187.h to support RTL8187B
@ 2008-07-08 16:18 Hin-Tak Leung
  2008-07-08 16:18 ` [PATCH 2/6] rtl8187: updating rtl818x.h " Hin-Tak Leung
  0 siblings, 1 reply; 10+ messages in thread
From: Hin-Tak Leung @ 2008-07-08 16:18 UTC (permalink / raw)
  To: linux-wireless, linville
  Cc: Hin-Tak Leung, Larry Finger, Herton Ronaldo Krzesinski,
	Hin-Tak Leung, Pavel Roskin

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
Signed-off-by: Hin-Tak Leung <htl10@users.sourceforge.net>
Signed-off-by: Pavel Roskin <proski@gnu.org>
---
 drivers/net/wireless/rtl8187.h |  113 ++++++++++++++++++++++++++++++++++------
 1 files changed, 97 insertions(+), 16 deletions(-)

diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
index a0cfb66..3afb49f 100644
--- a/drivers/net/wireless/rtl8187.h
+++ b/drivers/net/wireless/rtl8187.h
@@ -44,17 +44,48 @@ struct rtl8187_rx_hdr {
 	__le64 mac_time;
 } __attribute__((packed));
 
-struct rtl8187_tx_hdr {
+struct rtl8187b_rx_hdr {
 	__le32 flags;
+	__le64 mac_time;
+	u8 noise;
+	u8 signal;
+	u8 agc;
+	u8 reserved;
+	__le32 unused;
+} __attribute__((packed));
+
+/* {rtl8187,rtl8187b}_tx_info is in skb */
+
+/* Tx flags are common between rtl8187 and rtl8187b */
 #define RTL8187_TX_FLAG_NO_ENCRYPT	(1 << 15)
 #define RTL8187_TX_FLAG_MORE_FRAG	(1 << 17)
 #define RTL8187_TX_FLAG_CTS		(1 << 18)
 #define RTL8187_TX_FLAG_RTS		(1 << 23)
+
+struct rtl8187_tx_hdr {
+	__le32 flags;
 	__le16 rts_duration;
 	__le16 len;
 	__le32 retry;
 } __attribute__((packed));
 
+struct rtl8187b_tx_hdr {
+	__le32 flags;
+	__le16 rts_duration;
+	__le16 len;
+	__le32 unused_1;
+	__le16 unused_2;
+	__le16 tx_duration;
+	__le32 unused_3;
+	__le32 retry;
+	__le32 unused_4[2];
+} __attribute__((packed));
+
+enum {
+	DEVICE_RTL8187,
+	DEVICE_RTL8187B
+};
+
 struct rtl8187_priv {
 	/* common between rtl818x drivers */
 	struct rtl818x_csr *map;
@@ -70,70 +101,120 @@ struct rtl8187_priv {
 	u32 rx_conf;
 	u16 txpwr_base;
 	u8 asic_rev;
+	u8 is_rtl8187b;
+	enum {
+		RTL8187BvB,
+		RTL8187BvD,
+		RTL8187BvE
+	} hw_rev;
 	struct sk_buff_head rx_queue;
+	u8 signal;
+	u8 quality;
+	u8 noise;
 };
 
 void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
 
-static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr)
+static inline u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv,
+				     u8 *addr, u8 idx)
 {
 	u8 val;
 
 	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
 			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
-			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+			(unsigned long)addr, idx & 0x03, &val,
+			sizeof(val), HZ / 2);
 
 	return val;
 }
 
-static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr)
+static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr)
+{
+	return rtl818x_ioread8_idx(priv, addr, 0);
+}
+
+static inline u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv,
+				       __le16 *addr, u8 idx)
 {
 	__le16 val;
 
 	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
 			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
-			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+			(unsigned long)addr, idx & 0x03, &val,
+			sizeof(val), HZ / 2);
 
 	return le16_to_cpu(val);
 }
 
-static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr)
+static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr)
+{
+	return rtl818x_ioread16_idx(priv, addr, 0);
+}
+
+static inline u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv,
+				       __le32 *addr, u8 idx)
 {
 	__le32 val;
 
 	usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
 			RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
-			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+			(unsigned long)addr, idx & 0x03, &val,
+			sizeof(val), HZ / 2);
 
 	return le32_to_cpu(val);
 }
 
-static inline void rtl818x_iowrite8(struct rtl8187_priv *priv,
-				    u8 *addr, u8 val)
+static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr)
+{
+	return rtl818x_ioread32_idx(priv, addr, 0);
+}
+
+static inline void rtl818x_iowrite8_idx(struct rtl8187_priv *priv,
+					u8 *addr, u8 val, u8 idx)
 {
 	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
 			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
-			(unsigned long)addr, 0, &val, sizeof(val), HZ / 2);
+			(unsigned long)addr, idx & 0x03, &val,
+			sizeof(val), HZ / 2);
+}
+
+static inline void rtl818x_iowrite8(struct rtl8187_priv *priv, u8 *addr, u8 val)
+{
+	rtl818x_iowrite8_idx(priv, addr, val, 0);
 }
 
-static inline void rtl818x_iowrite16(struct rtl8187_priv *priv,
-				     __le16 *addr, u16 val)
+static inline void rtl818x_iowrite16_idx(struct rtl8187_priv *priv,
+					 __le16 *addr, u16 val, u8 idx)
 {
 	__le16 buf = cpu_to_le16(val);
 
 	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
 			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
-			(unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
+			(unsigned long)addr, idx & 0x03, &buf, sizeof(buf),
+			HZ / 2);
 }
 
-static inline void rtl818x_iowrite32(struct rtl8187_priv *priv,
-				     __le32 *addr, u32 val)
+static inline void rtl818x_iowrite16(struct rtl8187_priv *priv, __le16 *addr,
+				     u16 val)
+{
+	rtl818x_iowrite16_idx(priv, addr, val, 0);
+}
+
+static inline void rtl818x_iowrite32_idx(struct rtl8187_priv *priv,
+					 __le32 *addr, u32 val, u8 idx)
 {
 	__le32 buf = cpu_to_le32(val);
 
 	usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
 			RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
-			(unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2);
+			(unsigned long)addr, idx & 0x03, &buf, sizeof(buf),
+			HZ / 2);
+}
+
+static inline void rtl818x_iowrite32(struct rtl8187_priv *priv, __le32 *addr,
+				     u32 val)
+{
+	rtl818x_iowrite32_idx(priv, addr, val, 0);
 }
 
 #endif /* RTL8187_H */
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2008-07-08 16:20 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-08  6:26 [PATCH 0/6] rtl8187: Adding Realtek rtl8187B support Hin-Tak Leung
2008-07-08  6:30 ` [PATCH 1/6] " Hin-Tak Leung
2008-07-08  6:38 ` [PATCH 1/6] rtl8187: updating rtl8187.h to support RTL8187B Hin-Tak Leung
2008-07-08  6:41 ` [PATCH 2/6] rtl8187: updating rtl818x.h " Hin-Tak Leung
2008-07-08  6:46 ` [PATCH 3/6] rtl8187: updating rtl8187_rtl8225.c " Hin-Tak Leung
2008-07-08  6:52 ` [PATCH 4/6] rtl8187: change part 1 of rtl8187_dev.c " Hin-Tak Leung
2008-07-08  6:54 ` [PATCH 5/6] rtl8187: change part 2 " Hin-Tak Leung
2008-07-08  6:57 ` [PATCH 6/6] rtl8187: updating Kconfig " Hin-Tak Leung
  -- strict thread matches above, loose matches on Subject: below --
2008-07-08 11:36 [PATCH 5/6] rtl8187: change part 2 of rtl8187_dev.c " Hin-Tak Leung
2008-07-08 16:18 [PATCH 1/6] rtl8187: updating rtl8187.h " Hin-Tak Leung
2008-07-08 16:18 ` [PATCH 2/6] rtl8187: updating rtl818x.h " Hin-Tak Leung
2008-07-08 16:18   ` [PATCH 3/6] rtl8187: updating rtl8187_rtl8225.c " Hin-Tak Leung
2008-07-08 16:18     ` [PATCH 4/6] rtl8187: change part 1 of rtl8187_dev.c " Hin-Tak Leung
2008-07-08 16:18       ` [PATCH 5/6] rtl8187: change part 2 " Hin-Tak Leung

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).