diff options
Diffstat (limited to 'drivers/net/wireless/orinoco/orinoco_usb.c')
-rw-r--r-- | drivers/net/wireless/orinoco/orinoco_usb.c | 120 |
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 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 | ||
1087 | static 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 | |||
1112 | static 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 | |||
1126 | static 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 | |||
1139 | static 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 | |||
1164 | static 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 | |||
1080 | static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) | 1196 | static 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, |