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