linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: kilroyd@googlemail.com
To: linux-wireless@vger.kernel.org
Cc: proski@gnu.org, orinoco-devel@lists.sourceforge.net,
	David Kilroy <kilroyd@gmail.com>
Subject: [PATCH 08/19] orinoco: Extend hermes_dld routines for Agere firmware
Date: Sat,  2 Aug 2008 11:14:22 +0100	[thread overview]
Message-ID: <1217672073-7094-9-git-send-email-kilroyd@gmail.com> (raw)
In-Reply-To: <1217672073-7094-8-git-send-email-kilroyd@gmail.com>

Add programming initialisation and termination functions.
Add checks to avoid overrunning the firmware image or PDA areas.
Extra algorithm to program PDA values using defaults where necessary.

Signed-off-by: David Kilroy <kilroyd@gmail.com>
---
 drivers/net/wireless/hermes_dld.c |  285 +++++++++++++++++++++++++++++++++++++
 drivers/net/wireless/hermes_dld.h |    5 +
 2 files changed, 290 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/hermes_dld.c b/drivers/net/wireless/hermes_dld.c
index 454452f..4f11363 100644
--- a/drivers/net/wireless/hermes_dld.c
+++ b/drivers/net/wireless/hermes_dld.c
@@ -70,6 +70,12 @@ MODULE_LICENSE("Dual MPL/GPL");
 #define HERMES_AUX_PW1	0xDC23
 #define HERMES_AUX_PW2	0xBA45
 
+/* HERMES_CMD_DOWNLD */
+#define HERMES_PROGRAM_DISABLE             (0x0000 | HERMES_CMD_DOWNLD)
+#define HERMES_PROGRAM_ENABLE_VOLATILE     (0x0100 | HERMES_CMD_DOWNLD)
+#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
+#define HERMES_PROGRAM_NON_VOLATILE        (0x0300 | HERMES_CMD_DOWNLD)
+
 /* End markers used in dblocks */
 #define PDI_END		0x00000000	/* End of PDA */
 #define BLOCK_END	0xFFFFFFFF	/* Last image block */
@@ -247,6 +253,23 @@ hermes_find_pdr(struct pdr *first_pdr, u32 record_id)
 	return NULL;
 }
 
+/* Scan production data items for a particular entry */
+static struct pdi *
+hermes_find_pdi(struct pdi *first_pdi, u32 record_id)
+{
+	struct pdi *pdi = first_pdi;
+
+	while (pdi_id(pdi) != PDI_END) {
+
+		/* If the record ID matches, we are done */
+		if (pdi_id(pdi) == record_id)
+			return pdi;
+
+		pdi = (struct pdi *) &pdi->data[pdi_len(pdi)];
+	}
+	return NULL;
+}
+
 /* Process one Plug Data Item - find corresponding PDR and plug it */
 static int
 hermes_plug_pdi(hermes_t *hw, struct pdr *first_pdr, const struct pdi *pdi)
@@ -290,6 +313,15 @@ int hermes_read_pda(hermes_t *hw,
 		ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
 		if (ret)
 			return ret;
+	} else {
+		/* wl_lkm does not include PDA size in the PDA area.
+		 * We will pad the information into pda, so other routines
+		 * don't have to be modified */
+		pda[0] = cpu_to_le16(pda_len - 2);
+			/* Includes CFG_PROD_DATA but not itself */
+		pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
+		data_len = pda_len - 4;
+		data = pda + 2;
 	}
 
 	/* Open auxiliary port */
@@ -370,6 +402,94 @@ EXPORT_SYMBOL(hermes_blocks_length);
 
 /*** Hermes programming ***/
 
