Datel XBox 360 adapter

Tobias Diedrich ranma+ath9k_htc_fw at tdiedrich.de
Mon Jun 5 11:22:11 PDT 2017


Oleksij Rempel wrote:
> Am 20.05.2017 um 23:03 schrieb Tobias Diedrich:
> > Any suggestions on how to hook this up more properly instead of this hack?
> 
> First of all thank you for your work! :)
> 
> I would assume, adding a quirk will be the way to go.
> > 
> > Hacky patch to read the ath9k eeprom data from the memory-mapped PSI flash instead of the actual EEPROM:
> > 
> > --- a/drivers/net/wireless/ath/ath9k/hif_usb.c
> > +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
> > @@ -57,6 +57,8 @@ static struct usb_device_id ath9k_hif_us
> >  	  .driver_info = AR9280_USB },
> >  	{ USB_DEVICE(0x0930, 0x0a08),
> >  	  .driver_info = AR9280_USB },  /* Toshiba WLM-20U2 and GN-1080 */
> > +	{ USB_DEVICE(0x045e, 0x02a8),
> > +	  .driver_info = AR9280_USB },  /* Datel Xbox 360 */
> 
> For example:
> 	.driver_info = AR9280_USB_SPI

I've decided to split the driver_info field into a flags area and
the device id area.
Also I think this is an opportunity to remove the multi-read hack from eeprom*.
It seems cleaner to just do the eeprom read in htc_drv_init.c.
I'm now storing it in the struct firmware eeprom_blob (which is a
bit hacky in itself, but better than the current solution IMO).


--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -57,6 +57,8 @@ static struct usb_device_id ath9k_hif_us
 	  .driver_info = AR9280_USB },
 	{ USB_DEVICE(0x0930, 0x0a08),
 	  .driver_info = AR9280_USB },  /* Toshiba WLM-20U2 and GN-1080 */
+	{ USB_DEVICE(0x045e, 0x02a8),   /* MS (or Datel) Xbox 360 Adapter */
+	  .driver_info = AR9280_USB | AR_USB_SPI_EEPROM },
 
 	{ USB_DEVICE(0x0cf3, 0x20ff),
 	  .driver_info = STORAGE_DEVICE },
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -518,22 +518,120 @@ static void ath_usb_read_cachesize(struc
 	*csz = L1_CACHE_BYTES >> 2;
 }
 
+static int ath_usb_spi_eeprom_fillblob(struct ath_hw *ah, struct firmware *blob)
+{
+	int i = 0, j, addr;
+	u32 base = AR7010_SPI_EEPROM_BASE;
+	u32 size = blob->size;
+	u32 addrdata[8];
+	u32 data[8];
+	u16 *eep_data = (void*) blob->data;
+
+	for (addr = 0; addr < size; addr += 4) {
+		addrdata[i] = base + addr;
+		i++;
+		if (i == 8 || addr == size - 4) {
+			REG_READ_MULTI(ah, addrdata, data, i);
+
+			for (j = 0; j < i; j++) {
+				u32 word = be32_to_cpu(data[j]);
+				*eep_data = word >> 16;
+				eep_data++;
+				*eep_data = word;
+				eep_data++;
+			}
+			i = 0;
+		}
+	}
+	return 0;
+}
+
+static int ath_usb_ar928x_eeprom_fillblob(struct ath_hw *ah, struct firmware *blob)
+{
+	int i = 0, j, addr;
+	u32 size = blob->size / 2;
+	u16 *eep_data = (void*) blob->data;
+	u32 addrdata[8];
+	u32 data[8];
+
+	for (addr = 0; addr < size; addr++) {
+		addrdata[i] = AR5416_EEPROM_OFFSET + (addr << AR5416_EEPROM_S);
+		i++;
+		if (i == 8 || addr == size - 1) {
+			REG_READ_MULTI(ah, addrdata, data, i);
+
+			for (j = 0; j < i; j++) {
+				*eep_data = data[j];
+				eep_data++;
+			}
+			i = 0;
+		}
+	}
+
+	return 0;
+}
+
+static int ath_usb_eeprom_fillblob(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct firmware *blob;
+	int size = AR7010_EEPROM_SIZE_MAX;
+	int ret;
+
+	blob = kzalloc(sizeof(*blob) + size, GFP_KERNEL);
+	if (!blob) {
+		ath_err(common, "Failed to allocate blob memory\n");
+		return -ENOMEM;
+	}
+
+	blob->size = size;
+	blob->data = ((void*)blob) + sizeof(*blob);
+
+	if (ah->hw_version.usbflags & AR_USB_SPI_EEPROM) {
+		/* Read from last 4K of SPI flash (mapped at 0x0f07f000) */
+		ret = ath_usb_spi_eeprom_fillblob(ah, blob);
+	} else {
+		/* Read from EEPROM attached to AR9280/AR9287. */
+		ret = ath_usb_ar928x_eeprom_fillblob(ah, blob);
+	}
+
+	if (ret) {
+		kfree(blob);
+		return ret;
+	}
+
+	ah->eeprom_blob = blob;
+	return 0;
+}
+
 static bool ath_usb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
 {
 	struct ath_hw *ah = (struct ath_hw *) common->ah;
+	int ret;
+	u16 *blob_data;
 
-	(void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
+	if (ah->eeprom_blob) {
+		ath_err(common, "Invalid state: eeprom_blob already exists");
+		return false;
+	}
 
-	if (!ath9k_hw_wait(ah,
-			   AR_EEPROM_STATUS_DATA,
-			   AR_EEPROM_STATUS_DATA_BUSY |
-			   AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0,
-			   AH_WAIT_TIMEOUT))
+	ret = ath_usb_eeprom_fillblob(ah);
+	if (ret || !ah->eeprom_blob) {
+		ath_err(common, "Unable to fill eeprom data: %d\n", ret);
 		return false;
+	}
 
-	*data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
-		   AR_EEPROM_STATUS_DATA_VAL);
+	if (off > (ah->eeprom_blob->size / sizeof(*blob_data)))
+		return false;
+
+	blob_data = (void*) ah->eeprom_blob->data;
+	if (blob_data[0] != 0xa55a &&
+	    blob_data[0] != 0x5aa5) {
+		ath_err(common, "Bad eeprom magic: %04x\n", blob_data[0]);
+		return false;
+	}
 
+	*data = blob_data[off];
 	return true;
 }
 
