aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Kilroy <kilroyd@googlemail.com>2010-05-01 09:05:43 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-05-03 14:53:09 -0400
commit07cefe7ac983374ee4c369f1d4aee3093bf3b44f (patch)
treec4db80ac5a3f28bda1a5c93fb9b88b7db728898e /drivers
parentfc97431a50962e66c052ec6909d4b2582efd3554 (diff)
orinoco_usb: implement fw download
This involves some refactorring of the common fw download code to substitute ezusb versions of various functions. Note that WPA-enabled firmwares (9.xx series) will not work fully with orinoco_usb yet. Signed-off-by: David Kilroy <kilroyd@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/orinoco/fw.c8
-rw-r--r--drivers/net/wireless/orinoco/hermes.c208
-rw-r--r--drivers/net/wireless/orinoco/hermes.h7
-rw-r--r--drivers/net/wireless/orinoco/hermes_dld.c243
-rw-r--r--drivers/net/wireless/orinoco/orinoco_usb.c120
-rw-r--r--drivers/net/wireless/orinoco/spectrum_cs.c1
6 files changed, 349 insertions, 238 deletions
diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c
index 07c79e5de32d..94c0853f6814 100644
--- a/drivers/net/wireless/orinoco/fw.c
+++ b/drivers/net/wireless/orinoco/fw.c
@@ -121,7 +121,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
121 dev_dbg(dev, "Attempting to download firmware %s\n", firmware); 121 dev_dbg(dev, "Attempting to download firmware %s\n", firmware);
122 122
123 /* Read current plug data */ 123 /* Read current plug data */
124 err = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 0); 124 err = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size);
125 dev_dbg(dev, "Read PDA returned %d\n", err); 125 dev_dbg(dev, "Read PDA returned %d\n", err);
126 if (err) 126 if (err)
127 goto free; 127 goto free;
@@ -148,7 +148,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
148 } 148 }
149 149
150 /* Enable aux port to allow programming */ 150 /* Enable aux port to allow programming */
151 err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point)); 151 err = hw->ops->program_init(hw, le32_to_cpu(hdr->entry_point));
152 dev_dbg(dev, "Program init returned %d\n", err); 152 dev_dbg(dev, "Program init returned %d\n", err);
153 if (err != 0) 153 if (err != 0)
154 goto abort; 154 goto abort;
@@ -176,7 +176,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
176 goto abort; 176 goto abort;
177 177
178 /* Tell card we've finished */ 178 /* Tell card we've finished */
179 err = hermesi_program_end(hw); 179 err = hw->ops->program_end(hw);
180 dev_dbg(dev, "Program end returned %d\n", err); 180 dev_dbg(dev, "Program end returned %d\n", err);
181 if (err != 0) 181 if (err != 0)
182 goto abort; 182 goto abort;
@@ -223,7 +223,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
223 if (!pda) 223 if (!pda)
224 return -ENOMEM; 224 return -ENOMEM;
225 225
226 ret = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 1); 226 ret = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size);
227 if (ret) 227 if (ret)
228 goto free; 228 goto free;
229 } 229 }
diff --git a/drivers/net/wireless/orinoco/hermes.c b/drivers/net/wireless/orinoco/hermes.c
index 845693fb25f3..6c6a23e08df6 100644
--- a/drivers/net/wireless/orinoco/hermes.c
+++ b/drivers/net/wireless/orinoco/hermes.c
@@ -52,6 +52,26 @@
52#define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */ 52#define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
53 53
54/* 54/*
55 * AUX port access. To unlock the AUX port write the access keys to the
56 * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
57 * register. Then read it and make sure it's HERMES_AUX_ENABLED.
58 */
59#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
60#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
61#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
62#define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */
63
64#define HERMES_AUX_PW0 0xFE01
65#define HERMES_AUX_PW1 0xDC23
66#define HERMES_AUX_PW2 0xBA45
67
68/* HERMES_CMD_DOWNLD */
69#define HERMES_PROGRAM_DISABLE (0x0000 | HERMES_CMD_DOWNLD)
70#define HERMES_PROGRAM_ENABLE_VOLATILE (0x0100 | HERMES_CMD_DOWNLD)
71#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
72#define HERMES_PROGRAM_NON_VOLATILE (0x0300 | HERMES_CMD_DOWNLD)
73
74/*
55 * Debugging helpers 75 * Debugging helpers
56 */ 76 */
57 77
@@ -170,6 +190,7 @@ void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
170 hw->iobase = address; 190 hw->iobase = address;
171 hw->reg_spacing = reg_spacing; 191 hw->reg_spacing = reg_spacing;
172 hw->inten = 0x0; 192 hw->inten = 0x0;
193 hw->eeprom_pda = false;
173 hw->ops = &hermes_ops_local; 194 hw->ops = &hermes_ops_local;
174} 195}
175EXPORT_SYMBOL(hermes_struct_init); 196EXPORT_SYMBOL(hermes_struct_init);
@@ -529,6 +550,189 @@ static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
529 return err; 550 return err;
530} 551}
531 552
553/*** Hermes AUX control ***/
554
555static inline void
556hermes_aux_setaddr(hermes_t *hw, u32 addr)
557{
558 hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
559 hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
560}
561
562static inline int
563hermes_aux_control(hermes_t *hw, int enabled)
564{
565 int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
566 int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
567 int i;
568
569 /* Already open? */
570 if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state)
571 return 0;
572
573 hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
574 hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
575 hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
576 hermes_write_reg(hw, HERMES_CONTROL, action);
577
578 for (i = 0; i < 20; i++) {
579 udelay(10);
580 if (hermes_read_reg(hw, HERMES_CONTROL) ==
581 desired_state)
582 return 0;
583 }
584
585 return -EBUSY;
586}
587
588/*** Hermes programming ***/
589
590/* About to start programming data (Hermes I)
591 * offset is the entry point
592 *
593 * Spectrum_cs' Symbol fw does not require this
594 * wl_lkm Agere fw does
595 * Don't know about intersil
596 */
597static int hermesi_program_init(hermes_t *hw, u32 offset)
598{
599 int err;
600
601 /* Disable interrupts?*/
602 /*hw->inten = 0x0;*/
603 /*hermes_write_regn(hw, INTEN, 0);*/
604 /*hermes_set_irqmask(hw, 0);*/
605
606 /* Acknowledge any outstanding command */
607 hermes_write_regn(hw, EVACK, 0xFFFF);
608
609 /* Using init_cmd_wait rather than cmd_wait */
610 err = hw->ops->init_cmd_wait(hw,
611 0x0100 | HERMES_CMD_INIT,
612 0, 0, 0, NULL);
613 if (err)
614 return err;
615
616 err = hw->ops->init_cmd_wait(hw,
617 0x0000 | HERMES_CMD_INIT,
618 0, 0, 0, NULL);
619 if (err)
620 return err;
621
622 err = hermes_aux_control(hw, 1);
623 pr_debug("AUX enable returned %d\n", err);
624
625 if (err)
626 return err;
627
628 pr_debug("Enabling volatile, EP 0x%08x\n", offset);
629 err = hw->ops->init_cmd_wait(hw,
630 HERMES_PROGRAM_ENABLE_VOLATILE,
631 offset & 0xFFFFu,
632 offset >> 16,
633 0,
634 NULL);
635 pr_debug("PROGRAM_ENABLE returned %d\n", err);
636
637 return err;
638}
639
640/* Done programming data (Hermes I)
641 *
642 * Spectrum_cs' Symbol fw does not require this
643 * wl_lkm Agere fw does
644 * Don't know about intersil
645 */
646static int hermesi_program_end(hermes_t *hw)
647{
648 struct hermes_response resp;
649 int rc = 0;
650 int err;
651
652 rc = hw->ops->cmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
653
654 pr_debug("PROGRAM_DISABLE returned %d, "
655 "r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
656 rc, resp.resp0, resp.resp1, resp.resp2);
657
658 if ((rc == 0) &&
659 ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
660 rc = -EIO;
661
662 err = hermes_aux_control(hw, 0);
663 pr_debug("AUX disable returned %d\n", err);
664
665 /* Acknowledge any outstanding command */
666 hermes_write_regn(hw, EVACK, 0xFFFF);
667
668 /* Reinitialise, ignoring return */
669 (void) hw->ops->init_cmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
670 0, 0, 0, NULL);
671
672 return rc ? rc : err;
673}
674
675static int hermes_program_bytes(struct hermes *hw, const char *data,
676 u32 addr, u32 len)
677{
678 /* wl lkm splits the programming into chunks of 2000 bytes.
679 * This restriction appears to come from USB. The PCMCIA
680 * adapters can program the whole lot in one go */
681 hermes_aux_setaddr(hw, addr);
682 hermes_write_bytes(hw, HERMES_AUXDATA, data, len);
683 return 0;
684}
685
686/* Read PDA from the adapter */
687static int hermes_read_pda(hermes_t *hw, __le16 *pda, u32 pda_addr, u16 pda_len)
688{
689 int ret;
690 u16 pda_size;
691 u16 data_len = pda_len;
692 __le16 *data = pda;
693
694 if (hw->eeprom_pda) {
695 /* PDA of spectrum symbol is in eeprom */
696
697 /* Issue command to read EEPROM */
698 ret = hw->ops->cmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
699 if (ret)
700 return ret;
701 } else {
702 /* wl_lkm does not include PDA size in the PDA area.
703 * We will pad the information into pda, so other routines
704 * don't have to be modified */
705 pda[0] = cpu_to_le16(pda_len - 2);
706 /* Includes CFG_PROD_DATA but not itself */
707 pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
708 data_len = pda_len - 4;
709 data = pda + 2;
710 }
711
712 /* Open auxiliary port */
713 ret = hermes_aux_control(hw, 1);
714 pr_debug("AUX enable returned %d\n", ret);
715 if (ret)
716 return ret;
717
718 /* Read PDA */
719 hermes_aux_setaddr(hw, pda_addr);
720 hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2);
721
722 /* Close aux port */
723 ret = hermes_aux_control(hw, 0);
724 pr_debug("AUX disable returned %d\n", ret);
725
726 /* Check PDA length */
727 pda_size = le16_to_cpu(pda[0]);
728 pr_debug("Actual PDA length %d, Max allowed %d\n",
729 pda_size, pda_len);
730 if (pda_size > pda_len)
731 return -EINVAL;
732
733 return 0;
734}
735
532static void hermes_lock_irqsave(spinlock_t *lock, 736static void hermes_lock_irqsave(spinlock_t *lock,
533 unsigned long *flags) __acquires(lock) 737 unsigned long *flags) __acquires(lock)
534{ 738{
@@ -561,6 +765,10 @@ static const struct hermes_ops hermes_ops_local = {
561 .write_ltv = hermes_write_ltv, 765 .write_ltv = hermes_write_ltv,
562 .bap_pread = hermes_bap_pread, 766 .bap_pread = hermes_bap_pread,
563 .bap_pwrite = hermes_bap_pwrite, 767 .bap_pwrite = hermes_bap_pwrite,
768 .read_pda = hermes_read_pda,
769 .program_init = hermesi_program_init,
770 .program_end = hermesi_program_end,
771 .program = hermes_program_bytes,
564 .lock_irqsave = hermes_lock_irqsave, 772 .lock_irqsave = hermes_lock_irqsave,
565 .unlock_irqrestore = hermes_unlock_irqrestore, 773 .unlock_irqrestore = hermes_unlock_irqrestore,
566 .lock_irq = hermes_lock_irq, 774 .lock_irq = hermes_lock_irq,
diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h
index aed14ff2d235..9ca34e722b45 100644
--- a/drivers/net/wireless/orinoco/hermes.h
+++ b/drivers/net/wireless/orinoco/hermes.h
@@ -393,6 +393,12 @@ struct hermes_ops {
393 u16 id, u16 offset); 393 u16 id, u16 offset);
394 int (*bap_pwrite)(struct hermes *hw, int bap, const void *buf, 394 int (*bap_pwrite)(struct hermes *hw, int bap, const void *buf,
395 int len, u16 id, u16 offset); 395 int len, u16 id, u16 offset);
396 int (*read_pda)(struct hermes *hw, __le16 *pda,
397 u32 pda_addr, u16 pda_len);
398 int (*program_init)(struct hermes *hw, u32 entry_point);
399 int (*program_end)(struct hermes *hw);
400 int (*program)(struct hermes *hw, const char *buf,
401 u32 addr, u32 len);
396 void (*lock_irqsave)(spinlock_t *lock, unsigned long *flags); 402 void (*lock_irqsave)(spinlock_t *lock, unsigned long *flags);
397 void (*unlock_irqrestore)(spinlock_t *lock, unsigned long *flags); 403 void (*unlock_irqrestore)(spinlock_t *lock, unsigned long *flags);
398 void (*lock_irq)(spinlock_t *lock); 404 void (*lock_irq)(spinlock_t *lock);
@@ -406,6 +412,7 @@ typedef struct hermes {
406#define HERMES_16BIT_REGSPACING 0 412#define HERMES_16BIT_REGSPACING 0
407#define HERMES_32BIT_REGSPACING 1 413#define HERMES_32BIT_REGSPACING 1
408 u16 inten; /* Which interrupts should be enabled? */ 414 u16 inten; /* Which interrupts should be enabled? */
415 bool eeprom_pda;
409 const struct hermes_ops *ops; 416 const struct hermes_ops *ops;
410 void *priv; 417 void *priv;
411} hermes_t; 418} hermes_t;
diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c
index 8f22e2026a82..6da85e75fce0 100644
--- a/drivers/net/wireless/orinoco/hermes_dld.c
+++ b/drivers/net/wireless/orinoco/hermes_dld.c
@@ -46,37 +46,11 @@
46 46
47#define PFX "hermes_dld: " 47#define PFX "hermes_dld: "
48 48
49/*
50 * AUX port access. To unlock the AUX port write the access keys to the
51 * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
52 * register. Then read it and make sure it's HERMES_AUX_ENABLED.
53 */
54#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
55#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
56#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
57#define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */
58
59#define HERMES_AUX_PW0 0xFE01
60#define HERMES_AUX_PW1 0xDC23
61#define HERMES_AUX_PW2 0xBA45
62
63/* HERMES_CMD_DOWNLD */
64#define HERMES_PROGRAM_DISABLE (0x0000 | HERMES_CMD_DOWNLD)
65#define HERMES_PROGRAM_ENABLE_VOLATILE (0x0100 | HERMES_CMD_DOWNLD)
66#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
67#define HERMES_PROGRAM_NON_VOLATILE (0x0300 | HERMES_CMD_DOWNLD)
68
69/* End markers used in dblocks */ 49/* End markers used in dblocks */
70#define PDI_END 0x00000000 /* End of PDA */ 50#define PDI_END 0x00000000 /* End of PDA */
71#define BLOCK_END 0xFFFFFFFF /* Last image block */ 51#define BLOCK_END 0xFFFFFFFF /* Last image block */
72#define TEXT_END 0x1A /* End of text header */ 52#define TEXT_END 0x1A /* End of text header */
73 53
74/* Limit the amout we try to download in a single shot.
75 * Size is in bytes.
76 */
77#define MAX_DL_SIZE 1024
78#define LIMIT_PROGRAM_SIZE 0
79
80/* 54/*
81 * The following structures have little-endian fields denoted by 55 * The following structures have little-endian fields denoted by
82 * the leading underscore. Don't access them directly - use inline 56 * the leading underscore. Don't access them directly - use inline
@@ -165,41 +139,6 @@ pdi_len(const struct pdi *pdi)
165 return 2 * (le16_to_cpu(pdi->len) - 1); 139 return 2 * (le16_to_cpu(pdi->len) - 1);
166} 140}
167 141
168/*** Hermes AUX control ***/
169
170static inline void
171hermes_aux_setaddr(hermes_t *hw, u32 addr)
172{
173 hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
174 hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
175}
176
177static inline int
178hermes_aux_control(hermes_t *hw, int enabled)
179{
180 int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
181 int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
182 int i;
183
184 /* Already open? */
185 if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state)
186 return 0;
187
188 hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
189 hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
190 hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
191 hermes_write_reg(hw, HERMES_CONTROL, action);
192
193 for (i = 0; i < 20; i++) {
194 udelay(10);
195 if (hermes_read_reg(hw, HERMES_CONTROL) ==
196 desired_state)
197 return 0;
198 }
199
200 return -EBUSY;
201}
202
203/*** Plug Data Functions ***/ 142/*** Plug Data Functions ***/
204 143
205/* 144/*
@@ -271,62 +210,7 @@ hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr,
271 return -EINVAL; 210 return -EINVAL;
272 211
273 /* do the actual plugging */ 212 /* do the actual plugging */
274 hermes_aux_setaddr(hw, pdr_addr(pdr)); 213 hw->ops->program(hw, pdi->data, pdr_addr(pdr), pdi_len(pdi));
275 hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi));
276
277 return 0;
278}
279
280/* Read PDA from the adapter */
281int hermes_read_pda(hermes_t *hw,
282 __le16 *pda,
283 u32 pda_addr,
284 u16 pda_len,
285 int use_eeprom) /* can we get this into hw? */
286{
287 int ret;
288 u16 pda_size;
289 u16 data_len = pda_len;
290 __le16 *data = pda;
291
292 if (use_eeprom) {
293 /* PDA of spectrum symbol is in eeprom */
294
295 /* Issue command to read EEPROM */
296 ret = hw->ops->cmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
297 if (ret)
298 return ret;
299 } else {
300 /* wl_lkm does not include PDA size in the PDA area.
301 * We will pad the information into pda, so other routines
302 * don't have to be modified */
303 pda[0] = cpu_to_le16(pda_len - 2);
304 /* Includes CFG_PROD_DATA but not itself */
305 pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
306 data_len = pda_len - 4;
307 data = pda + 2;
308 }
309
310 /* Open auxiliary port */
311 ret = hermes_aux_control(hw, 1);
312 pr_debug(PFX "AUX enable returned %d\n", ret);
313 if (ret)
314 return ret;
315
316 /* read PDA from EEPROM */
317 hermes_aux_setaddr(hw, pda_addr);
318 hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2);
319
320 /* Close aux port */
321 ret = hermes_aux_control(hw, 0);
322 pr_debug(PFX "AUX disable returned %d\n", ret);
323
324 /* Check PDA length */
325 pda_size = le16_to_cpu(pda[0]);
326 pr_debug(PFX "Actual PDA length %d, Max allowed %d\n",
327 pda_size, pda_len);
328 if (pda_size > pda_len)
329 return -EINVAL;
330 214
331 return 0; 215 return 0;
332} 216}
@@ -389,101 +273,13 @@ hermes_blocks_length(const char *first_block, const void *end)
389 273
390/*** Hermes programming ***/ 274/*** Hermes programming ***/
391 275
392/* About to start programming data (Hermes I)
393 * offset is the entry point
394 *
395 * Spectrum_cs' Symbol fw does not require this
396 * wl_lkm Agere fw does
397 * Don't know about intersil
398 */
399int hermesi_program_init(hermes_t *hw, u32 offset)
400{
401 int err;
402
403 /* Disable interrupts?*/
404 /*hw->inten = 0x0;*/
405 /*hermes_write_regn(hw, INTEN, 0);*/
406 /*hermes_set_irqmask(hw, 0);*/
407
408 /* Acknowledge any outstanding command */
409 hermes_write_regn(hw, EVACK, 0xFFFF);
410
411 /* Using init_cmd_wait rather than cmd_wait */
412 err = hw->ops->init_cmd_wait(hw,
413 0x0100 | HERMES_CMD_INIT,
414 0, 0, 0, NULL);
415 if (err)
416 return err;
417
418 err = hw->ops->init_cmd_wait(hw,
419 0x0000 | HERMES_CMD_INIT,
420 0, 0, 0, NULL);
421 if (err)
422 return err;
423
424 err = hermes_aux_control(hw, 1);
425 pr_debug(PFX "AUX enable returned %d\n", err);
426
427 if (err)
428 return err;
429
430 pr_debug(PFX "Enabling volatile, EP 0x%08x\n", offset);
431 err = hw->ops->init_cmd_wait(hw,
432 HERMES_PROGRAM_ENABLE_VOLATILE,
433 offset & 0xFFFFu,
434 offset >> 16,
435 0,
436 NULL);
437 pr_debug(PFX "PROGRAM_ENABLE returned %d\n", err);
438
439 return err;
440}
441
442/* Done programming data (Hermes I)
443 *
444 * Spectrum_cs' Symbol fw does not require this
445 * wl_lkm Agere fw does
446 * Don't know about intersil
447 */
448int hermesi_program_end(hermes_t *hw)
449{
450 struct hermes_response resp;
451 int rc = 0;
452 int err;
453
454 rc = hw->ops->cmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
455
456 pr_debug(PFX "PROGRAM_DISABLE returned %d, "
457 "r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
458 rc, resp.resp0, resp.resp1, resp.resp2);
459
460 if ((rc == 0) &&
461 ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
462 rc = -EIO;
463
464 err = hermes_aux_control(hw, 0);
465 pr_debug(PFX "AUX disable returned %d\n", err);
466
467 /* Acknowledge any outstanding command */
468 hermes_write_regn(hw, EVACK, 0xFFFF);
469
470 /* Reinitialise, ignoring return */
471 (void) hw->ops->init_cmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
472 0, 0, 0, NULL);
473
474 return rc ? rc : err;
475}
476
477/* Program the data blocks */ 276/* Program the data blocks */
478int hermes_program(hermes_t *hw, const char *first_block, const void *end) 277int hermes_program(hermes_t *hw, const char *first_block, const void *end)
479{ 278{
480 const struct dblock *blk; 279 const struct dblock *blk;
481 u32 blkaddr; 280 u32 blkaddr;
482 u32 blklen; 281 u32 blklen;
483#if LIMIT_PROGRAM_SIZE 282 int err = 0;
484 u32 addr;
485 u32 len;
486#endif
487 283
488 blk = (const struct dblock *) first_block; 284 blk = (const struct dblock *) first_block;
489 285
@@ -498,30 +294,10 @@ int hermes_program(hermes_t *hw, const char *first_block, const void *end)
498 pr_debug(PFX "Programming block of length %d " 294 pr_debug(PFX "Programming block of length %d "
499 "to address 0x%08x\n", blklen, blkaddr); 295 "to address 0x%08x\n", blklen, blkaddr);
500 296
501#if !LIMIT_PROGRAM_SIZE 297 err = hw->ops->program(hw, blk->data, blkaddr, blklen);
502 /* wl_lkm driver splits this into writes of 2000 bytes */ 298 if (err)
503 hermes_aux_setaddr(hw, blkaddr); 299 break;
504 hermes_write_bytes(hw, HERMES_AUXDATA, blk->data, 300
505 blklen);
506#else
507 len = (blklen < MAX_DL_SIZE) ? blklen : MAX_DL_SIZE;
508 addr = blkaddr;
509
510 while (addr < (blkaddr + blklen)) {
511 pr_debug(PFX "Programming subblock of length %d "
512 "to address 0x%08x. Data @ %p\n",
513 len, addr, &blk->data[addr - blkaddr]);
514
515 hermes_aux_setaddr(hw, addr);
516 hermes_write_bytes(hw, HERMES_AUXDATA,
517 &blk->data[addr - blkaddr],
518 len);
519
520 addr += len;
521 len = ((blkaddr + blklen - addr) < MAX_DL_SIZE) ?
522 (blkaddr + blklen - addr) : MAX_DL_SIZE;
523 }
524#endif
525 blk = (const struct dblock *) &blk->data[blklen]; 301 blk = (const struct dblock *) &blk->data[blklen];
526 302
527 if ((void *) blk > (end - sizeof(*blk))) 303 if ((void *) blk > (end - sizeof(*blk)))
@@ -530,7 +306,7 @@ int hermes_program(hermes_t *hw, const char *first_block, const void *end)
530 blkaddr = dblock_addr(blk); 306 blkaddr = dblock_addr(blk);
531 blklen = dblock_len(blk); 307 blklen = dblock_len(blk);
532 } 308 }
533 return 0; 309 return err;
534} 310}
535 311
536/*** Default plugging data for Hermes I ***/ 312/*** Default plugging data for Hermes I ***/
@@ -690,9 +466,8 @@ int hermes_apply_pda_with_defaults(hermes_t *hw,
690 if ((pdi_len(pdi) == pdr_len(pdr)) && 466 if ((pdi_len(pdi) == pdr_len(pdr)) &&
691 ((void *) pdi->data + pdi_len(pdi) < pda_end)) { 467 ((void *) pdi->data + pdi_len(pdi) < pda_end)) {
692 /* do the actual plugging */ 468 /* do the actual plugging */
693 hermes_aux_setaddr(hw, pdr_addr(pdr)); 469 hw->ops->program(hw, pdi->data, pdr_addr(pdr),
694 hermes_write_bytes(hw, HERMES_AUXDATA, 470 pdi_len(pdi));
695 pdi->data, pdi_len(pdi));
696 } 471 }
697 } 472 }
698 473
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index 8e1b31cbd375..e22093359f3e 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -184,6 +184,11 @@ MODULE_FIRMWARE("orinoco_ezusb_fw");
184#define EZUSB_RID_RX 0x0701 184#define EZUSB_RID_RX 0x0701
185#define EZUSB_RID_INIT1 0x0702 185#define EZUSB_RID_INIT1 0x0702
186#define EZUSB_RID_ACK 0x0710 186#define EZUSB_RID_ACK 0x0710
187#define EZUSB_RID_READ_PDA 0x0800
188#define EZUSB_RID_PROG_INIT 0x0852
189#define EZUSB_RID_PROG_SET_ADDR 0x0853
190#define EZUSB_RID_PROG_BYTES 0x0854
191#define EZUSB_RID_PROG_END 0x0855
187#define EZUSB_RID_DOCMD 0x0860 192#define EZUSB_RID_DOCMD 0x0860
188 193
189/* Recognize info frames */ 194/* Recognize info frames */
@@ -198,6 +203,8 @@ MODULE_FIRMWARE("orinoco_ezusb_fw");
198 203
199#define BULK_BUF_SIZE 2048 204#define BULK_BUF_SIZE 2048
200 205
206#define MAX_DL_SIZE (BULK_BUF_SIZE - sizeof(struct ezusb_packet))
207
201#define FW_BUF_SIZE 64 208#define FW_BUF_SIZE 64
202#define FW_VAR_OFFSET_PTR 0x359 209#define FW_VAR_OFFSET_PTR 0x359
203#define FW_VAR_VALUE 0 210#define FW_VAR_VALUE 0
@@ -1077,6 +1084,115 @@ static int ezusb_bap_pread(struct hermes *hw, int bap,
1077 return 0; 1084 return 0;
1078} 1085}
1079 1086
1087static int ezusb_read_pda(struct hermes *hw, __le16 *pda,
1088 u32 pda_addr, u16 pda_len)
1089{
1090 struct ezusb_priv *upriv = hw->priv;
1091 struct request_context *ctx;
1092 __le16 data[] = {
1093 cpu_to_le16(pda_addr & 0xffff),
1094 cpu_to_le16(pda_len - 4)
1095 };
1096 ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_READ_PDA, EZUSB_RID_READ_PDA);
1097 if (!ctx)
1098 return -ENOMEM;
1099
1100 /* wl_lkm does not include PDA size in the PDA area.
1101 * We will pad the information into pda, so other routines
1102 * don't have to be modified */
1103 pda[0] = cpu_to_le16(pda_len - 2);
1104 /* Includes CFG_PROD_DATA but not itself */
1105 pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
1106
1107 return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
1108 EZUSB_FRAME_CONTROL, &pda[2], pda_len - 4,
1109 NULL);
1110}
1111
1112static int ezusb_program_init(struct hermes *hw, u32 entry_point)
1113{
1114 struct ezusb_priv *upriv = hw->priv;
1115 struct request_context *ctx;
1116 __le32 data = cpu_to_le32(entry_point);
1117
1118 ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_INIT, EZUSB_RID_ACK);
1119 if (!ctx)
1120 return -ENOMEM;
1121
1122 return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
1123 EZUSB_FRAME_CONTROL, NULL, 0, NULL);
1124}
1125
1126static int ezusb_program_end(struct hermes *hw)
1127{
1128 struct ezusb_priv *upriv = hw->priv;
1129 struct request_context *ctx;
1130
1131 ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_END, EZUSB_RID_ACK);
1132 if (!ctx)
1133 return -ENOMEM;
1134
1135 return ezusb_access_ltv(upriv, ctx, 0, NULL,
1136 EZUSB_FRAME_CONTROL, NULL, 0, NULL);
1137}
1138
1139static int ezusb_program_bytes(struct hermes *hw, const char *buf,
1140 u32 addr, u32 len)
1141{
1142 struct ezusb_priv *upriv = hw->priv;
1143 struct request_context *ctx;
1144 __le32 data = cpu_to_le32(addr);
1145 int err;
1146
1147 ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_SET_ADDR, EZUSB_RID_ACK);
1148 if (!ctx)
1149 return -ENOMEM;
1150
1151 err = ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
1152 EZUSB_FRAME_CONTROL, NULL, 0, NULL);
1153 if (err)
1154 return err;
1155
1156 ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_BYTES, EZUSB_RID_ACK);
1157 if (!ctx)
1158 return -ENOMEM;
1159
1160 return ezusb_access_ltv(upriv, ctx, len, buf,
1161 EZUSB_FRAME_CONTROL, NULL, 0, NULL);
1162}
1163
1164static int ezusb_program(struct hermes *hw, const char *buf,
1165 u32 addr, u32 len)
1166{
1167 u32 ch_addr;
1168 u32 ch_len;
1169 int err = 0;
1170
1171 /* We can only send 2048 bytes out of the bulk xmit at a time,
1172 * so we have to split any programming into chunks of <2048
1173 * bytes. */
1174
1175 ch_len = (len < MAX_DL_SIZE) ? len : MAX_DL_SIZE;
1176 ch_addr = addr;
1177
1178 while (ch_addr < (addr + len)) {
1179 pr_debug("Programming subblock of length %d "
1180 "to address 0x%08x. Data @ %p\n",
1181 ch_len, ch_addr, &buf[ch_addr - addr]);
1182
1183 err = ezusb_program_bytes(hw, &buf[ch_addr - addr],
1184 ch_addr, ch_len);
1185 if (err)
1186 break;
1187
1188 ch_addr += ch_len;
1189 ch_len = ((addr + len - ch_addr) < MAX_DL_SIZE) ?
1190 (addr + len - ch_addr) : MAX_DL_SIZE;
1191 }
1192
1193 return err;
1194}
1195
1080static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) 1196static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev)
1081{ 1197{
1082 struct orinoco_private *priv = ndev_priv(dev); 1198 struct orinoco_private *priv = ndev_priv(dev);
@@ -1440,6 +1556,10 @@ static const struct hermes_ops ezusb_ops = {
1440 .read_ltv = ezusb_read_ltv, 1556 .read_ltv = ezusb_read_ltv,
1441 .write_ltv = ezusb_write_ltv, 1557 .write_ltv = ezusb_write_ltv,
1442 .bap_pread = ezusb_bap_pread, 1558 .bap_pread = ezusb_bap_pread,
1559 .read_pda = ezusb_read_pda,
1560 .program_init = ezusb_program_init,
1561 .program_end = ezusb_program_end,
1562 .program = ezusb_program,
1443 .lock_irqsave = ezusb_lock_irqsave, 1563 .lock_irqsave = ezusb_lock_irqsave,
1444 .unlock_irqrestore = ezusb_unlock_irqrestore, 1564 .unlock_irqrestore = ezusb_unlock_irqrestore,
1445 .lock_irq = ezusb_lock_irq, 1565 .lock_irq = ezusb_lock_irq,
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index b4f68ef771e4..9b1af4976bf5 100644
--- a/drivers/net/wireless/orinoco/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -349,6 +349,7 @@ spectrum_cs_config(struct pcmcia_device *link)
349 goto failed; 349 goto failed;
350 350
351 hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); 351 hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
352 hw->eeprom_pda = true;
352 353
353 /* 354 /*
354 * This actually configures the PCMCIA socket -- setting up 355 * This actually configures the PCMCIA socket -- setting up