+/* About to start programming data (Hermes I)
+ * offset is the entry point
+ *
+ * Spectrum_cs' Symbol fw does not require this
+ * wl_lkm Agere fw does
+ * Don't know about intersil
+ */
+int hermesi_program_init(hermes_t *hw, u32 offset)
+{
+	int err;
+
+	/* Disable interrupts?*/
+	/*hw->inten = 0x0;*/
+	/*hermes_write_regn(hw, INTEN, 0);*/
+	/*hermes_set_irqmask(hw, 0);*/
+
+	/* Acknowledge any outstanding command */
+	hermes_write_regn(hw, EVACK, 0xFFFF);
+
+	/* Using doicmd_wait rather than docmd_wait */
+	err = hermes_doicmd_wait(hw,
+				 0x0100 | HERMES_CMD_INIT,
+				 0, 0, 0, NULL);
+	if (err)
+		return err;
+
+	err = hermes_doicmd_wait(hw,
+				 0x0000 | HERMES_CMD_INIT,
+				 0, 0, 0, NULL);
+	if (err)
+		return err;
+
+	err = hermes_aux_control(hw, 1);
+	printk(KERN_DEBUG PFX "AUX enable returned %d\n", err);
+
+	if (err)
+		return err;
+
+	printk(KERN_DEBUG PFX "Enabling volatile, EP 0x%08x\n", offset);
+	err = hermes_doicmd_wait(hw,
+				 HERMES_PROGRAM_ENABLE_VOLATILE,
+				 offset & 0xFFFFu,
+				 offset >> 16,
+				 0,
+				 NULL);
+	printk(KERN_DEBUG PFX "PROGRAM_ENABLE returned %d\n",
+	       err);
+
+	return err;
+}
+EXPORT_SYMBOL(hermesi_program_init);
+
+/* Done programming data (Hermes I)
+ *
+ * Spectrum_cs' Symbol fw does not require this
+ * wl_lkm Agere fw does
+ * Don't know about intersil
+ */
+int hermesi_program_end(hermes_t *hw)
+{
+	struct hermes_response resp;
+	int rc = 0;
+	int err;
+
+	rc = hermes_docmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
+
+	printk(KERN_DEBUG PFX "PROGRAM_DISABLE returned %d, "
+	       "r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
+	       rc, resp.resp0, resp.resp1, resp.resp2);
+
+	if ((rc == 0) &&
+	    ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
+		rc = -EIO;
+
+	err = hermes_aux_control(hw, 0);
+	printk(KERN_DEBUG PFX "AUX disable returned %d\n", err);
+
+	/* Acknowledge any outstanding command */
+	hermes_write_regn(hw, EVACK, 0xFFFF);
+
+	/* Reinitialise, ignoring return */
+	(void) hermes_doicmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
+				  0, 0, 0, NULL);
+
+	return rc ? rc : err;
+}
+EXPORT_SYMBOL(hermesi_program_end);
+
 /* Program the data blocks */
 int hermes_program(hermes_t *hw, const char *first_block, const char *end)
 {
@@ -443,3 +563,168 @@ static void __exit exit_hermes_dld(void)
 
 module_init(init_hermes_dld);
 module_exit(exit_hermes_dld);
+
+/*** Default plugging data for Hermes I ***/
+/* Values from wl_lkm_718/hcf/dhf.c */
+
+#define DEFINE_DEFAULT_PDR(pid, length, data)				\
+static const struct {							\
+	__le16 len;							\
+	__le16 id;							\
+	u8 val[length];							\
+} __attribute__ ((packed)) default_pdr_data_##pid = {			\
+	__constant_cpu_to_le16((sizeof(default_pdr_data_##pid)/		\
+				sizeof(__le16)) - 1),			\
+	__constant_cpu_to_le16(pid),					\
+	data								\
+}
+
+#define DEFAULT_PDR(pid) default_pdr_data_##pid
+
+/*  HWIF Compatiblity */
+DEFINE_DEFAULT_PDR(0x0005, 10, "\x00\x00\x06\x00\x01\x00\x01\x00\x01\x00");
+
+/* PPPPSign */
+DEFINE_DEFAULT_PDR(0x0108, 4, "\x00\x00\x00\x00");
+
+/* PPPPProf */
+DEFINE_DEFAULT_PDR(0x0109, 10, "\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00");
+
+/* Antenna diversity */
+DEFINE_DEFAULT_PDR(0x0150, 2, "\x00\x3F");
+
+/* Modem VCO band Set-up */
+DEFINE_DEFAULT_PDR(0x0160, 28,
+		   "\x00\x00\x00\x00\x00\x00\x00\x00"
+		   "\x00\x00\x00\x00\x00\x00\x00\x00"
+		   "\x00\x00\x00\x00\x00\x00\x00\x00"
+		   "\x00\x00\x00\x00");
+
+/* Modem Rx Gain Table Values */
+DEFINE_DEFAULT_PDR(0x0161, 256,
+		   "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
+		   "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
+		   "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
+		   "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
+		   "\x3F\x01\x3E\01\x3E\x01\x3D\x01"
+		   "\x3D\x01\x3C\01\x3C\x01\x3B\x01"
+		   "\x3B\x01\x3A\01\x3A\x01\x39\x01"
+		   "\x39\x01\x38\01\x38\x01\x37\x01"
+		   "\x37\x01\x36\01\x36\x01\x35\x01"
+		   "\x35\x01\x34\01\x34\x01\x33\x01"
+		   "\x33\x01\x32\x01\x32\x01\x31\x01"
+		   "\x31\x01\x30\x01\x30\x01\x7B\x01"
+		   "\x7B\x01\x7A\x01\x7A\x01\x79\x01"
+		   "\x79\x01\x78\x01\x78\x01\x77\x01"
+		   "\x77\x01\x76\x01\x76\x01\x75\x01"
+		   "\x75\x01\x74\x01\x74\x01\x73\x01"
+		   "\x73\x01\x72\x01\x72\x01\x71\x01"
+		   "\x71\x01\x70\x01\x70\x01\x68\x01"
+		   "\x68\x01\x67\x01\x67\x01\x66\x01"
+		   "\x66\x01\x65\x01\x65\x01\x57\x01"
+		   "\x57\x01\x56\x01\x56\x01\x55\x01"
+		   "\x55\x01\x54\x01\x54\x01\x53\x01"
+		   "\x53\x01\x52\x01\x52\x01\x51\x01"
+		   "\x51\x01\x50\x01\x50\x01\x48\x01"
+		   "\x48\x01\x47\x01\x47\x01\x46\x01"
+		   "\x46\x01\x45\x01\x45\x01\x44\x01"
+		   "\x44\x01\x43\x01\x43\x01\x42\x01"
+		   "\x42\x01\x41\x01\x41\x01\x40\x01"
+		   "\x40\x01\x40\x01\x40\x01\x40\x01"
+		   "\x40\x01\x40\x01\x40\x01\x40\x01"
+		   "\x40\x01\x40\x01\x40\x01\x40\x01"
+		   "\x40\x01\x40\x01\x40\x01\x40\x01");
+
+/* Write PDA according to certain rules.
+ *
+ * For every production data record, look for a previous setting in
+ * the pda, and use that.
+ *
+ * For certain records, use defaults if they are not found in pda.
+ */
+int hermes_apply_pda_with_defaults(hermes_t *hw,
+				   const char *first_pdr,
+				   const __le16 *pda)
+{
+	const struct pdr *pdr = (const struct pdr *) first_pdr;
+	struct pdi *first_pdi = (struct pdi *) &pda[2];
+	struct pdi *pdi;
+	struct pdi *default_pdi = NULL;
+	struct pdi *outdoor_pdi;
+	void *end = (void *)first_pdr + MAX_PDA_SIZE;
+	int record_id;
+
+	while (((void *)pdr < end) &&
+	       (pdr_id(pdr) != PDI_END)) {
+		/*
+		 * For spectrum_cs firmwares,
+		 * PDR area is currently not terminated by PDI_END.
+		 * It's followed by CRC records, which have the type
+		 * field where PDR has length.  The type can be 0 or 1.
+		 */
+		if (pdr_len(pdr) < 2)
+			break;
+		record_id = pdr_id(pdr);
+
+		pdi = hermes_find_pdi(first_pdi, record_id);
+		if (pdi)
+			printk(KERN_DEBUG PFX "Found record 0x%04x at %p\n",
+			       record_id, pdi);
+
+		switch (record_id) {
+		case 0x110: /* Modem REFDAC values */
+		case 0x120: /* Modem VGDAC values */
+			outdoor_pdi = hermes_find_pdi(first_pdi, record_id + 1);
+			default_pdi = NULL;
+			if (outdoor_pdi) {
+				pdi = outdoor_pdi;
+				printk(KERN_DEBUG PFX
+				       "Using outdoor record 0x%04x at %p\n",
+				       record_id + 1, pdi);
+			}
+			break;
+		case 0x5: /*  HWIF Compatiblity */
+			default_pdi = (struct pdi *) &DEFAULT_PDR(0x0005);
+			break;
+		case 0x108: /* PPPPSign */
+			default_pdi = (struct pdi *) &DEFAULT_PDR(0x0108);
+			break;
+		case 0x109: /* PPPPProf */
+			default_pdi = (struct pdi *) &DEFAULT_PDR(0x0109);
+			break;
+		case 0x150: /* Antenna diversity */
+			default_pdi = (struct pdi *) &DEFAULT_PDR(0x0150);
+			break;
+		case 0x160: /* Modem VCO band Set-up */
+			default_pdi = (struct pdi *) &DEFAULT_PDR(0x0160);
+			break;
+		case 0x161: /* Modem Rx Gain Table Values */
+			default_pdi = (struct pdi *) &DEFAULT_PDR(0x0161);
+			break;
+		default:
+			default_pdi = NULL;
+			break;
+		}
+		if (!pdi && default_pdi) {
+			/* Use default */
+			pdi = default_pdi;
+			printk(KERN_DEBUG PFX
+			       "Using default record 0x%04x at %p\n",
+			       record_id, pdi);
+		}
+
+		if (pdi) {
+			/* Lengths of the data in PDI and PDR must match */
+			if (pdi_len(pdi) == pdr_len(pdr)) {
+				/* do the actual plugging */
+				hermes_aux_setaddr(hw, pdr_addr(pdr));
+				hermes_write_bytes(hw, HERMES_AUXDATA,
+						   pdi->data, pdi_len(pdi));
+			}
+		}
+
+		pdr++;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(hermes_apply_pda_with_defaults);
diff --git a/drivers/net/wireless/hermes_dld.h b/drivers/net/wireless/hermes_dld.h
index a39a482..c13a1c2 100644
--- a/drivers/net/wireless/hermes_dld.h
+++ b/drivers/net/wireless/hermes_dld.h
@@ -27,6 +27,8 @@
 
 #include "hermes.h"
 
+int hermesi_program_init(hermes_t *hw, u32 offset);
+int hermesi_program_end(hermes_t *hw);
 int hermes_program(hermes_t *hw, const char *first_block, const char *end);
 
 int hermes_read_pda(hermes_t *hw,
@@ -37,6 +39,9 @@ int hermes_read_pda(hermes_t *hw,
 int hermes_apply_pda(hermes_t *hw,
 		     const char *first_pdr,
 		     const __le16 *pda);
+int hermes_apply_pda_with_defaults(hermes_t *hw,
+				   const char *first_pdr,
+				   const __le16 *pda);
 
 size_t hermes_blocks_length(const char *first_block);
 
-- 
1.5.4.5


  reply	other threads:[~2008-08-02 10:15 UTC|newest]

Thread overview: 75+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-02 10:14 [PATCH 00/19] orinoco: WPA for Agere based cards kilroyd
2008-08-02 10:14 ` [PATCH 01/19] orinoco: Add ESSID specific scanning for Agere fw kilroyd
2008-08-02 10:14   ` [PATCH 02/19] orinoco: Update scan translation kilroyd
2008-08-02 10:14     ` [PATCH 03/19] orinoco: Specify all three parameters to every Hermes command kilroyd
2008-08-02 10:14       ` [PATCH 04/19] orinoco: Move EXPORT_SYMBOL declarations next to exported function kilroyd
2008-08-02 10:14         ` [PATCH 05/19] orinoco: Add function to execute Hermes initialisation commands synchronously kilroyd
2008-08-02 10:14           ` [PATCH 06/19] orinoco: Move firmware download functionality into new module kilroyd
2008-08-02 10:14             ` [PATCH 07/19] orinoco: Make firmware download logic more generic kilroyd
2008-08-02 10:14               ` kilroyd [this message]
2008-08-02 10:14                 ` [PATCH 09/19] orinoco: Invoke firmware download in main driver kilroyd
2008-08-02 10:14                   ` [PATCH 10/19] orinoco: Fix transmit for Agere/Lucent with fw 9.x kilroyd
2008-08-02 10:14                     ` [PATCH 11/19] orinoco: address checkpatch typedef warning kilroyd
2008-08-02 10:14                       ` [PATCH 12/19] orinoco: Use extended Agere scans available on 9.x series firmwares kilroyd
2008-08-02 10:14                         ` [PATCH 13/19] orinoco: Don't use boolean parameter to record encoding type kilroyd
2008-08-02 10:14                           ` [PATCH 14/19] orinoco: Split wevent work thread from wevent sending kilroyd
2008-08-02 10:14                             ` [PATCH 15/19] orinoco: Use a macro to define wireless handlers kilroyd
2008-08-02 10:14                               ` [PATCH 16/19] orinoco: Add WE-18 ioctls for WPA kilroyd
2008-08-02 10:14                                 ` [PATCH 17/19] orinoco: Send association events to userspace kilroyd
2008-08-02 10:14                                   ` [PATCH 18/19] orinoco: Process bulk of receive interrupt in a tasklet kilroyd
2008-08-02 10:14                                     ` [PATCH 19/19] orinoco: Add MIC on TX and check on RX kilroyd
2008-08-02 10:22                               ` [PATCH 15/19] orinoco: Use a macro to define wireless handlers kilroyd
2008-08-04  4:48   ` [PATCH 01/19] orinoco: Add ESSID specific scanning for Agere fw Pavel Roskin
2008-08-04 15:34     ` Dan Williams
2008-08-05 16:22       ` Jean Tourrilhes
2008-09-02 23:06         ` Jean Tourrilhes
2008-09-08 12:48           ` Pavel Roskin
2008-09-08 16:45             ` Jean Tourrilhes
2008-09-08 18:32             ` Jean Tourrilhes
2008-09-09 18:37               ` Dave
2008-09-09 19:33                 ` Jean Tourrilhes
2008-09-09 21:20                   ` Tomas Winkler
2008-09-09 21:44                     ` Jean Tourrilhes
2008-09-13  4:17               ` Pavel Roskin
2008-09-15 21:17                 ` Jean Tourrilhes
2008-08-05 21:15       ` Pavel Roskin
2008-08-05 21:50         ` Dave
2008-08-05 21:55         ` Dan Williams
2008-08-05 22:48           ` Pavel Roskin
2008-08-06 13:13             ` Dan Williams
2008-08-06 13:48               ` Pavel Roskin
2008-08-06 19:26                 ` Dave
2008-08-06 19:29               ` Dave
2008-08-06 20:56                 ` Dan Williams
2008-08-06 21:03                   ` Dan Williams
2008-08-06 21:08                   ` Dave
2008-08-07  2:48                     ` Dan Williams
2008-08-07 18:43                       ` Dave
2008-08-07 19:42                         ` Dan Williams
2008-08-07 20:17                           ` Dave
2008-08-07 20:46                             ` Dan Williams
2008-08-07 21:08                           ` Dave
2008-08-08 14:51                             ` Dan Williams
2008-08-04  3:57 ` [PATCH 00/19] orinoco: WPA for Agere based cards Pavel Roskin
2008-08-04 23:09   ` Dave
2008-08-04 23:28     ` Dan Williams
2008-08-06  0:37       ` Pavel Roskin
2008-08-06 18:33         ` Dave
2008-08-06 21:01           ` Dan Williams
2008-08-07  8:06             ` Jouni Malinen
2008-08-06 21:28         ` [PATCH 12/19] orinoco: Use extended Agere scans available on 9.x series firmwares kilroyd
2008-08-05 22:38     ` [Orinoco-devel] [PATCH 00/19] orinoco: WPA for Agere based cards Pavel Roskin
2008-08-08  0:02       ` Dave
2008-08-05 22:59     ` Pavel Roskin
2008-08-05 23:46       ` Dave
2008-08-06  0:41         ` [Orinoco-devel] " Pavel Roskin
2008-08-05 22:22   ` [PATCH 07/19] orinoco: Make firmware download logic more generic kilroyd
2008-08-05 22:22     ` [PATCH 09/19] orinoco: Invoke firmware download in main driver kilroyd
2008-08-05 22:22       ` [PATCH 12/19] orinoco: Use extended Agere scans available on 9.x series firmwares kilroyd
2008-08-20 19:28 ` [PATCH 00/19] orinoco: WPA for Agere based cards John W. Linville
2008-08-20 20:49   ` Dave
2008-08-20 21:06     ` Larry Finger
2008-08-20 21:07     ` Johannes Berg
2008-08-20 21:22       ` Johannes Berg
2008-08-20 23:07         ` Dave
2008-08-21  6:42           ` Johannes Berg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1217672073-7094-9-git-send-email-kilroyd@gmail.com \
    --to=kilroyd@googlemail.com \
    --cc=kilroyd@gmail.com \
    --cc=linux-wireless@vger.kernel.org \
    --cc=orinoco-devel@lists.sourceforge.net \
    --cc=proski@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).