]>
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 | |
279b6ccc PE |
9 | // true : read command process successfully |
10 | // false : register not support | |
66101de1 PM |
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 | unsigned char | |
8e41b4b6 | 17 | Wb35Reg_BurstWrite(struct hw_data * pHwData, u16 RegisterNo, u32 * pRegisterData, u8 NumberOfData, u8 Flag) |
66101de1 | 18 | { |
65144de7 | 19 | struct wb35_reg *reg = &pHwData->reg; |
a55a89b1 | 20 | struct urb *urb = NULL; |
f37435ce | 21 | struct wb35_reg_queue *reg_queue = NULL; |
66101de1 PM |
22 | u16 UrbSize; |
23 | struct usb_ctrlrequest *dr; | |
24 | u16 i, DataSize = NumberOfData*4; | |
25 | ||
26 | // Module shutdown | |
27 | if (pHwData->SurpriseRemove) | |
279b6ccc | 28 | return false; |
66101de1 PM |
29 | |
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); |
f37435ce PE |
34 | if( urb && reg_queue ) { |
35 | reg_queue->DIRECT = 2;// burst write register | |
36 | reg_queue->INDEX = RegisterNo; | |
37 | reg_queue->pBuffer = (u32 *)((u8 *)reg_queue + sizeof(struct wb35_reg_queue)); | |
38 | memcpy( reg_queue->pBuffer, pRegisterData, DataSize ); | |
66101de1 PM |
39 | //the function for reversing register data from little endian to big endian |
40 | for( i=0; i<NumberOfData ; i++ ) | |
f37435ce | 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 PM |
44 | dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE; |
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 | |
65144de7 PE |
53 | spin_lock_irq( ®->EP0VM_spin_lock ); |
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 | |
65144de7 | 60 | spin_unlock_irq( ®->EP0VM_spin_lock ); |
66101de1 PM |
61 | |
62 | // Start EP0VM | |
63 | Wb35Reg_EP0VM_start(pHwData); | |
64 | ||
279b6ccc | 65 | return true; |
66101de1 | 66 | } else { |
a55a89b1 PE |
67 | if (urb) |
68 | usb_free_urb(urb); | |
f37435ce PE |
69 | if (reg_queue) |
70 | kfree(reg_queue); | |
279b6ccc | 71 | return false; |
66101de1 | 72 | } |
279b6ccc | 73 | return false; |
66101de1 PM |
74 | } |
75 | ||
76 | void | |
8e41b4b6 | 77 | 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 | ||
279b6ccc PE |
119 | // true : read command process successfully |
120 | // false : register not support | |
66101de1 | 121 | unsigned char |
8e41b4b6 | 122 | Wb35Reg_WriteSync( struct hw_data * pHwData, u16 RegisterNo, u32 RegisterValue ) |
66101de1 | 123 | { |
65144de7 | 124 | struct wb35_reg *reg = &pHwData->reg; |
66101de1 PM |
125 | int ret = -1; |
126 | ||
127 | // Module shutdown | |
128 | if (pHwData->SurpriseRemove) | |
279b6ccc | 129 | return false; |
66101de1 PM |
130 | |
131 | RegisterValue = cpu_to_le32(RegisterValue); | |
132 | ||
133 | // update the register by send usb message------------------------------------ | |
65144de7 | 134 | reg->SyncIoPause = 1; |
66101de1 PM |
135 | |
136 | // 20060717.5 Wait until EP0VM stop | |
65144de7 | 137 | while (reg->EP0vm_state != VM_STOP) |
34222e0a | 138 | msleep(10); |
66101de1 PM |
139 | |
140 | // Sync IoCallDriver | |
65144de7 | 141 | reg->EP0vm_state = VM_RUNNING; |
66101de1 PM |
142 | ret = usb_control_msg( pHwData->WbUsb.udev, |
143 | usb_sndctrlpipe( pHwData->WbUsb.udev, 0 ), | |
144 | 0x03, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | |
145 | 0x0,RegisterNo, &RegisterValue, 4, HZ*100 ); | |
65144de7 PE |
146 | reg->EP0vm_state = VM_STOP; |
147 | reg->SyncIoPause = 0; | |
66101de1 PM |
148 | |
149 | Wb35Reg_EP0VM_start(pHwData); | |
150 | ||
151 | if (ret < 0) { | |
152 | #ifdef _PE_REG_DUMP_ | |
0c59dbaa | 153 | printk("EP0 Write register usb message sending error\n"); |
66101de1 PM |
154 | #endif |
155 | ||
156 | pHwData->SurpriseRemove = 1; // 20060704.2 | |
279b6ccc | 157 | return false; |
66101de1 PM |
158 | } |
159 | ||
279b6ccc | 160 | return true; |
66101de1 PM |
161 | } |
162 | ||
279b6ccc PE |
163 | // true : read command process successfully |
164 | // false : register not support | |
66101de1 | 165 | unsigned char |
8e41b4b6 | 166 | Wb35Reg_Write( struct hw_data * pHwData, u16 RegisterNo, u32 RegisterValue ) |
66101de1 | 167 | { |
65144de7 | 168 | struct wb35_reg *reg = &pHwData->reg; |
66101de1 | 169 | struct usb_ctrlrequest *dr; |
a55a89b1 | 170 | struct urb *urb = NULL; |
f37435ce | 171 | struct wb35_reg_queue *reg_queue = NULL; |
66101de1 PM |
172 | u16 UrbSize; |
173 | ||
174 | ||
175 | // Module shutdown | |
176 | if (pHwData->SurpriseRemove) | |
279b6ccc | 177 | return false; |
66101de1 PM |
178 | |
179 | // update the register by send urb request------------------------------------ | |
f37435ce | 180 | UrbSize = sizeof(struct wb35_reg_queue) + sizeof(struct usb_ctrlrequest); |
c8b2b70b | 181 | reg_queue = kzalloc(UrbSize, GFP_ATOMIC); |
f3d20188 | 182 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
f37435ce PE |
183 | if (urb && reg_queue) { |
184 | reg_queue->DIRECT = 1;// burst write register | |
185 | reg_queue->INDEX = RegisterNo; | |
186 | reg_queue->VALUE = cpu_to_le32(RegisterValue); | |
279b6ccc | 187 | reg_queue->RESERVED_VALID = false; |
f37435ce | 188 | dr = (struct usb_ctrlrequest *)((u8 *)reg_queue + sizeof(struct wb35_reg_queue)); |
66101de1 PM |
189 | dr->bRequestType = USB_TYPE_VENDOR|USB_DIR_OUT |USB_RECIP_DEVICE; |
190 | dr->bRequest = 0x03; // USB or vendor-defined request code, burst mode | |
191 | dr->wValue = cpu_to_le16(0x0); | |
192 | dr->wIndex = cpu_to_le16(RegisterNo); | |
193 | dr->wLength = cpu_to_le16(4); | |
194 | ||
195 | // Enter the sending queue | |
f37435ce PE |
196 | reg_queue->Next = NULL; |
197 | reg_queue->pUsbReq = dr; | |
198 | reg_queue->urb = urb; | |
66101de1 | 199 | |
65144de7 PE |
200 | spin_lock_irq(®->EP0VM_spin_lock ); |
201 | if (reg->reg_first == NULL) | |
202 | reg->reg_first = reg_queue; | |
66101de1 | 203 | else |
65144de7 PE |
204 | reg->reg_last->Next = reg_queue; |
205 | reg->reg_last = reg_queue; | |
66101de1 | 206 | |
65144de7 | 207 | spin_unlock_irq( ®->EP0VM_spin_lock ); |
66101de1 PM |
208 | |
209 | // Start EP0VM | |
210 | Wb35Reg_EP0VM_start(pHwData); | |
211 | ||
279b6ccc | 212 | return true; |
66101de1 | 213 | } else { |
a55a89b1 PE |
214 | if (urb) |
215 | usb_free_urb(urb); | |
f37435ce | 216 | kfree(reg_queue); |
279b6ccc | 217 | return false; |
66101de1 PM |
218 | } |
219 | } | |
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. | |
279b6ccc PE |
223 | // true : read command process successfully |
224 | // false : register not support | |
66101de1 | 225 | unsigned char |
8e41b4b6 | 226 | Wb35Reg_WriteWithCallbackValue( struct hw_data * pHwData, u16 RegisterNo, u32 RegisterValue, |
8b384e0c | 227 | s8 *pValue, s8 Len) |
66101de1 | 228 | { |
65144de7 | 229 | struct wb35_reg *reg = &pHwData->reg; |
66101de1 | 230 | struct usb_ctrlrequest *dr; |
a55a89b1 | 231 | struct urb *urb = NULL; |
f37435ce | 232 | struct wb35_reg_queue *reg_queue = NULL; |
66101de1 PM |
233 | u16 UrbSize; |
234 | ||
235 | // Module shutdown | |
236 | if (pHwData->SurpriseRemove) | |
279b6ccc | 237 | return false; |
66101de1 PM |
238 | |
239 | // update the register by send urb request------------------------------------ | |
f37435ce | 240 | UrbSize = sizeof(struct wb35_reg_queue) + sizeof(struct usb_ctrlrequest); |
c8b2b70b | 241 | reg_queue = kzalloc(UrbSize, GFP_ATOMIC); |
f3d20188 | 242 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
f37435ce PE |
243 | if (urb && reg_queue) { |
244 | reg_queue->DIRECT = 1;// burst write register | |
245 | reg_queue->INDEX = RegisterNo; | |
246 | reg_queue->VALUE = cpu_to_le32(RegisterValue); | |
66101de1 | 247 | //NOTE : Users must guarantee the size of value will not exceed the buffer size. |
f37435ce | 248 | memcpy(reg_queue->RESERVED, pValue, Len); |
279b6ccc | 249 | reg_queue->RESERVED_VALID = true; |
f37435ce | 250 | dr = (struct usb_ctrlrequest *)((u8 *)reg_queue + sizeof(struct wb35_reg_queue)); |
66101de1 PM |
251 | dr->bRequestType = USB_TYPE_VENDOR|USB_DIR_OUT |USB_RECIP_DEVICE; |
252 | dr->bRequest = 0x03; // USB or vendor-defined request code, burst mode | |
253 | dr->wValue = cpu_to_le16(0x0); | |
254 | dr->wIndex = cpu_to_le16(RegisterNo); | |
255 | dr->wLength = cpu_to_le16(4); | |
256 | ||
257 | // Enter the sending queue | |
f37435ce PE |
258 | reg_queue->Next = NULL; |
259 | reg_queue->pUsbReq = dr; | |
260 | reg_queue->urb = urb; | |
65144de7 PE |
261 | spin_lock_irq (®->EP0VM_spin_lock ); |
262 | if( reg->reg_first == NULL ) | |
263 | reg->reg_first = reg_queue; | |
66101de1 | 264 | else |
65144de7 PE |
265 | reg->reg_last->Next = reg_queue; |
266 | reg->reg_last = reg_queue; | |
66101de1 | 267 | |
65144de7 | 268 | spin_unlock_irq ( ®->EP0VM_spin_lock ); |
66101de1 PM |
269 | |
270 | // Start EP0VM | |
271 | Wb35Reg_EP0VM_start(pHwData); | |
279b6ccc | 272 | return true; |
66101de1 | 273 | } else { |
a55a89b1 PE |
274 | if (urb) |
275 | usb_free_urb(urb); | |
f37435ce | 276 | kfree(reg_queue); |
279b6ccc | 277 | return false; |
66101de1 PM |
278 | } |
279 | } | |
280 | ||
279b6ccc PE |
281 | // true : read command process successfully |
282 | // false : register not support | |
66101de1 PM |
283 | // pRegisterValue : It must be a resident buffer due to asynchronous read register. |
284 | unsigned char | |
8e41b4b6 | 285 | Wb35Reg_ReadSync( struct hw_data * pHwData, u16 RegisterNo, u32 * pRegisterValue ) |
66101de1 | 286 | { |
65144de7 | 287 | struct wb35_reg *reg = &pHwData->reg; |
8b384e0c | 288 | u32 * pltmp = pRegisterValue; |
66101de1 PM |
289 | int ret = -1; |
290 | ||
291 | // Module shutdown | |
292 | if (pHwData->SurpriseRemove) | |
279b6ccc | 293 | return false; |
66101de1 PM |
294 | |
295 | // Read the register by send usb message------------------------------------ | |
296 | ||
65144de7 | 297 | reg->SyncIoPause = 1; |
66101de1 PM |
298 | |
299 | // 20060717.5 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; |
66101de1 PM |
304 | ret = usb_control_msg( pHwData->WbUsb.udev, |
305 | usb_rcvctrlpipe(pHwData->WbUsb.udev, 0), | |
306 | 0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN, | |
307 | 0x0, RegisterNo, pltmp, 4, HZ*100 ); | |
308 | ||
309 | *pRegisterValue = cpu_to_le32(*pltmp); | |
310 | ||
65144de7 | 311 | reg->EP0vm_state = VM_STOP; |
66101de1 PM |
312 | |
313 | Wb35Reg_Update( pHwData, RegisterNo, *pRegisterValue ); | |
65144de7 | 314 | reg->SyncIoPause = 0; |
66101de1 PM |
315 | |
316 | Wb35Reg_EP0VM_start( pHwData ); | |
317 | ||
318 | if (ret < 0) { | |
319 | #ifdef _PE_REG_DUMP_ | |
0c59dbaa | 320 | printk("EP0 Read register usb message sending error\n"); |
66101de1 PM |
321 | #endif |
322 | ||
323 | pHwData->SurpriseRemove = 1; // 20060704.2 | |
279b6ccc | 324 | return false; |
66101de1 PM |
325 | } |
326 | ||
279b6ccc | 327 | return true; |
66101de1 PM |
328 | } |
329 | ||
279b6ccc PE |
330 | // true : read command process successfully |
331 | // false : register not support | |
66101de1 PM |
332 | // pRegisterValue : It must be a resident buffer due to asynchronous read register. |
333 | unsigned char | |
8e41b4b6 | 334 | Wb35Reg_Read(struct hw_data * pHwData, u16 RegisterNo, u32 * pRegisterValue ) |
66101de1 | 335 | { |
65144de7 | 336 | struct wb35_reg *reg = &pHwData->reg; |
66101de1 | 337 | struct usb_ctrlrequest * dr; |
a55a89b1 | 338 | struct urb *urb; |
f37435ce | 339 | struct wb35_reg_queue *reg_queue; |
66101de1 PM |
340 | u16 UrbSize; |
341 | ||
342 | // Module shutdown | |
343 | if (pHwData->SurpriseRemove) | |
279b6ccc | 344 | return false; |
66101de1 PM |
345 | |
346 | // update the variable by send Urb to read register ------------------------------------ | |
f37435ce | 347 | UrbSize = sizeof(struct wb35_reg_queue) + sizeof(struct usb_ctrlrequest); |
c8b2b70b | 348 | reg_queue = kzalloc(UrbSize, GFP_ATOMIC); |
f3d20188 | 349 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
f37435ce | 350 | if( urb && reg_queue ) |
66101de1 | 351 | { |
f37435ce PE |
352 | reg_queue->DIRECT = 0;// read register |
353 | reg_queue->INDEX = RegisterNo; | |
354 | reg_queue->pBuffer = pRegisterValue; | |
355 | dr = (struct usb_ctrlrequest *)((u8 *)reg_queue + sizeof(struct wb35_reg_queue)); | |
66101de1 PM |
356 | dr->bRequestType = USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN; |
357 | dr->bRequest = 0x01; // USB or vendor-defined request code, burst mode | |
358 | dr->wValue = cpu_to_le16(0x0); | |
359 | dr->wIndex = cpu_to_le16 (RegisterNo); | |
360 | dr->wLength = cpu_to_le16 (4); | |
361 | ||
362 | // Enter the sending queue | |
f37435ce PE |
363 | reg_queue->Next = NULL; |
364 | reg_queue->pUsbReq = dr; | |
365 | reg_queue->urb = urb; | |
65144de7 PE |
366 | spin_lock_irq ( ®->EP0VM_spin_lock ); |
367 | if( reg->reg_first == NULL ) | |
368 | reg->reg_first = reg_queue; | |
66101de1 | 369 | else |
65144de7 PE |
370 | reg->reg_last->Next = reg_queue; |
371 | reg->reg_last = reg_queue; | |
66101de1 | 372 | |
65144de7 | 373 | spin_unlock_irq( ®->EP0VM_spin_lock ); |
66101de1 PM |
374 | |
375 | // Start EP0VM | |
376 | Wb35Reg_EP0VM_start( pHwData ); | |
377 | ||
279b6ccc | 378 | return true; |
66101de1 | 379 | } else { |
a55a89b1 PE |
380 | if (urb) |
381 | usb_free_urb( urb ); | |
f37435ce | 382 | kfree(reg_queue); |
279b6ccc | 383 | return false; |
66101de1 PM |
384 | } |
385 | } | |
386 | ||
387 | ||
388 | void | |
8e41b4b6 | 389 | Wb35Reg_EP0VM_start( struct hw_data * pHwData ) |
66101de1 | 390 | { |
65144de7 | 391 | struct wb35_reg *reg = &pHwData->reg; |
66101de1 | 392 | |
44e8541c | 393 | if (atomic_inc_return(®->RegFireCount) == 1) { |
65144de7 | 394 | reg->EP0vm_state = VM_RUNNING; |
66101de1 PM |
395 | Wb35Reg_EP0VM(pHwData); |
396 | } else | |
44e8541c | 397 | atomic_dec(®->RegFireCount); |
66101de1 PM |
398 | } |
399 | ||
400 | void | |
8e41b4b6 | 401 | Wb35Reg_EP0VM(struct hw_data * pHwData ) |
66101de1 | 402 | { |
65144de7 | 403 | struct wb35_reg *reg = &pHwData->reg; |
a55a89b1 | 404 | struct urb *urb; |
66101de1 | 405 | struct usb_ctrlrequest *dr; |
8b384e0c | 406 | u32 * pBuffer; |
66101de1 | 407 | int ret = -1; |
f37435ce | 408 | struct wb35_reg_queue *reg_queue; |
66101de1 PM |
409 | |
410 | ||
65144de7 | 411 | if (reg->SyncIoPause) |
66101de1 PM |
412 | goto cleanup; |
413 | ||
414 | if (pHwData->SurpriseRemove) | |
415 | goto cleanup; | |
416 | ||
417 | // Get the register data and send to USB through Irp | |
65144de7 PE |
418 | spin_lock_irq( ®->EP0VM_spin_lock ); |
419 | reg_queue = reg->reg_first; | |
420 | spin_unlock_irq( ®->EP0VM_spin_lock ); | |
66101de1 | 421 | |
f37435ce | 422 | if (!reg_queue) |
66101de1 PM |
423 | goto cleanup; |
424 | ||
425 | // Get an Urb, send it | |
f37435ce | 426 | urb = (struct urb *)reg_queue->urb; |
66101de1 | 427 | |
f37435ce PE |
428 | dr = reg_queue->pUsbReq; |
429 | urb = reg_queue->urb; | |
430 | pBuffer = reg_queue->pBuffer; | |
431 | if (reg_queue->DIRECT == 1) // output | |
432 | pBuffer = ®_queue->VALUE; | |
66101de1 | 433 | |
a55a89b1 | 434 | usb_fill_control_urb( urb, pHwData->WbUsb.udev, |
f37435ce | 435 | REG_DIRECTION(pHwData->WbUsb.udev,reg_queue), |
8b384e0c | 436 | (u8 *)dr,pBuffer,cpu_to_le16(dr->wLength), |
66101de1 PM |
437 | Wb35Reg_EP0VM_complete, (void*)pHwData); |
438 | ||
65144de7 | 439 | reg->EP0vm_state = VM_RUNNING; |
66101de1 | 440 | |
7c126043 | 441 | ret = usb_submit_urb(urb, GFP_ATOMIC); |
66101de1 PM |
442 | |
443 | if (ret < 0) { | |
444 | #ifdef _PE_REG_DUMP_ | |
0c59dbaa | 445 | printk("EP0 Irp sending error\n"); |
66101de1 PM |
446 | #endif |
447 | goto cleanup; | |
448 | } | |
449 | ||
450 | return; | |
451 | ||
452 | cleanup: | |
65144de7 | 453 | reg->EP0vm_state = VM_STOP; |
44e8541c | 454 | atomic_dec(®->RegFireCount); |
66101de1 PM |
455 | } |
456 | ||
457 | ||
458 | void | |
a55a89b1 | 459 | Wb35Reg_EP0VM_complete(struct urb *urb) |
66101de1 | 460 | { |
8e41b4b6 | 461 | struct hw_data * pHwData = (struct hw_data *)urb->context; |
65144de7 | 462 | struct wb35_reg *reg = &pHwData->reg; |
f37435ce | 463 | struct wb35_reg_queue *reg_queue; |
66101de1 PM |
464 | |
465 | ||
466 | // Variable setting | |
65144de7 PE |
467 | reg->EP0vm_state = VM_COMPLETED; |
468 | reg->EP0VM_status = urb->status; | |
66101de1 PM |
469 | |
470 | if (pHwData->SurpriseRemove) { // Let WbWlanHalt to handle surprise remove | |
65144de7 | 471 | reg->EP0vm_state = VM_STOP; |
44e8541c | 472 | atomic_dec(®->RegFireCount); |
66101de1 PM |
473 | } else { |
474 | // Complete to send, remove the URB from the first | |
65144de7 PE |
475 | spin_lock_irq( ®->EP0VM_spin_lock ); |
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; | |
480 | spin_unlock_irq( ®->EP0VM_spin_lock ); | |
481 | ||
482 | if (reg->EP0VM_status) { | |
66101de1 | 483 | #ifdef _PE_REG_DUMP_ |
0c59dbaa | 484 | printk("EP0 IoCompleteRoutine return error\n"); |
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 | |
8e41b4b6 | 503 | Wb35Reg_destroy(struct hw_data * pHwData) |
66101de1 | 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 { | |
9ce922fd | 514 | msleep(10); // Delay for waiting function enter 940623.1.a |
65144de7 | 515 | } while (reg->EP0vm_state != VM_STOP); |
9ce922fd | 516 | msleep(10); // Delay for waiting function enter 940623.1.b |
66101de1 PM |
517 | |
518 | // Release all the data in RegQueue | |
9ce922fd | 519 | spin_lock_irq( ®->EP0VM_spin_lock ); |
65144de7 | 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; |
9ce922fd | 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_ | |
0c59dbaa | 533 | printk("EP0 queue release error\n"); |
66101de1 PM |
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 | //==================================================================================== | |
8e41b4b6 | 546 | unsigned char Wb35Reg_initial(struct hw_data * pHwData) |
66101de1 | 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 | |
bd37b7fd | 602 | memcpy( pHwData->CurrentMacAddress, pHwData->PermanentMacAddress, ETH_ALEN ); |
66101de1 PM |
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 | ||
8e41b4b6 | 726 | void Wb35Reg_phy_calibration( struct hw_data * pHwData ) |
66101de1 PM |
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 |