@@ -620,7 +718,8 @@ static int ath9k_init_priv(struct ath9k_
 	ah->dev = priv->dev;
 	ah->hw = priv->hw;
 	ah->hw_version.devid = devid;
-	ah->hw_version.usbdev = drv_info;
+	ah->hw_version.usbdev = drv_info & AR_USB_DEV_MASK;
+	ah->hw_version.usbflags = drv_info & AR_USB_FLAGS_MASK;
 	ah->ah_flags |= AH_USE_EEPROM;
 	ah->reg_ops.read = ath9k_regread;
 	ah->reg_ops.multi_read = ath9k_multi_regread;
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -390,6 +390,7 @@ static inline void ath9k_htc_err_stat_rx
 #define ATH_LED_PIN_DEF             1
 #define ATH_LED_PIN_9287            10
 #define ATH_LED_PIN_9271            15
+#define ATH_LED_PIN_7010_RED        10 /* XBOX: red led */
 #define ATH_LED_PIN_7010            12
 
 #define BSTUCK_THRESHOLD 10
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -999,6 +999,12 @@ enum ath_usb_dev {
 	STORAGE_DEVICE = 3,
 };
 
+/* Mask for ath_usb_dev enum value in usb driver_info */
+#define AR_USB_DEV_MASK                       0x0000000f
+/* Read EEPROM data from SPI flash if set */
+#define AR_USB_FLAGS_MASK                     0x00010000
+#define AR_USB_SPI_EEPROM                     0x00010000
+
 #define AR_DEVID_7010(_ah) \
 	(((_ah)->hw_version.usbdev == AR9280_USB) || \
 	 ((_ah)->hw_version.usbdev == AR9287_USB))
--- a/drivers/net/wireless/ath/ath9k/hif_usb.h
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.h
@@ -38,14 +38,17 @@
 
 extern int htc_use_dev_fw;
 
-#define IS_AR7010_DEVICE(_v) (((_v) == AR9280_USB) || \
-                              ((_v) == AR9280_USB_XBOX) || \
-                              ((_v) == AR9287_USB))
+#define IS_AR7010_DEVICE(_v) ((((_v) & AR_USB_DEV_MASK) == AR9280_USB) || \
+                              (((_v) & AR_USB_DEV_MASK) == AR9287_USB))
 
 #define AR9271_FIRMWARE       0x501000
 #define AR9271_FIRMWARE_TEXT  0x903000
 #define AR7010_FIRMWARE_TEXT  0x906000
 
