Commit | Line | Data |
---|---|---|
80aba536 | 1 | #include "wb35reg_f.h" |
717d812f | 2 | #include "phy_calibration.h" |
80aba536 PE |
3 | |
4 | #include <linux/usb.h> | |
5a0e3ad6 | 5 | #include <linux/slab.h> |
66101de1 | 6 | |
fa448c1f LL |
7 | /* |
8 | * true : read command process successfully | |
9 | * false : register not support | |
10 | * RegisterNo : start base | |
11 | * pRegisterData : data point | |
12 | * NumberOfData : number of register data | |
13 | * Flag : AUTO_INCREMENT - RegisterNo will auto increment 4 | |
14 | * NO_INCREMENT - Function will write data into the same register | |
15 | */ | |
6bd50336 IP |
16 | unsigned char Wb35Reg_BurstWrite(struct hw_data *pHwData, u16 RegisterNo, |
17 | u32 *pRegisterData, u8 NumberOfData, u8 Flag) | |
66101de1 | 18 | { |
fa448c1f LL |
19 | struct wb35_reg *reg = &pHwData->reg; |
20 | struct urb *urb = NULL; | |
21 | struct wb35_reg_queue *reg_queue = NULL; | |
22 | u16 UrbSize; | |
23 | struct usb_ctrlrequest *dr; | |
24 | u16 i, DataSize = NumberOfData * 4; | |
25 | ||
26 | /* Module shutdown */ | |
66101de1 | 27 | if (pHwData->SurpriseRemove) |
279b6ccc | 28 | return false; |
66101de1 | 29 | |
fa448c1f | 30 | /* Trying to use burst write function if use new hardware */ |
f37435ce | 31 | UrbSize = sizeof(struct wb35_reg_queue) + DataSize + sizeof(struct usb_ctrlrequest); |
c8b2b70b | 32 | reg_queue = kzalloc(UrbSize, GFP_ATOMIC); |
d3d472b6 HK |
33 | if (reg_queue == NULL) |
34 | return false; | |
35 | ||
f3d20188 | 36 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
d3d472b6 | 37 | if (urb == NULL) { |
4d527a7a | 38 | kfree(reg_queue); |
279b6ccc | 39 | return false; |
66101de1 | 40 | } |
d3d472b6 HK |
41 | |
42 | reg_queue->DIRECT = 2; /* burst write register */ | |
43 | reg_queue->INDEX = RegisterNo; | |
44 | reg_queue->pBuffer = (u32 *)((u8 *)reg_queue + sizeof(struct wb35_reg_queue)); | |
45 | memcpy(reg_queue->pBuffer, pRegisterData, DataSize); | |
46 | /* the function for reversing register data from little endian to big endian */ | |
5cca8c01 | 47 | for (i = 0; i < NumberOfData; i++) |
d3d472b6 HK |
48 | reg_queue->pBuffer[i] = cpu_to_le32(reg_queue->pBuffer[i]); |
49 | ||
50 | dr = (struct usb_ctrlrequest *)((u8 *)reg_queue + sizeof(struct wb35_reg_queue) + DataSize); | |
51 | dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE; | |
52 | dr->bRequest = 0x04; /* USB or vendor-defined request code, burst mode */ | |
53 | dr->wValue = cpu_to_le16(Flag); /* 0: Register number auto-increment, 1: No auto increment */ | |
54 | dr->wIndex = cpu_to_le16(RegisterNo); | |
55 | dr->wLength = cpu_to_le16(DataSize); | |
56 | reg_queue->Next = NULL; | |
57 | reg_queue->pUsbReq = dr; | |
58 | reg_queue->urb = urb; | |
59 | ||
60 | spin_lock_irq(®->EP0VM_spin_lock); | |
61 | if (reg->reg_first == NULL) | |
62 | reg->reg_first = reg_queue; | |
63 | else | |
64 | reg->reg_last->Next = reg_queue; | |
65 | reg->reg_last = reg_queue; | |
66 | ||
67 | spin_unlock_irq(®->EP0VM_spin_lock); | |
68 | ||
69 | /* Start EP0VM */ | |
70 | Wb35Reg_EP0VM_start(pHwData); | |
71 | ||
72 | return true; | |
66101de1 PM |
73 | } |
74 | ||
6bd50336 | 75 | void Wb35Reg_Update(struct hw_data *pHwData, u16 RegisterNo, u32 RegisterValue) |
66101de1 | 76 | { |
65144de7 | 77 | struct wb35_reg *reg = &pHwData->reg; |
66101de1 | 78 | switch (RegisterNo) { |
65144de7 PE |
79 | case 0x3b0: reg->U1B0 = RegisterValue; break; |
80 | case 0x3bc: reg->U1BC_LEDConfigure = RegisterValue; break; | |
81 | case 0x400: reg->D00_DmaControl = RegisterValue; break; | |
82 | case 0x800: reg->M00_MacControl = RegisterValue; break; | |
83 | case 0x804: reg->M04_MulticastAddress1 = RegisterValue; break; | |
84 | case 0x808: reg->M08_MulticastAddress2 = RegisterValue; break; | |
85 | case 0x824: reg->M24_MacControl = RegisterValue; break; | |
86 | case 0x828: reg->M28_MacControl = RegisterValue; break; | |
87 | case 0x82c: reg->M2C_MacControl = RegisterValue; break; | |
88 | case 0x838: reg->M38_MacControl = RegisterValue; break; | |
89 | case 0x840: reg->M40_MacControl = RegisterValue; break; | |
90 | case 0x844: reg->M44_MacControl = RegisterValue; break; | |
91 | case 0x848: reg->M48_MacControl = RegisterValue; break; | |
92 | case 0x84c: reg->M4C_MacStatus = RegisterValue; break; | |
93 | case 0x860: reg->M60_MacControl = RegisterValue; break; | |
94 | case 0x868: reg->M68_MacControl = RegisterValue; break; | |
95 | case 0x870: reg->M70_MacControl = RegisterValue; break; | |
96 | case 0x874: reg->M74_MacControl = RegisterValue; break; | |
97 | case 0x878: reg->M78_ERPInformation = RegisterValue; break; | |
98 | case 0x87C: reg->M7C_MacControl = RegisterValue; break; | |
99 | case 0x880: reg->M80_MacControl = RegisterValue; break; | |
100 | case 0x884: reg->M84_MacControl = RegisterValue; break; | |
101 | case 0x888: reg->M88_MacControl = RegisterValue; break; | |
102 | case 0x898: reg->M98_MacControl = RegisterValue; break; | |
103 | case 0x100c: reg->BB0C = RegisterValue; break; | |
104 | case 0x102c: reg->BB2C = RegisterValue; break; | |
105 | case 0x1030: reg->BB30 = RegisterValue; break; | |
106 | case 0x103c: reg->BB3C = RegisterValue; break; | |
107 | case 0x1048: reg->BB48 = RegisterValue; break; | |
108 | case 0x104c: reg->BB4C = RegisterValue; break; | |
109 | case 0x1050: reg->BB50 = RegisterValue; break; | |
110 | case 0x1054: reg->BB54 = RegisterValue; break; | |
111 | case 0x1058: reg->BB58 = RegisterValue; break; | |
112 | case 0x105c: reg->BB5C = RegisterValue; break; | |
113 | case 0x1060: reg->BB60 = RegisterValue; break; | |
66101de1 PM |
114 | } |
115 | } | |
116 | ||
fa448c1f LL |
117 | /* |
118 | * true : read command process successfully | |
119 | * false : register not support | |
120 | */ | |
6bd50336 IP |
121 | unsigned char Wb35Reg_WriteSync(struct hw_data *pHwData, u16 RegisterNo, |
122 | u32 RegisterValue) | |
66101de1 | 123 | { |
65144de7 | 124 | struct wb35_reg *reg = &pHwData->reg; |
66101de1 PM |
125 | int ret = -1; |
126 | ||
fa448c1f | 127 | /* Module shutdown */ |
66101de1 | 128 | if (pHwData->SurpriseRemove) |
279b6ccc | 129 | return false; |
66101de1 PM |
130 | |
131 | RegisterValue = cpu_to_le32(RegisterValue); | |
132 | ||
fa448c1f | 133 | /* update the register by send usb message */ |
65144de7 | 134 | reg->SyncIoPause = 1; |
66101de1 | 135 | |
fa448c1f | 136 | /* Wait until EP0VM stop */ |
65144de7 | 137 | while (reg->EP0vm_state != VM_STOP) |
34222e0a | 138 | msleep(10); |
66101de1 | 139 | |
fa448c1f | 140 | /* Sync IoCallDriver */ |
65144de7 | 141 | reg->EP0vm_state = VM_RUNNING; |
2894c6cd | 142 | ret = usb_control_msg(pHwData->udev, |
6bd50336 IP |
143 | usb_sndctrlpipe(pHwData->udev, 0), |
144 | 0x03, | |
145 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | |
146 | 0x0, RegisterNo, &RegisterValue, 4, HZ * 100); | |
65144de7 PE |
147 | reg->EP0vm_state = VM_STOP; |
148 | reg->SyncIoPause = 0; | |
66101de1 PM |
149 | |
150 | Wb35Reg_EP0VM_start(pHwData); | |
151 | ||
152 | if (ret < 0) { | |
2855bb79 | 153 | pr_debug("EP0 Write register usb message sending error\n"); |
fa448c1f | 154 | pHwData->SurpriseRemove = 1; |
279b6ccc | 155 | return false; |
66101de1 | 156 | } |
279b6ccc | 157 | return true; |
66101de1 PM |
158 | } |
159 | ||
fa448c1f LL |
160 | /* |
161 | * true : read command process successfully | |
162 | * false : register not support | |
163 | */ | |
6bd50336 IP |
164 | unsigned char Wb35Reg_Write(struct hw_data *pHwData, u16 RegisterNo, |
165 | u32 RegisterValue) | |
66101de1 | 166 | { |
fa448c1f LL |
167 | struct wb35_reg *reg = &pHwData->reg; |
168 | struct usb_ctrlrequest *dr; | |
169 | struct urb *urb = NULL; | |
170 | struct wb35_reg_queue *reg_queue = NULL; | |
171 | u16 UrbSize; | |
66101de1 | 172 | |
fa448c1f | 173 | /* Module shutdown */ |
66101de1 | 174 | if (pHwData->SurpriseRemove) |
279b6ccc | 175 | return false; |
66101de1 | 176 | |
fa448c1f | 177 | /* update the register by send urb request */ |
f37435ce | 178 | UrbSize = sizeof(struct wb35_reg_queue) + sizeof(struct usb_ctrlrequest); |
c8b2b70b | 179 | reg_queue = kzalloc(UrbSize, GFP_ATOMIC); |
d3d472b6 HK |
180 | if (reg_queue == NULL) |
181 | return false; | |
182 | ||
f3d20188 | 183 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
d3d472b6 | 184 | if (urb == NULL) { |
f37435ce | 185 | kfree(reg_queue); |
279b6ccc | 186 | return false; |
66101de1 | 187 | } |
d3d472b6 HK |
188 | |
189 | reg_queue->DIRECT = 1; /* burst write register */ | |
190 | reg_queue->INDEX = RegisterNo; | |
191 | reg_queue->VALUE = cpu_to_le32(RegisterValue); | |
192 | reg_queue->RESERVED_VALID = false; | |
193 | dr = (struct usb_ctrlrequest *)((u8 *)reg_queue + sizeof(struct wb35_reg_queue)); | |
194 | dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE; | |
195 | dr->bRequest = 0x03; /* USB or vendor-defined request code, burst mode */ | |
196 | dr->wValue = cpu_to_le16(0x0); | |
197 | dr->wIndex = cpu_to_le16(RegisterNo); | |
198 | dr->wLength = cpu_to_le16(4); | |
199 | ||
200 | /* Enter the sending queue */ | |
201 | reg_queue->Next = NULL; | |
202 | reg_queue->pUsbReq = dr; | |
203 | reg_queue->urb = urb; | |
204 | ||
205 | spin_lock_irq(®->EP0VM_spin_lock); | |
206 | if (reg->reg_first == NULL) | |
207 | reg->reg_first = reg_queue; | |
208 | else | |
209 | reg->reg_last->Next = reg_queue; | |
210 | reg->reg_last = reg_queue; | |
211 | ||
212 | spin_unlock_irq(®->EP0VM_spin_lock); | |
213 | ||
214 | /* Start EP0VM */ | |
215 | Wb35Reg_EP0VM_start(pHwData); | |
216 | ||
217 | return true; | |
66101de1 PM |
218 | } |
219 | ||
fa448c1f LL |
220 | /* |
221 | * This command will be executed with a user defined value. When it completes, | |
222 | * this value is useful. For example, hal_set_current_channel will use it. | |
223 | * true : read command process successfully | |
a31f7f5f | 224 | * false : register not supported |
fa448c1f LL |
225 | */ |
226 | unsigned char Wb35Reg_WriteWithCallbackValue(struct hw_data *pHwData, | |
227 | u16 RegisterNo, | |
228 | u32 RegisterValue, | |
229 | s8 *pValue, | |
230 | s8 Len) | |
66101de1 | 231 | { |
fa448c1f LL |
232 | struct wb35_reg *reg = &pHwData->reg; |
233 | struct usb_ctrlrequest *dr; | |
234 | struct urb *urb = NULL; | |
235 | struct wb35_reg_queue *reg_queue = NULL; | |
236 | u16 UrbSize; | |
66101de1 | 237 | |
fa448c1f | 238 | /* Module shutdown */ |
66101de1 | 239 | if (pHwData->SurpriseRemove) |
279b6ccc | 240 | return false; |
66101de1 | 241 | |
fa448c1f | 242 | /* update the register by send urb request */ |
f37435ce | 243 | UrbSize = sizeof(struct wb35_reg_queue) + sizeof(struct usb_ctrlrequest); |
c8b2b70b | 244 | reg_queue = kzalloc(UrbSize, GFP_ATOMIC); |
d3d472b6 HK |
245 | if (reg_queue == NULL) |
246 | return false; | |
247 | ||
f3d20188 | 248 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
d3d472b6 | 249 | if (urb == NULL) { |
f37435ce | 250 | kfree(reg_queue); |
279b6ccc | 251 | return false; |
66101de1 | 252 | } |
d3d472b6 HK |
253 | |
254 | reg_queue->DIRECT = 1; /* burst write register */ | |
255 | reg_queue->INDEX = RegisterNo; | |
256 | reg_queue->VALUE = cpu_to_le32(RegisterValue); | |
257 | /* NOTE : Users must guarantee the size of value will not exceed the buffer size. */ | |
258 | memcpy(reg_queue->RESERVED, pValue, Len); | |
259 | reg_queue->RESERVED_VALID = true; | |
260 | dr = (struct usb_ctrlrequest *)((u8 *)reg_queue + sizeof(struct wb35_reg_queue)); | |
261 | dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE; | |
262 | dr->bRequest = 0x03; /* USB or vendor-defined request code, burst mode */ | |
263 | dr->wValue = cpu_to_le16(0x0); | |
264 | dr->wIndex = cpu_to_le16(RegisterNo); | |
265 | dr->wLength = cpu_to_le16(4); | |
266 | ||
267 | /* Enter the sending queue */ | |
268 | reg_queue->Next = NULL; | |
269 | reg_queue->pUsbReq = dr; | |
270 | reg_queue->urb = urb; | |
271 | spin_lock_irq(®->EP0VM_spin_lock); | |
272 | if (reg->reg_first == NULL) | |
273 | reg->reg_first = reg_queue; | |
274 | else | |
275 | reg->reg_last->Next = reg_queue; | |
276 | reg->reg_last = reg_queue; | |
277 | ||
278 | spin_unlock_irq(®->EP0VM_spin_lock); | |
279 | ||
280 | /* Start EP0VM */ | |
281 | Wb35Reg_EP0VM_start(pHwData); | |
282 | ||
283 | return true; | |
66101de1 PM |
284 | } |
285 | ||
fa448c1f LL |
286 | /* |
287 | * true : read command process successfully | |
288 | * false : register not support | |
289 | * pRegisterValue : It must be a resident buffer due to | |
290 | * asynchronous read register. | |
291 | */ | |
6bd50336 IP |
292 | unsigned char Wb35Reg_ReadSync(struct hw_data *pHwData, u16 RegisterNo, |
293 | u32 *pRegisterValue) | |
66101de1 | 294 | { |
65144de7 | 295 | struct wb35_reg *reg = &pHwData->reg; |
fa448c1f LL |
296 | u32 *pltmp = pRegisterValue; |
297 | int ret = -1; | |
66101de1 | 298 | |
fa448c1f | 299 | /* Module shutdown */ |
66101de1 | 300 | if (pHwData->SurpriseRemove) |
279b6ccc | 301 | return false; |
66101de1 | 302 | |
fa448c1f | 303 | /* Read the register by send usb message */ |
65144de7 | 304 | reg->SyncIoPause = 1; |
66101de1 | 305 | |
fa448c1f | 306 | /* Wait until EP0VM stop */ |
65144de7 | 307 | while (reg->EP0vm_state != VM_STOP) |
34222e0a | 308 | msleep(10); |
66101de1 | 309 | |
65144de7 | 310 | reg->EP0vm_state = VM_RUNNING; |
2894c6cd | 311 | ret = usb_control_msg(pHwData->udev, |
6bd50336 IP |
312 | usb_rcvctrlpipe(pHwData->udev, 0), |
313 | 0x01, | |
314 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | |
315 | 0x0, RegisterNo, pltmp, 4, HZ * 100); | |
66101de1 PM |
316 | |
317 | *pRegisterValue = cpu_to_le32(*pltmp); | |
318 | ||
65144de7 | 319 | reg->EP0vm_state = VM_STOP; |
66101de1 | 320 | |
fa448c1f | 321 | Wb35Reg_Update(pHwData, RegisterNo, *pRegisterValue); |
65144de7 | 322 | reg->SyncIoPause = 0; |
66101de1 | 323 | |
fa448c1f | 324 | Wb35Reg_EP0VM_start(pHwData); |
66101de1 PM |
325 | |
326 | if (ret < 0) { | |
2855bb79 | 327 | pr_debug("EP0 Read register usb message sending error\n"); |
fa448c1f | 328 | pHwData->SurpriseRemove = 1; |
279b6ccc | 329 | return false; |
66101de1 | 330 | } |
279b6ccc | 331 | return true; |
66101de1 PM |
332 | } |
333 | ||
fa448c1f LL |
334 | /* |
335 | * true : read command process successfully | |
336 | * false : register not support | |
337 | * pRegisterValue : It must be a resident buffer due to | |
338 | * asynchronous read register. | |
339 | */ | |
6bd50336 IP |
340 | unsigned char Wb35Reg_Read(struct hw_data *pHwData, u16 RegisterNo, |
341 | u32 *pRegisterValue) | |
66101de1 | 342 | { |
fa448c1f LL |
343 | struct wb35_reg *reg = &pHwData->reg; |
344 | struct usb_ctrlrequest *dr; | |
345 | struct urb *urb; | |
346 | struct wb35_reg_queue *reg_queue; | |
347 | u16 UrbSize; | |
66101de1 | 348 | |
fa448c1f | 349 | /* Module shutdown */ |
66101de1 | 350 | if (pHwData->SurpriseRemove) |
279b6ccc | 351 | return false; |
66101de1 | 352 | |
fa448c1f | 353 | /* update the variable by send Urb to read register */ |
f37435ce | 354 | UrbSize = sizeof(struct wb35_reg_queue) + sizeof(struct usb_ctrlrequest); |
c8b2b70b | 355 | reg_queue = kzalloc(UrbSize, GFP_ATOMIC); |
d3d472b6 HK |
356 | if (reg_queue == NULL) |
357 | return false; | |
358 | ||
f3d20188 | 359 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
d3d472b6 | 360 | if (urb == NULL) { |
f37435ce | 361 | kfree(reg_queue); |
279b6ccc | 362 | return false; |
66101de1 | 363 | } |
d3d472b6 HK |
364 | reg_queue->DIRECT = 0; /* read register */ |
365 | reg_queue->INDEX = RegisterNo; | |
366 | reg_queue->pBuffer = pRegisterValue; | |
367 | dr = (struct usb_ctrlrequest *)((u8 *)reg_queue + sizeof(struct wb35_reg_queue)); | |
368 | dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN; | |
369 | dr->bRequest = 0x01; /* USB or vendor-defined request code, burst mode */ | |
370 | dr->wValue = cpu_to_le16(0x0); | |
371 | dr->wIndex = cpu_to_le16(RegisterNo); | |
372 | dr->wLength = cpu_to_le16(4); | |
373 | ||
374 | /* Enter the sending queue */ | |
375 | reg_queue->Next = NULL; | |
376 | reg_queue->pUsbReq = dr; | |
377 | reg_queue->urb = urb; | |
378 | spin_lock_irq(®->EP0VM_spin_lock); | |
379 | if (reg->reg_first == NULL) | |
380 | reg->reg_first = reg_queue; | |
381 | else | |
382 | reg->reg_last->Next = reg_queue; | |
383 | reg->reg_last = reg_queue; | |
384 | ||
385 | spin_unlock_irq(®->EP0VM_spin_lock); | |
386 | ||
387 | /* Start EP0VM */ | |
388 | Wb35Reg_EP0VM_start(pHwData); | |
389 | ||
390 | return true; | |
66101de1 PM |
391 | } |
392 | ||
393 | ||
fa448c1f | 394 | void Wb35Reg_EP0VM_start(struct hw_data *pHwData) |
66101de1 | 395 | { |
65144de7 | 396 | struct wb35_reg *reg = &pHwData->reg; |
66101de1 | 397 | |
44e8541c | 398 | if (atomic_inc_return(®->RegFireCount) == 1) { |
65144de7 | 399 | reg->EP0vm_state = VM_RUNNING; |
66101de1 PM |
400 | Wb35Reg_EP0VM(pHwData); |
401 | } else | |
44e8541c | 402 | atomic_dec(®->RegFireCount); |
66101de1 PM |
403 | } |
404 | ||
fa448c1f | 405 | void Wb35Reg_EP0VM(struct hw_data *pHwData) |
66101de1 | 406 | { |
fa448c1f LL |
407 | struct wb35_reg *reg = &pHwData->reg; |
408 | struct urb *urb; | |
409 | struct usb_ctrlrequest *dr; | |
410 | u32 *pBuffer; | |
66101de1 | 411 | int ret = -1; |
fa448c1f | 412 | struct wb35_reg_queue *reg_queue; |
66101de1 PM |
413 | |
414 | ||
65144de7 | 415 | if (reg->SyncIoPause) |
66101de1 PM |
416 | goto cleanup; |
417 | ||
418 | if (pHwData->SurpriseRemove) | |
419 | goto cleanup; | |
420 | ||
fa448c1f LL |
421 | /* Get the register data and send to USB through Irp */ |
422 | spin_lock_irq(®->EP0VM_spin_lock); | |
65144de7 | 423 | reg_queue = reg->reg_first; |
fa448c1f | 424 | spin_unlock_irq(®->EP0VM_spin_lock); |
66101de1 | 425 | |
f37435ce | 426 | if (!reg_queue) |
66101de1 PM |
427 | goto cleanup; |
428 | ||
fa448c1f | 429 | /* Get an Urb, send it */ |
f37435ce | 430 | urb = (struct urb *)reg_queue->urb; |
66101de1 | 431 | |
f37435ce PE |
432 | dr = reg_queue->pUsbReq; |
433 | urb = reg_queue->urb; | |
434 | pBuffer = reg_queue->pBuffer; | |
fa448c1f | 435 | if (reg_queue->DIRECT == 1) /* output */ |
f37435ce | 436 | pBuffer = ®_queue->VALUE; |
66101de1 | 437 | |
2894c6cd PE |
438 | usb_fill_control_urb(urb, pHwData->udev, |
439 | REG_DIRECTION(pHwData->udev, reg_queue), | |
fa448c1f LL |
440 | (u8 *)dr, pBuffer, cpu_to_le16(dr->wLength), |
441 | Wb35Reg_EP0VM_complete, (void *)pHwData); | |
66101de1 | 442 | |
65144de7 | 443 | reg->EP0vm_state = VM_RUNNING; |
66101de1 | 444 | |
7c126043 | 445 | ret = usb_submit_urb(urb, GFP_ATOMIC); |
66101de1 PM |
446 | |
447 | if (ret < 0) { | |
2855bb79 | 448 | pr_debug("EP0 Irp sending error\n"); |
66101de1 PM |
449 | goto cleanup; |
450 | } | |
66101de1 PM |
451 | return; |
452 | ||
453 | cleanup: | |
65144de7 | 454 | reg->EP0vm_state = VM_STOP; |
44e8541c | 455 | atomic_dec(®->RegFireCount); |
66101de1 PM |
456 | } |
457 | ||
458 | ||
fa448c1f | 459 | void Wb35Reg_EP0VM_complete(struct urb *urb) |
66101de1 | 460 | { |
fa448c1f LL |
461 | struct hw_data *pHwData = (struct hw_data *)urb->context; |
462 | struct wb35_reg *reg = &pHwData->reg; | |
463 | struct wb35_reg_queue *reg_queue; | |
66101de1 PM |
464 | |
465 | ||
fa448c1f | 466 | /* Variable setting */ |
65144de7 PE |
467 | reg->EP0vm_state = VM_COMPLETED; |
468 | reg->EP0VM_status = urb->status; | |
66101de1 | 469 | |
fa448c1f | 470 | if (pHwData->SurpriseRemove) { /* Let WbWlanHalt to handle surprise remove */ |
65144de7 | 471 | reg->EP0vm_state = VM_STOP; |
44e8541c | 472 | atomic_dec(®->RegFireCount); |
66101de1 | 473 | } else { |
fa448c1f LL |
474 | /* Complete to send, remove the URB from the first */ |
475 | spin_lock_irq(®->EP0VM_spin_lock); | |
65144de7 PE |
476 | reg_queue = reg->reg_first; |
477 | if (reg_queue == reg->reg_last) | |
478 | reg->reg_last = NULL; | |
479 | reg->reg_first = reg->reg_first->Next; | |
fa448c1f | 480 | spin_unlock_irq(®->EP0VM_spin_lock); |
65144de7 PE |
481 | |
482 | if (reg->EP0VM_status) { | |
2855bb79 | 483 | pr_debug("EP0 IoCompleteRoutine return error\n"); |
65144de7 | 484 | reg->EP0vm_state = VM_STOP; |
66101de1 PM |
485 | pHwData->SurpriseRemove = 1; |
486 | } else { | |
fa448c1f | 487 | /* Success. Update the result */ |
66101de1 | 488 | |
fa448c1f | 489 | /* Start the next send */ |
66101de1 PM |
490 | Wb35Reg_EP0VM(pHwData); |
491 | } | |
492 | ||
fa448c1f | 493 | kfree(reg_queue); |
66101de1 PM |
494 | } |
495 | ||
a55a89b1 | 496 | usb_free_urb(urb); |
66101de1 PM |
497 | } |
498 | ||
499 | ||
fa448c1f | 500 | void Wb35Reg_destroy(struct hw_data *pHwData) |
66101de1 | 501 | { |
fa448c1f LL |
502 | struct wb35_reg *reg = &pHwData->reg; |
503 | struct urb *urb; | |
504 | struct wb35_reg_queue *reg_queue; | |
66101de1 PM |
505 | |
506 | Uxx_power_off_procedure(pHwData); | |
507 | ||
fa448c1f | 508 | /* Wait for Reg operation completed */ |
66101de1 | 509 | do { |
fa448c1f | 510 | msleep(10); /* Delay for waiting function enter */ |
65144de7 | 511 | } while (reg->EP0vm_state != VM_STOP); |
fa448c1f | 512 | msleep(10); /* Delay for waiting function enter */ |
66101de1 | 513 | |
fa448c1f LL |
514 | /* Release all the data in RegQueue */ |
515 | spin_lock_irq(®->EP0VM_spin_lock); | |
65144de7 | 516 | reg_queue = reg->reg_first; |
f37435ce | 517 | while (reg_queue) { |
65144de7 PE |
518 | if (reg_queue == reg->reg_last) |
519 | reg->reg_last = NULL; | |
520 | reg->reg_first = reg->reg_first->Next; | |
66101de1 | 521 | |
f37435ce | 522 | urb = reg_queue->urb; |
fa448c1f | 523 | spin_unlock_irq(®->EP0VM_spin_lock); |
a55a89b1 PE |
524 | if (urb) { |
525 | usb_free_urb(urb); | |
f37435ce | 526 | kfree(reg_queue); |
66101de1 | 527 | } else { |
2855bb79 | 528 | pr_debug("EP0 queue release error\n"); |
66101de1 | 529 | } |
fa448c1f | 530 | spin_lock_irq(®->EP0VM_spin_lock); |
66101de1 | 531 | |
65144de7 | 532 | reg_queue = reg->reg_first; |
66101de1 | 533 | } |
fa448c1f | 534 | spin_unlock_irq(®->EP0VM_spin_lock); |
66101de1 PM |
535 | } |
536 | ||
fa448c1f LL |
537 | /* |
538 | * ======================================================================= | |
539 | * The function can be run in passive-level only. | |
540 | * ========================================================================= | |
541 | */ | |
542 | unsigned char Wb35Reg_initial(struct hw_data *pHwData) | |
66101de1 | 543 | { |
fa448c1f | 544 | struct wb35_reg *reg = &pHwData->reg; |
66101de1 PM |
545 | u32 ltmp; |
546 | u32 SoftwareSet, VCO_trim, TxVga, Region_ScanInterval; | |
547 | ||
fa448c1f LL |
548 | /* Spin lock is acquired for read and write IRP command */ |
549 | spin_lock_init(®->EP0VM_spin_lock); | |
550 | ||
551 | /* Getting RF module type from EEPROM */ | |
552 | Wb35Reg_WriteSync(pHwData, 0x03b4, 0x080d0000); /* Start EEPROM access + Read + address(0x0d) */ | |
553 | Wb35Reg_ReadSync(pHwData, 0x03b4, <mp); | |
554 | ||
555 | /* Update RF module type and determine the PHY type by inf or EEPROM */ | |
556 | reg->EEPROMPhyType = (u8)(ltmp & 0xff); | |
557 | /* | |
558 | * 0 V MAX2825, 1 V MAX2827, 2 V MAX2828, 3 V MAX2829 | |
559 | * 16V AL2230, 17 - AL7230, 18 - AL2230S | |
560 | * 32 Reserved | |
561 | * 33 - W89RF242(TxVGA 0~19), 34 - W89RF242(TxVGA 0~34) | |
562 | */ | |
65144de7 | 563 | if (reg->EEPROMPhyType != RF_DECIDE_BY_INF) { |
fa448c1f | 564 | if ((reg->EEPROMPhyType == RF_MAXIM_2825) || |
65144de7 PE |
565 | (reg->EEPROMPhyType == RF_MAXIM_2827) || |
566 | (reg->EEPROMPhyType == RF_MAXIM_2828) || | |
567 | (reg->EEPROMPhyType == RF_MAXIM_2829) || | |
568 | (reg->EEPROMPhyType == RF_MAXIM_V1) || | |
569 | (reg->EEPROMPhyType == RF_AIROHA_2230) || | |
fa448c1f | 570 | (reg->EEPROMPhyType == RF_AIROHA_2230S) || |
65144de7 | 571 | (reg->EEPROMPhyType == RF_AIROHA_7230) || |
fa448c1f | 572 | (reg->EEPROMPhyType == RF_WB_242) || |
65144de7 PE |
573 | (reg->EEPROMPhyType == RF_WB_242_1)) |
574 | pHwData->phy_type = reg->EEPROMPhyType; | |
66101de1 PM |
575 | } |
576 | ||
fa448c1f LL |
577 | /* Power On procedure running. The relative parameter will be set according to phy_type */ |
578 | Uxx_power_on_procedure(pHwData); | |
66101de1 | 579 | |
fa448c1f LL |
580 | /* Reading MAC address */ |
581 | Uxx_ReadEthernetAddress(pHwData); | |
66101de1 | 582 | |
fa448c1f LL |
583 | /* Read VCO trim for RF parameter */ |
584 | Wb35Reg_WriteSync(pHwData, 0x03b4, 0x08200000); | |
585 | Wb35Reg_ReadSync(pHwData, 0x03b4, &VCO_trim); | |
66101de1 | 586 | |
fa448c1f LL |
587 | /* Read Antenna On/Off of software flag */ |
588 | Wb35Reg_WriteSync(pHwData, 0x03b4, 0x08210000); | |
589 | Wb35Reg_ReadSync(pHwData, 0x03b4, &SoftwareSet); | |
66101de1 | 590 | |
fa448c1f LL |
591 | /* Read TXVGA */ |
592 | Wb35Reg_WriteSync(pHwData, 0x03b4, 0x08100000); | |
593 | Wb35Reg_ReadSync(pHwData, 0x03b4, &TxVga); | |
66101de1 | 594 | |
fa448c1f LL |
595 | /* Get Scan interval setting from EEPROM offset 0x1c */ |
596 | Wb35Reg_WriteSync(pHwData, 0x03b4, 0x081d0000); | |
597 | Wb35Reg_ReadSync(pHwData, 0x03b4, &Region_ScanInterval); | |
66101de1 | 598 | |
fa448c1f LL |
599 | /* Update Ethernet address */ |
600 | memcpy(pHwData->CurrentMacAddress, pHwData->PermanentMacAddress, ETH_ALEN); | |
66101de1 | 601 | |
fa448c1f | 602 | /* Update software variable */ |
66101de1 PM |
603 | pHwData->SoftwareSet = (u16)(SoftwareSet & 0xffff); |
604 | TxVga &= 0x000000ff; | |
605 | pHwData->PowerIndexFromEEPROM = (u8)TxVga; | |
606 | pHwData->VCO_trim = (u8)VCO_trim & 0xff; | |
607 | if (pHwData->VCO_trim == 0xff) | |
608 | pHwData->VCO_trim = 0x28; | |
609 | ||
fa448c1f LL |
610 | reg->EEPROMRegion = (u8)(Region_ScanInterval >> 8); |
611 | if (reg->EEPROMRegion < 1 || reg->EEPROMRegion > 6) | |
65144de7 | 612 | reg->EEPROMRegion = REGION_AUTO; |
66101de1 | 613 | |
fa448c1f LL |
614 | /* For Get Tx VGA from EEPROM */ |
615 | GetTxVgaFromEEPROM(pHwData); | |
66101de1 | 616 | |
fa448c1f | 617 | /* Set Scan Interval */ |
66101de1 | 618 | pHwData->Scan_Interval = (u8)(Region_ScanInterval & 0xff) * 10; |
fa448c1f | 619 | if ((pHwData->Scan_Interval == 2550) || (pHwData->Scan_Interval < 10)) /* Is default setting 0xff * 10 */ |
66101de1 PM |
620 | pHwData->Scan_Interval = SCAN_MAX_CHNL_TIME; |
621 | ||
fa448c1f | 622 | /* Initial register */ |
66101de1 PM |
623 | RFSynthesizer_initial(pHwData); |
624 | ||
fa448c1f | 625 | BBProcessor_initial(pHwData); /* Async write, must wait until complete */ |
66101de1 PM |
626 | |
627 | Wb35Reg_phy_calibration(pHwData); | |
628 | ||
629 | Mxx_initial(pHwData); | |
630 | Dxx_initial(pHwData); | |
631 | ||
632 | if (pHwData->SurpriseRemove) | |
279b6ccc | 633 | return false; |
66101de1 | 634 | else |
fa448c1f | 635 | return true; /* Initial fail */ |
66101de1 PM |
636 | } |
637 | ||
fa448c1f LL |
638 | /* |
639 | * ================================================================ | |
640 | * CardComputeCrc -- | |
641 | * | |
642 | * Description: | |
a31f7f5f | 643 | * Runs the AUTODIN II CRC algorithm on the buffers Buffer length. |
fa448c1f LL |
644 | * |
645 | * Arguments: | |
646 | * Buffer - the input buffer | |
647 | * Length - the length of Buffer | |
648 | * | |
649 | * Return Value: | |
650 | * The 32-bit CRC value. | |
651 | * =================================================================== | |
652 | */ | |
653 | u32 CardComputeCrc(u8 *Buffer, u32 Length) | |
66101de1 | 654 | { |
fa448c1f LL |
655 | u32 Crc, Carry; |
656 | u32 i, j; | |
657 | u8 CurByte; | |
658 | ||
659 | Crc = 0xffffffff; | |
660 | ||
661 | for (i = 0; i < Length; i++) { | |
662 | CurByte = Buffer[i]; | |
663 | for (j = 0; j < 8; j++) { | |
664 | Carry = ((Crc & 0x80000000) ? 1 : 0) ^ (CurByte & 0x01); | |
665 | Crc <<= 1; | |
666 | CurByte >>= 1; | |
667 | if (Carry) | |
668 | Crc = (Crc ^ 0x04c11db6) | Carry; | |
669 | } | |
670 | } | |
671 | return Crc; | |
66101de1 PM |
672 | } |
673 | ||
674 | ||
fa448c1f LL |
675 | /* |
676 | * ================================================================== | |
677 | * BitReverse -- | |
678 | * Reverse the bits in the input argument, dwData, which is | |
679 | * regarded as a string of bits with the length, DataLength. | |
680 | * | |
681 | * Arguments: | |
682 | * dwData : | |
683 | * DataLength : | |
684 | * | |
685 | * Return: | |
686 | * The converted value. | |
687 | * ================================================================== | |
688 | */ | |
689 | u32 BitReverse(u32 dwData, u32 DataLength) | |
66101de1 | 690 | { |
fa448c1f LL |
691 | u32 HalfLength, i, j; |
692 | u32 BitA, BitB; | |
66101de1 | 693 | |
fa448c1f LL |
694 | if (DataLength <= 0) |
695 | return 0; /* No conversion is done. */ | |
66101de1 PM |
696 | dwData = dwData & (0xffffffff >> (32 - DataLength)); |
697 | ||
698 | HalfLength = DataLength / 2; | |
fa448c1f LL |
699 | for (i = 0, j = DataLength - 1; i < HalfLength; i++, j--) { |
700 | BitA = GetBit(dwData, i); | |
701 | BitB = GetBit(dwData, j); | |
66101de1 | 702 | if (BitA && !BitB) { |
fa448c1f LL |
703 | dwData = ClearBit(dwData, i); |
704 | dwData = SetBit(dwData, j); | |
66101de1 | 705 | } else if (!BitA && BitB) { |
fa448c1f LL |
706 | dwData = SetBit(dwData, i); |
707 | dwData = ClearBit(dwData, j); | |
708 | } else { | |
709 | /* Do nothing since these two bits are of the save values. */ | |
66101de1 PM |
710 | } |
711 | } | |
66101de1 PM |
712 | return dwData; |
713 | } | |
714 | ||
fa448c1f | 715 | void Wb35Reg_phy_calibration(struct hw_data *pHwData) |
66101de1 | 716 | { |
fa448c1f | 717 | u32 BB3c, BB54; |
66101de1 PM |
718 | |
719 | if ((pHwData->phy_type == RF_WB_242) || | |
720 | (pHwData->phy_type == RF_WB_242_1)) { | |
fa448c1f LL |
721 | phy_calibration_winbond(pHwData, 2412); /* Sync operation */ |
722 | Wb35Reg_ReadSync(pHwData, 0x103c, &BB3c); | |
723 | Wb35Reg_ReadSync(pHwData, 0x1054, &BB54); | |
66101de1 PM |
724 | |
725 | pHwData->BB3c_cal = BB3c; | |
726 | pHwData->BB54_cal = BB54; | |
727 | ||
728 | RFSynthesizer_initial(pHwData); | |
fa448c1f | 729 | BBProcessor_initial(pHwData); /* Async operation */ |
66101de1 | 730 | |
fa448c1f LL |
731 | Wb35Reg_WriteSync(pHwData, 0x103c, BB3c); |
732 | Wb35Reg_WriteSync(pHwData, 0x1054, BB54); | |
66101de1 PM |
733 | } |
734 | } | |
735 | ||
736 |