aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco/orinoco_usb.c
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/net/wireless/orinoco/orinoco_usb.c
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/net/wireless/orinoco/orinoco_usb.c')
-rw-r--r--drivers/net/wireless/orinoco/orinoco_usb.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index 8e1b31cbd37..e22093359f3 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,