+/* FIXME: This assumes a 512KiB SPI flash size */
+#define AR7010_SPI_EEPROM_BASE 0xf07f000
+#define AR7010_EEPROM_SIZE_MAX 0x0001000
+
 #define FIRMWARE_DOWNLOAD       0x30
 #define FIRMWARE_DOWNLOAD_COMP  0x31
 
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -667,8 +667,6 @@ bool ath9k_hw_nvram_read(struct ath_hw *
 int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size);
 bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size);
 bool ath9k_hw_nvram_check_version(struct ath_hw *ah, int version, int minrev);
-void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
-				  int eep_start_loc, int size);
 void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
 			     u8 *pVpdList, u16 numIntercepts,
 			     u8 *pRetVpdList);
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -44,15 +44,6 @@ static bool __ath9k_hw_4k_fill_eeprom(st
 	return true;
 }
 
-static bool __ath9k_hw_usb_4k_fill_eeprom(struct ath_hw *ah)
-{
-	u16 *eep_data = (u16 *)&ah->eeprom.map4k;
-
-	ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, 64, SIZE_EEPROM_4K);
-
-	return true;
-}
-
 static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -61,10 +52,7 @@ static bool ath9k_hw_4k_fill_eeprom(stru
 		ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
 	}
 
-	if (common->bus_ops->ath_bus_type == ATH_USB)
-		return __ath9k_hw_usb_4k_fill_eeprom(ah);
-	else
-		return __ath9k_hw_4k_fill_eeprom(ah);
+	return __ath9k_hw_4k_fill_eeprom(ah);
 }
 
 #if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -46,16 +46,6 @@ static bool __ath9k_hw_ar9287_fill_eepro
 	return true;
 }
 
-static bool __ath9k_hw_usb_ar9287_fill_eeprom(struct ath_hw *ah)
-{
-	u16 *eep_data = (u16 *)&ah->eeprom.map9287;
-
-	ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
-				     AR9287_HTC_EEP_START_LOC,
-				     SIZE_EEPROM_AR9287);
-	return true;
-}
-
 static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -64,10 +54,7 @@ static bool ath9k_hw_ar9287_fill_eeprom(
 		ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
 	}
 
-	if (common->bus_ops->ath_bus_type == ATH_USB)
-		return __ath9k_hw_usb_ar9287_fill_eeprom(ah);
-	else
-		return __ath9k_hw_ar9287_fill_eeprom(ah);
+	return __ath9k_hw_ar9287_fill_eeprom(ah);
 }
 
 #if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -103,15 +103,6 @@ static bool __ath9k_hw_def_fill_eeprom(s
 	return true;
 }
 
-static bool __ath9k_hw_usb_def_fill_eeprom(struct ath_hw *ah)
-{
-	u16 *eep_data = (u16 *)&ah->eeprom.def;
-
-	ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
-				     0x100, SIZE_EEPROM_DEF);
-	return true;
-}
-
 static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -120,10 +111,7 @@ static bool ath9k_hw_def_fill_eeprom(str
 		ath_dbg(common, EEPROM, "Reading from EEPROM, not flash\n");
 	}
 
-	if (common->bus_ops->ath_bus_type == ATH_USB)
-		return __ath9k_hw_usb_def_fill_eeprom(ah);
-	else
-		return __ath9k_hw_def_fill_eeprom(ah);
+	return __ath9k_hw_def_fill_eeprom(ah);
 }
 
 #if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -77,38 +77,6 @@ bool ath9k_hw_get_lower_upper_index(u8 t
 	return false;
 }
 
-void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
-				  int eep_start_loc, int size)
-{
-	int i = 0, j, addr;
-	u32 addrdata[8];
-	u32 data[8];
-
-	for (addr = 0; addr < size; addr++) {
-		addrdata[i] = AR5416_EEPROM_OFFSET +
-			((addr + eep_start_loc) << AR5416_EEPROM_S);
-		i++;
-		if (i == 8) {
-			REG_READ_MULTI(ah, addrdata, data, i);
-
-			for (j = 0; j < i; j++) {
-				*eep_data = data[j];
-				eep_data++;
-			}
-			i = 0;
-		}
-	}
-
-	if (i != 0) {
-		REG_READ_MULTI(ah, addrdata, data, i);
-
-		for (j = 0; j < i; j++) {
-			*eep_data = data[j];
-			eep_data++;
-		}
-	}
-}
-
 static bool ath9k_hw_nvram_read_array(u16 *blob, size_t blob_size,
 				      off_t offset, u16 *data)
 {

-- 
Tobias						PGP: http://8ef7ddba.uguu.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/ath9k_htc_fw/attachments/20170605/1063ebd7/attachment.sig>


More information about the ath9k_htc_fw mailing list