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