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