diff options
Diffstat (limited to 'drivers/usb/atm/ueagle-atm.c')
-rw-r--r-- | drivers/usb/atm/ueagle-atm.c | 1191 |
1 files changed, 978 insertions, 213 deletions
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 29807d048b04..b5e8cbad223b 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c | |||
@@ -107,12 +107,42 @@ | |||
107 | #define uea_info(usb_dev, format,args...) \ | 107 | #define uea_info(usb_dev, format,args...) \ |
108 | dev_info(&(usb_dev)->dev ,"[ueagle-atm] " format, ##args) | 108 | dev_info(&(usb_dev)->dev ,"[ueagle-atm] " format, ##args) |
109 | 109 | ||
110 | struct uea_cmvs { | 110 | struct intr_pkt; |
111 | |||
112 | /* cmv's from firmware */ | ||
113 | struct uea_cmvs_v1 { | ||
111 | u32 address; | 114 | u32 address; |
112 | u16 offset; | 115 | u16 offset; |
113 | u32 data; | 116 | u32 data; |
114 | } __attribute__ ((packed)); | 117 | } __attribute__ ((packed)); |
115 | 118 | ||
119 | struct uea_cmvs_v2 { | ||
120 | u32 group; | ||
121 | u32 address; | ||
122 | u32 offset; | ||
123 | u32 data; | ||
124 | } __attribute__ ((packed)); | ||
125 | |||
126 | /* information about currently processed cmv */ | ||
127 | struct cmv_dsc_e1 { | ||
128 | u8 function; | ||
129 | u16 idx; | ||
130 | u32 address; | ||
131 | u16 offset; | ||
132 | }; | ||
133 | |||
134 | struct cmv_dsc_e4 { | ||
135 | u16 function; | ||
136 | u16 offset; | ||
137 | u16 address; | ||
138 | u16 group; | ||
139 | }; | ||
140 | |||
141 | union cmv_dsc { | ||
142 | struct cmv_dsc_e1 e1; | ||
143 | struct cmv_dsc_e4 e4; | ||
144 | }; | ||
145 | |||
116 | struct uea_softc { | 146 | struct uea_softc { |
117 | struct usb_device *usb_dev; | 147 | struct usb_device *usb_dev; |
118 | struct usbatm_data *usbatm; | 148 | struct usbatm_data *usbatm; |
@@ -127,8 +157,11 @@ struct uea_softc { | |||
127 | 157 | ||
128 | struct task_struct *kthread; | 158 | struct task_struct *kthread; |
129 | u32 data; | 159 | u32 data; |
160 | u32 data1; | ||
130 | wait_queue_head_t cmv_ack_wait; | 161 | wait_queue_head_t cmv_ack_wait; |
162 | |||
131 | int cmv_ack; | 163 | int cmv_ack; |
164 | union cmv_dsc cmv_dsc; | ||
132 | 165 | ||
133 | struct work_struct task; | 166 | struct work_struct task; |
134 | u16 pageno; | 167 | u16 pageno; |
@@ -137,10 +170,10 @@ struct uea_softc { | |||
137 | const struct firmware *dsp_firm; | 170 | const struct firmware *dsp_firm; |
138 | struct urb *urb_int; | 171 | struct urb *urb_int; |
139 | 172 | ||
140 | u8 cmv_function; | 173 | void (*dispatch_cmv) (struct uea_softc *, struct intr_pkt *); |
141 | u16 cmv_idx; | 174 | void (*schedule_load_page) (struct uea_softc *, struct intr_pkt *); |
142 | u32 cmv_address; | 175 | int (*stat) (struct uea_softc *); |
143 | u16 cmv_offset; | 176 | int (*send_cmvs) (struct uea_softc *); |
144 | 177 | ||
145 | /* keep in sync with eaglectl */ | 178 | /* keep in sync with eaglectl */ |
146 | struct uea_stats { | 179 | struct uea_stats { |
@@ -187,12 +220,12 @@ struct uea_softc { | |||
187 | #define EAGLE_II_PID_PREFIRM 0x9022 /* Eagle II */ | 220 | #define EAGLE_II_PID_PREFIRM 0x9022 /* Eagle II */ |
188 | #define EAGLE_II_PID_PSTFIRM 0x9021 /* Eagle II */ | 221 | #define EAGLE_II_PID_PSTFIRM 0x9021 /* Eagle II */ |
189 | 222 | ||
190 | /* | ||
191 | * Eagle III Pid | ||
192 | */ | ||
193 | #define EAGLE_III_PID_PREFIRM 0x9032 /* Eagle III */ | 223 | #define EAGLE_III_PID_PREFIRM 0x9032 /* Eagle III */ |
194 | #define EAGLE_III_PID_PSTFIRM 0x9031 /* Eagle III */ | 224 | #define EAGLE_III_PID_PSTFIRM 0x9031 /* Eagle III */ |
195 | 225 | ||
226 | #define EAGLE_IV_PID_PREFIRM 0x9042 /* Eagle IV */ | ||
227 | #define EAGLE_IV_PID_PSTFIRM 0x9041 /* Eagle IV */ | ||
228 | |||
196 | /* | 229 | /* |
197 | * USR USB IDs | 230 | * USR USB IDs |
198 | */ | 231 | */ |
@@ -212,7 +245,8 @@ enum { | |||
212 | ADI930 = 0, | 245 | ADI930 = 0, |
213 | EAGLE_I, | 246 | EAGLE_I, |
214 | EAGLE_II, | 247 | EAGLE_II, |
215 | EAGLE_III | 248 | EAGLE_III, |
249 | EAGLE_IV | ||
216 | }; | 250 | }; |
217 | 251 | ||
218 | /* macros for both struct usb_device_id and struct uea_softc */ | 252 | /* macros for both struct usb_device_id and struct uea_softc */ |
@@ -228,8 +262,11 @@ enum { | |||
228 | 262 | ||
229 | #define GET_STATUS(data) \ | 263 | #define GET_STATUS(data) \ |
230 | ((data >> 8) & 0xf) | 264 | ((data >> 8) & 0xf) |
265 | |||
231 | #define IS_OPERATIONAL(sc) \ | 266 | #define IS_OPERATIONAL(sc) \ |
232 | (GET_STATUS(sc->stats.phy.state) == 2) | 267 | ((UEA_CHIP_VERSION(sc) != EAGLE_IV) ? \ |
268 | (GET_STATUS(sc->stats.phy.state) == 2) : \ | ||
269 | (sc->stats.phy.state == 7)) | ||
233 | 270 | ||
234 | /* | 271 | /* |
235 | * Set of macros to handle unaligned data in the firmware blob. | 272 | * Set of macros to handle unaligned data in the firmware blob. |
@@ -259,7 +296,8 @@ enum { | |||
259 | #define UEA_INTR_PIPE 0x04 | 296 | #define UEA_INTR_PIPE 0x04 |
260 | #define UEA_ISO_DATA_PIPE 0x08 | 297 | #define UEA_ISO_DATA_PIPE 0x08 |
261 | 298 | ||
262 | #define UEA_SET_BLOCK 0x0001 | 299 | #define UEA_E1_SET_BLOCK 0x0001 |
300 | #define UEA_E4_SET_BLOCK 0x002c | ||
263 | #define UEA_SET_MODE 0x0003 | 301 | #define UEA_SET_MODE 0x0003 |
264 | #define UEA_SET_2183_DATA 0x0004 | 302 | #define UEA_SET_2183_DATA 0x0004 |
265 | #define UEA_SET_TIMEOUT 0x0011 | 303 | #define UEA_SET_TIMEOUT 0x0011 |
@@ -275,71 +313,179 @@ enum { | |||
275 | #define UEA_MPTX_MAILBOX (0x3fd6 | 0x4000) | 313 | #define UEA_MPTX_MAILBOX (0x3fd6 | 0x4000) |
276 | #define UEA_MPRX_MAILBOX (0x3fdf | 0x4000) | 314 | #define UEA_MPRX_MAILBOX (0x3fdf | 0x4000) |
277 | 315 | ||
278 | /* structure describing a block within a DSP page */ | 316 | /* block information in eagle4 dsp firmware */ |
279 | struct block_info { | 317 | struct block_index { |
318 | __le32 PageOffset; | ||
319 | __le32 NotLastBlock; | ||
320 | __le32 dummy; | ||
321 | __le32 PageSize; | ||
322 | __le32 PageAddress; | ||
323 | __le16 dummy1; | ||
324 | __le16 PageNumber; | ||
325 | } __attribute__ ((packed)); | ||
326 | |||
327 | #define E4_IS_BOOT_PAGE(PageSize) ((le32_to_cpu(PageSize)) & 0x80000000) | ||
328 | #define E4_PAGE_BYTES(PageSize) ((le32_to_cpu(PageSize) & 0x7fffffff) * 4) | ||
329 | |||
330 | #define E4_L1_STRING_HEADER 0x10 | ||
331 | #define E4_MAX_PAGE_NUMBER 0x58 | ||
332 | #define E4_NO_SWAPPAGE_HEADERS 0x31 | ||
333 | |||
334 | /* l1_code is eagle4 dsp firmware format */ | ||
335 | struct l1_code { | ||
336 | u8 string_header[E4_L1_STRING_HEADER]; | ||
337 | u8 page_number_to_block_index[E4_MAX_PAGE_NUMBER]; | ||
338 | struct block_index page_header[E4_NO_SWAPPAGE_HEADERS]; | ||
339 | u8 code [0]; | ||
340 | } __attribute__ ((packed)); | ||
341 | |||
342 | /* structures describing a block within a DSP page */ | ||
343 | struct block_info_e1 { | ||
280 | __le16 wHdr; | 344 | __le16 wHdr; |
281 | #define UEA_BIHDR 0xabcd | ||
282 | __le16 wAddress; | 345 | __le16 wAddress; |
283 | __le16 wSize; | 346 | __le16 wSize; |
284 | __le16 wOvlOffset; | 347 | __le16 wOvlOffset; |
285 | __le16 wOvl; /* overlay */ | 348 | __le16 wOvl; /* overlay */ |
286 | __le16 wLast; | 349 | __le16 wLast; |
287 | } __attribute__ ((packed)); | 350 | } __attribute__ ((packed)); |
288 | #define BLOCK_INFO_SIZE 12 | 351 | #define E1_BLOCK_INFO_SIZE 12 |
352 | |||
353 | struct block_info_e4 { | ||
354 | __be16 wHdr; | ||
355 | __u8 bBootPage; | ||
356 | __u8 bPageNumber; | ||
357 | __be32 dwSize; | ||
358 | __be32 dwAddress; | ||
359 | __be16 wReserved; | ||
360 | } __attribute__ ((packed)); | ||
361 | #define E4_BLOCK_INFO_SIZE 14 | ||
289 | 362 | ||
290 | /* structure representing a CMV (Configuration and Management Variable) */ | 363 | #define UEA_BIHDR 0xabcd |
291 | struct cmv { | 364 | #define UEA_RESERVED 0xffff |
292 | __le16 wPreamble; | 365 | |
293 | #define PREAMBLE 0x535c | 366 | /* constants describing cmv type */ |
294 | __u8 bDirection; | 367 | #define E1_PREAMBLE 0x535c |
295 | #define MODEMTOHOST 0x01 | 368 | #define E1_MODEMTOHOST 0x01 |
296 | #define HOSTTOMODEM 0x10 | 369 | #define E1_HOSTTOMODEM 0x10 |
297 | __u8 bFunction; | 370 | |
298 | #define FUNCTION_TYPE(f) ((f) >> 4) | 371 | #define E1_MEMACCESS 0x1 |
299 | #define MEMACCESS 0x1 | 372 | #define E1_ADSLDIRECTIVE 0x7 |
300 | #define ADSLDIRECTIVE 0x7 | 373 | #define E1_FUNCTION_TYPE(f) ((f) >> 4) |
374 | #define E1_FUNCTION_SUBTYPE(f) ((f) & 0x0f) | ||
375 | |||
376 | #define E4_MEMACCESS 0 | ||
377 | #define E4_ADSLDIRECTIVE 0xf | ||
378 | #define E4_FUNCTION_TYPE(f) ((f) >> 8) | ||
379 | #define E4_FUNCTION_SIZE(f) ((f) & 0x0f) | ||
380 | #define E4_FUNCTION_SUBTYPE(f) (((f) >> 4) & 0x0f) | ||
301 | 381 | ||
302 | #define FUNCTION_SUBTYPE(f) ((f) & 0x0f) | ||
303 | /* for MEMACCESS */ | 382 | /* for MEMACCESS */ |
304 | #define REQUESTREAD 0x0 | 383 | #define E1_REQUESTREAD 0x0 |
305 | #define REQUESTWRITE 0x1 | 384 | #define E1_REQUESTWRITE 0x1 |
306 | #define REPLYREAD 0x2 | 385 | #define E1_REPLYREAD 0x2 |
307 | #define REPLYWRITE 0x3 | 386 | #define E1_REPLYWRITE 0x3 |
387 | |||
388 | #define E4_REQUESTREAD 0x0 | ||
389 | #define E4_REQUESTWRITE 0x4 | ||
390 | #define E4_REPLYREAD (E4_REQUESTREAD | 1) | ||
391 | #define E4_REPLYWRITE (E4_REQUESTWRITE | 1) | ||
392 | |||
308 | /* for ADSLDIRECTIVE */ | 393 | /* for ADSLDIRECTIVE */ |
309 | #define KERNELREADY 0x0 | 394 | #define E1_KERNELREADY 0x0 |
310 | #define MODEMREADY 0x1 | 395 | #define E1_MODEMREADY 0x1 |
311 | 396 | ||
312 | #define MAKEFUNCTION(t, s) (((t) & 0xf) << 4 | ((s) & 0xf)) | 397 | #define E4_KERNELREADY 0x0 |
313 | __le16 wIndex; | 398 | #define E4_MODEMREADY 0x1 |
314 | __le32 dwSymbolicAddress; | 399 | |
315 | #define MAKESA(a, b, c, d) \ | 400 | #define E1_MAKEFUNCTION(t, s) (((t) & 0xf) << 4 | ((s) & 0xf)) |
401 | #define E4_MAKEFUNCTION(t, st, s) (((t) & 0xf) << 8 | ((st) & 0xf) << 4 | ((s) & 0xf)) | ||
402 | |||
403 | #define E1_MAKESA(a, b, c, d) \ | ||
316 | (((c) & 0xff) << 24 | \ | 404 | (((c) & 0xff) << 24 | \ |
317 | ((d) & 0xff) << 16 | \ | 405 | ((d) & 0xff) << 16 | \ |
318 | ((a) & 0xff) << 8 | \ | 406 | ((a) & 0xff) << 8 | \ |
319 | ((b) & 0xff)) | 407 | ((b) & 0xff)) |
320 | #define GETSA1(a) ((a >> 8) & 0xff) | 408 | |
321 | #define GETSA2(a) (a & 0xff) | 409 | #define E1_GETSA1(a) ((a >> 8) & 0xff) |
322 | #define GETSA3(a) ((a >> 24) & 0xff) | 410 | #define E1_GETSA2(a) (a & 0xff) |
323 | #define GETSA4(a) ((a >> 16) & 0xff) | 411 | #define E1_GETSA3(a) ((a >> 24) & 0xff) |
324 | 412 | #define E1_GETSA4(a) ((a >> 16) & 0xff) | |
325 | #define SA_CNTL MAKESA('C', 'N', 'T', 'L') | 413 | |
326 | #define SA_DIAG MAKESA('D', 'I', 'A', 'G') | 414 | #define E1_SA_CNTL E1_MAKESA('C', 'N', 'T', 'L') |
327 | #define SA_INFO MAKESA('I', 'N', 'F', 'O') | 415 | #define E1_SA_DIAG E1_MAKESA('D', 'I', 'A', 'G') |
328 | #define SA_OPTN MAKESA('O', 'P', 'T', 'N') | 416 | #define E1_SA_INFO E1_MAKESA('I', 'N', 'F', 'O') |
329 | #define SA_RATE MAKESA('R', 'A', 'T', 'E') | 417 | #define E1_SA_OPTN E1_MAKESA('O', 'P', 'T', 'N') |
330 | #define SA_STAT MAKESA('S', 'T', 'A', 'T') | 418 | #define E1_SA_RATE E1_MAKESA('R', 'A', 'T', 'E') |
419 | #define E1_SA_STAT E1_MAKESA('S', 'T', 'A', 'T') | ||
420 | |||
421 | #define E4_SA_CNTL 1 | ||
422 | #define E4_SA_STAT 2 | ||
423 | #define E4_SA_INFO 3 | ||
424 | #define E4_SA_TEST 4 | ||
425 | #define E4_SA_OPTN 5 | ||
426 | #define E4_SA_RATE 6 | ||
427 | #define E4_SA_DIAG 7 | ||
428 | #define E4_SA_CNFG 8 | ||
429 | |||
430 | /* structures representing a CMV (Configuration and Management Variable) */ | ||
431 | struct cmv_e1 { | ||
432 | __le16 wPreamble; | ||
433 | __u8 bDirection; | ||
434 | __u8 bFunction; | ||
435 | __le16 wIndex; | ||
436 | __le32 dwSymbolicAddress; | ||
331 | __le16 wOffsetAddress; | 437 | __le16 wOffsetAddress; |
332 | __le32 dwData; | 438 | __le32 dwData; |
333 | } __attribute__ ((packed)); | 439 | } __attribute__ ((packed)); |
334 | #define CMV_SIZE 16 | ||
335 | 440 | ||
336 | /* structure representing swap information */ | 441 | struct cmv_e4 { |
337 | struct swap_info { | 442 | __be16 wGroup; |
443 | __be16 wFunction; | ||
444 | __be16 wOffset; | ||
445 | __be16 wAddress; | ||
446 | __be32 dwData [6]; | ||
447 | } __attribute__ ((packed)); | ||
448 | |||
449 | /* structures representing swap information */ | ||
450 | struct swap_info_e1 { | ||
338 | __u8 bSwapPageNo; | 451 | __u8 bSwapPageNo; |
339 | __u8 bOvl; /* overlay */ | 452 | __u8 bOvl; /* overlay */ |
340 | } __attribute__ ((packed)); | 453 | } __attribute__ ((packed)); |
341 | 454 | ||
342 | /* structure representing interrupt data */ | 455 | struct swap_info_e4 { |
456 | __u8 bSwapPageNo; | ||
457 | } __attribute__ ((packed)); | ||
458 | |||
459 | /* structures representing interrupt data */ | ||
460 | #define e1_bSwapPageNo u.e1.s1.swapinfo.bSwapPageNo | ||
461 | #define e1_bOvl u.e1.s1.swapinfo.bOvl | ||
462 | #define e4_bSwapPageNo u.e4.s1.swapinfo.bSwapPageNo | ||
463 | |||
464 | #define INT_LOADSWAPPAGE 0x0001 | ||
465 | #define INT_INCOMINGCMV 0x0002 | ||
466 | |||
467 | union intr_data_e1 { | ||
468 | struct { | ||
469 | struct swap_info_e1 swapinfo; | ||
470 | __le16 wDataSize; | ||
471 | } __attribute__ ((packed)) s1; | ||
472 | struct { | ||
473 | struct cmv_e1 cmv; | ||
474 | __le16 wDataSize; | ||
475 | } __attribute__ ((packed)) s2; | ||
476 | } __attribute__ ((packed)); | ||
477 | |||
478 | union intr_data_e4 { | ||
479 | struct { | ||
480 | struct swap_info_e4 swapinfo; | ||
481 | __le16 wDataSize; | ||
482 | } __attribute__ ((packed)) s1; | ||
483 | struct { | ||
484 | struct cmv_e4 cmv; | ||
485 | __le16 wDataSize; | ||
486 | } __attribute__ ((packed)) s2; | ||
487 | } __attribute__ ((packed)); | ||
488 | |||
343 | struct intr_pkt { | 489 | struct intr_pkt { |
344 | __u8 bType; | 490 | __u8 bType; |
345 | __u8 bNotification; | 491 | __u8 bNotification; |
@@ -347,27 +493,18 @@ struct intr_pkt { | |||
347 | __le16 wIndex; | 493 | __le16 wIndex; |
348 | __le16 wLength; | 494 | __le16 wLength; |
349 | __le16 wInterrupt; | 495 | __le16 wInterrupt; |
350 | #define INT_LOADSWAPPAGE 0x0001 | ||
351 | #define INT_INCOMINGCMV 0x0002 | ||
352 | union { | 496 | union { |
353 | struct { | 497 | union intr_data_e1 e1; |
354 | struct swap_info swapinfo; | 498 | union intr_data_e4 e4; |
355 | __le16 wDataSize; | 499 | } u; |
356 | } __attribute__ ((packed)) s1; | ||
357 | |||
358 | struct { | ||
359 | struct cmv cmv; | ||
360 | __le16 wDataSize; | ||
361 | } __attribute__ ((packed)) s2; | ||
362 | } __attribute__ ((packed)) u; | ||
363 | #define bSwapPageNo u.s1.swapinfo.bSwapPageNo | ||
364 | #define bOvl u.s1.swapinfo.bOvl | ||
365 | } __attribute__ ((packed)); | 500 | } __attribute__ ((packed)); |
366 | #define INTR_PKT_SIZE 28 | 501 | |
502 | #define E1_INTR_PKT_SIZE 28 | ||
503 | #define E4_INTR_PKT_SIZE 64 | ||
367 | 504 | ||
368 | static struct usb_driver uea_driver; | 505 | static struct usb_driver uea_driver; |
369 | static DEFINE_MUTEX(uea_mutex); | 506 | static DEFINE_MUTEX(uea_mutex); |
370 | static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III"}; | 507 | static const char *chip_name[] = {"ADI930", "Eagle I", "Eagle II", "Eagle III", "Eagle IV"}; |
371 | 508 | ||
372 | static int modem_index; | 509 | static int modem_index; |
373 | static unsigned int debug; | 510 | static unsigned int debug; |
@@ -519,6 +656,9 @@ static int uea_load_firmware(struct usb_device *usb, unsigned int ver) | |||
519 | case EAGLE_III: | 656 | case EAGLE_III: |
520 | fw_name = FW_DIR "eagleIII.fw"; | 657 | fw_name = FW_DIR "eagleIII.fw"; |
521 | break; | 658 | break; |
659 | case EAGLE_IV: | ||
660 | fw_name = FW_DIR "eagleIV.fw"; | ||
661 | break; | ||
522 | } | 662 | } |
523 | 663 | ||
524 | ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware); | 664 | ret = request_firmware_nowait(THIS_MODULE, 1, fw_name, &usb->dev, usb, uea_upload_pre_firmware); |
@@ -537,7 +677,7 @@ static int uea_load_firmware(struct usb_device *usb, unsigned int ver) | |||
537 | /* | 677 | /* |
538 | * Make sure that the DSP code provided is safe to use. | 678 | * Make sure that the DSP code provided is safe to use. |
539 | */ | 679 | */ |
540 | static int check_dsp(u8 *dsp, unsigned int len) | 680 | static int check_dsp_e1(u8 *dsp, unsigned int len) |
541 | { | 681 | { |
542 | u8 pagecount, blockcount; | 682 | u8 pagecount, blockcount; |
543 | u16 blocksize; | 683 | u16 blocksize; |
@@ -588,6 +728,51 @@ static int check_dsp(u8 *dsp, unsigned int len) | |||
588 | return 0; | 728 | return 0; |
589 | } | 729 | } |
590 | 730 | ||
731 | static int check_dsp_e4(u8 *dsp, int len) | ||
732 | { | ||
733 | int i; | ||
734 | struct l1_code *p = (struct l1_code *) dsp; | ||
735 | unsigned int sum = p->code - dsp; | ||
736 | |||
737 | if (len < sum) | ||
738 | return 1; | ||
739 | |||
740 | if (strcmp("STRATIPHY ANEXA", p->string_header) != 0 && | ||
741 | strcmp("STRATIPHY ANEXB", p->string_header) != 0) | ||
742 | return 1; | ||
743 | |||
744 | for (i = 0; i < E4_MAX_PAGE_NUMBER; i++) { | ||
745 | struct block_index *blockidx; | ||
746 | u8 blockno = p->page_number_to_block_index[i]; | ||
747 | if (blockno >= E4_NO_SWAPPAGE_HEADERS) | ||
748 | continue; | ||
749 | |||
750 | do { | ||
751 | u64 l; | ||
752 | |||
753 | if (blockno >= E4_NO_SWAPPAGE_HEADERS) | ||
754 | return 1; | ||
755 | |||
756 | blockidx = &p->page_header[blockno++]; | ||
757 | if ((u8 *)(blockidx + 1) - dsp >= len) | ||
758 | return 1; | ||
759 | |||
760 | if (le16_to_cpu(blockidx->PageNumber) != i) | ||
761 | return 1; | ||
762 | |||
763 | l = E4_PAGE_BYTES(blockidx->PageSize); | ||
764 | sum += l; | ||
765 | l += le32_to_cpu(blockidx->PageOffset); | ||
766 | if (l > len) | ||
767 | return 1; | ||
768 | |||
769 | /* zero is zero regardless endianes */ | ||
770 | } while (blockidx->NotLastBlock); | ||
771 | } | ||
772 | |||
773 | return (sum == len) ? 0 : 1; | ||
774 | } | ||
775 | |||
591 | /* | 776 | /* |
592 | * send data to the idma pipe | 777 | * send data to the idma pipe |
593 | * */ | 778 | * */ |
@@ -624,7 +809,12 @@ static int request_dsp(struct uea_softc *sc) | |||
624 | int ret; | 809 | int ret; |
625 | char *dsp_name; | 810 | char *dsp_name; |
626 | 811 | ||
627 | if (UEA_CHIP_VERSION(sc) == ADI930) { | 812 | if (UEA_CHIP_VERSION(sc) == EAGLE_IV) { |
813 | if (IS_ISDN(sc->usb_dev)) | ||
814 | dsp_name = FW_DIR "DSP4i.bin"; | ||
815 | else | ||
816 | dsp_name = FW_DIR "DSP4p.bin"; | ||
817 | } else if (UEA_CHIP_VERSION(sc) == ADI930) { | ||
628 | if (IS_ISDN(sc->usb_dev)) | 818 | if (IS_ISDN(sc->usb_dev)) |
629 | dsp_name = FW_DIR "DSP9i.bin"; | 819 | dsp_name = FW_DIR "DSP9i.bin"; |
630 | else | 820 | else |
@@ -640,11 +830,16 @@ static int request_dsp(struct uea_softc *sc) | |||
640 | if (ret < 0) { | 830 | if (ret < 0) { |
641 | uea_err(INS_TO_USBDEV(sc), | 831 | uea_err(INS_TO_USBDEV(sc), |
642 | "requesting firmware %s failed with error %d\n", | 832 | "requesting firmware %s failed with error %d\n", |
643 | dsp_name, ret); | 833 | dsp_name, ret); |
644 | return ret; | 834 | return ret; |
645 | } | 835 | } |
646 | 836 | ||
647 | if (check_dsp(sc->dsp_firm->data, sc->dsp_firm->size)) { | 837 | if (UEA_CHIP_VERSION(sc) == EAGLE_IV) |
838 | ret = check_dsp_e4(sc->dsp_firm->data, sc->dsp_firm->size); | ||
839 | else | ||
840 | ret = check_dsp_e1(sc->dsp_firm->data, sc->dsp_firm->size); | ||
841 | |||
842 | if (ret) { | ||
648 | uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n", | 843 | uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n", |
649 | dsp_name); | 844 | dsp_name); |
650 | release_firmware(sc->dsp_firm); | 845 | release_firmware(sc->dsp_firm); |
@@ -658,12 +853,12 @@ static int request_dsp(struct uea_softc *sc) | |||
658 | /* | 853 | /* |
659 | * The uea_load_page() function must be called within a process context | 854 | * The uea_load_page() function must be called within a process context |
660 | */ | 855 | */ |
661 | static void uea_load_page(struct work_struct *work) | 856 | static void uea_load_page_e1(struct work_struct *work) |
662 | { | 857 | { |
663 | struct uea_softc *sc = container_of(work, struct uea_softc, task); | 858 | struct uea_softc *sc = container_of(work, struct uea_softc, task); |
664 | u16 pageno = sc->pageno; | 859 | u16 pageno = sc->pageno; |
665 | u16 ovl = sc->ovl; | 860 | u16 ovl = sc->ovl; |
666 | struct block_info bi; | 861 | struct block_info_e1 bi; |
667 | 862 | ||
668 | u8 *p; | 863 | u8 *p; |
669 | u8 pagecount, blockcount; | 864 | u8 pagecount, blockcount; |
@@ -716,7 +911,7 @@ static void uea_load_page(struct work_struct *work) | |||
716 | bi.wLast = cpu_to_le16((i == blockcount - 1) ? 1 : 0); | 911 | bi.wLast = cpu_to_le16((i == blockcount - 1) ? 1 : 0); |
717 | 912 | ||
718 | /* send block info through the IDMA pipe */ | 913 | /* send block info through the IDMA pipe */ |
719 | if (uea_idma_write(sc, &bi, BLOCK_INFO_SIZE)) | 914 | if (uea_idma_write(sc, &bi, E1_BLOCK_INFO_SIZE)) |
720 | goto bad2; | 915 | goto bad2; |
721 | 916 | ||
722 | /* send block data through the IDMA pipe */ | 917 | /* send block data through the IDMA pipe */ |
@@ -735,6 +930,103 @@ bad1: | |||
735 | uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno); | 930 | uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno); |
736 | } | 931 | } |
737 | 932 | ||
933 | static void __uea_load_page_e4(struct uea_softc *sc, u8 pageno, int boot) | ||
934 | { | ||
935 | struct block_info_e4 bi; | ||
936 | struct block_index *blockidx; | ||
937 | struct l1_code *p = (struct l1_code *) sc->dsp_firm->data; | ||
938 | u8 blockno = p->page_number_to_block_index[pageno]; | ||
939 | |||
940 | bi.wHdr = cpu_to_be16(UEA_BIHDR); | ||
941 | bi.bBootPage = boot; | ||
942 | bi.bPageNumber = pageno; | ||
943 | bi.wReserved = cpu_to_be16(UEA_RESERVED); | ||
944 | |||
945 | do { | ||
946 | u8 *blockoffset; | ||
947 | unsigned int blocksize; | ||
948 | |||
949 | blockidx = &p->page_header[blockno]; | ||
950 | blocksize = E4_PAGE_BYTES(blockidx->PageSize); | ||
951 | blockoffset = sc->dsp_firm->data + le32_to_cpu(blockidx->PageOffset); | ||
952 | |||
953 | bi.dwSize = cpu_to_be32(blocksize); | ||
954 | bi.dwAddress = swab32(blockidx->PageAddress); | ||
955 | |||
956 | uea_dbg(INS_TO_USBDEV(sc), | ||
957 | "sending block %u for DSP page %u size %u adress %x\n", | ||
958 | blockno, pageno, blocksize, le32_to_cpu(blockidx->PageAddress)); | ||
959 | |||
960 | /* send block info through the IDMA pipe */ | ||
961 | if (uea_idma_write(sc, &bi, E4_BLOCK_INFO_SIZE)) | ||
962 | goto bad; | ||
963 | |||
964 | /* send block data through the IDMA pipe */ | ||
965 | if (uea_idma_write(sc, blockoffset, blocksize)) | ||
966 | goto bad; | ||
967 | |||
968 | blockno++; | ||
969 | } while (blockidx->NotLastBlock); | ||
970 | |||
971 | return; | ||
972 | |||
973 | bad: | ||
974 | uea_err(INS_TO_USBDEV(sc), "sending DSP block %u failed\n", blockno); | ||
975 | return; | ||
976 | } | ||
977 | |||
978 | static void uea_load_page_e4(struct work_struct *work) | ||
979 | { | ||
980 | struct uea_softc *sc = container_of(work, struct uea_softc, task); | ||
981 | u8 pageno = sc->pageno; | ||
982 | int i; | ||
983 | struct block_info_e4 bi; | ||
984 | struct l1_code *p; | ||
985 | |||
986 | uea_dbg(INS_TO_USBDEV(sc), "sending DSP page %u\n", pageno); | ||
987 | |||
988 | /* reload firmware when reboot start and it's loaded already */ | ||
989 | if (pageno == 0 && sc->dsp_firm) { | ||
990 | release_firmware(sc->dsp_firm); | ||
991 | sc->dsp_firm = NULL; | ||
992 | } | ||
993 | |||
994 | if (sc->dsp_firm == NULL && request_dsp(sc) < 0) | ||
995 | return; | ||
996 | |||
997 | p = (struct l1_code *) sc->dsp_firm->data; | ||
998 | if (pageno >= p->page_header[0].PageNumber) { | ||
999 | uea_err(INS_TO_USBDEV(sc), "invalid DSP page %u requested\n", pageno); | ||
1000 | return; | ||
1001 | } | ||
1002 | |||
1003 | if (pageno != 0) { | ||
1004 | __uea_load_page_e4(sc, pageno, 0); | ||
1005 | return; | ||
1006 | } | ||
1007 | |||
1008 | uea_dbg(INS_TO_USBDEV(sc), | ||
1009 | "sending Main DSP page %u\n", p->page_header[0].PageNumber); | ||
1010 | |||
1011 | for (i = 0; i < le16_to_cpu(p->page_header[0].PageNumber); i++) { | ||
1012 | if (E4_IS_BOOT_PAGE(p->page_header[i].PageSize)) | ||
1013 | __uea_load_page_e4(sc, i, 1); | ||
1014 | } | ||
1015 | |||
1016 | uea_dbg(INS_TO_USBDEV(sc),"sending start bi\n"); | ||
1017 | |||
1018 | bi.wHdr = cpu_to_be16(UEA_BIHDR); | ||
1019 | bi.bBootPage = 0; | ||
1020 | bi.bPageNumber = 0xff; | ||
1021 | bi.wReserved = cpu_to_be16(UEA_RESERVED); | ||
1022 | bi.dwSize = cpu_to_be32(E4_PAGE_BYTES(p->page_header[0].PageSize)); | ||
1023 | bi.dwAddress = swab32(p->page_header[0].PageAddress); | ||
1024 | |||
1025 | /* send block info through the IDMA pipe */ | ||
1026 | if (uea_idma_write(sc, &bi, E4_BLOCK_INFO_SIZE)) | ||
1027 | uea_err(INS_TO_USBDEV(sc), "sending DSP start bi failed\n"); | ||
1028 | } | ||
1029 | |||
738 | static inline void wake_up_cmv_ack(struct uea_softc *sc) | 1030 | static inline void wake_up_cmv_ack(struct uea_softc *sc) |
739 | { | 1031 | { |
740 | BUG_ON(sc->cmv_ack); | 1032 | BUG_ON(sc->cmv_ack); |
@@ -792,33 +1084,68 @@ static int uea_request(struct uea_softc *sc, | |||
792 | return 0; | 1084 | return 0; |
793 | } | 1085 | } |
794 | 1086 | ||
795 | static int uea_cmv(struct uea_softc *sc, | 1087 | static int uea_cmv_e1(struct uea_softc *sc, |
796 | u8 function, u32 address, u16 offset, u32 data) | 1088 | u8 function, u32 address, u16 offset, u32 data) |
797 | { | 1089 | { |
798 | struct cmv cmv; | 1090 | struct cmv_e1 cmv; |
799 | int ret; | 1091 | int ret; |
800 | 1092 | ||
801 | uea_enters(INS_TO_USBDEV(sc)); | 1093 | uea_enters(INS_TO_USBDEV(sc)); |
802 | uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Address : %c%c%c%c, " | 1094 | uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Address : %c%c%c%c, " |
803 | "offset : 0x%04x, data : 0x%08x\n", | 1095 | "offset : 0x%04x, data : 0x%08x\n", |
804 | FUNCTION_TYPE(function), FUNCTION_SUBTYPE(function), | 1096 | E1_FUNCTION_TYPE(function), E1_FUNCTION_SUBTYPE(function), |
805 | GETSA1(address), GETSA2(address), GETSA3(address), | 1097 | E1_GETSA1(address), E1_GETSA2(address), E1_GETSA3(address), |
806 | GETSA4(address), offset, data); | 1098 | E1_GETSA4(address), offset, data); |
1099 | |||
807 | /* we send a request, but we expect a reply */ | 1100 | /* we send a request, but we expect a reply */ |
808 | sc->cmv_function = function | 0x2; | 1101 | sc->cmv_dsc.e1.function = function | 0x2; |
809 | sc->cmv_idx++; | 1102 | sc->cmv_dsc.e1.idx++; |
810 | sc->cmv_address = address; | 1103 | sc->cmv_dsc.e1.address = address; |
811 | sc->cmv_offset = offset; | 1104 | sc->cmv_dsc.e1.offset = offset; |
812 | 1105 | ||
813 | cmv.wPreamble = cpu_to_le16(PREAMBLE); | 1106 | cmv.wPreamble = cpu_to_le16(E1_PREAMBLE); |
814 | cmv.bDirection = HOSTTOMODEM; | 1107 | cmv.bDirection = E1_HOSTTOMODEM; |
815 | cmv.bFunction = function; | 1108 | cmv.bFunction = function; |
816 | cmv.wIndex = cpu_to_le16(sc->cmv_idx); | 1109 | cmv.wIndex = cpu_to_le16(sc->cmv_dsc.e1.idx); |
817 | put_unaligned(cpu_to_le32(address), &cmv.dwSymbolicAddress); | 1110 | put_unaligned(cpu_to_le32(address), &cmv.dwSymbolicAddress); |
818 | cmv.wOffsetAddress = cpu_to_le16(offset); | 1111 | cmv.wOffsetAddress = cpu_to_le16(offset); |
819 | put_unaligned(cpu_to_le32(data >> 16 | data << 16), &cmv.dwData); | 1112 | put_unaligned(cpu_to_le32(data >> 16 | data << 16), &cmv.dwData); |
820 | 1113 | ||
821 | ret = uea_request(sc, UEA_SET_BLOCK, UEA_MPTX_START, CMV_SIZE, &cmv); | 1114 | ret = uea_request(sc, UEA_E1_SET_BLOCK, UEA_MPTX_START, sizeof(cmv), &cmv); |
1115 | if (ret < 0) | ||
1116 | return ret; | ||
1117 | ret = wait_cmv_ack(sc); | ||
1118 | uea_leaves(INS_TO_USBDEV(sc)); | ||
1119 | return ret; | ||
1120 | } | ||
1121 | |||
1122 | static int uea_cmv_e4(struct uea_softc *sc, | ||
1123 | u16 function, u16 group, u16 address, u16 offset, u32 data) | ||
1124 | { | ||
1125 | struct cmv_e4 cmv; | ||
1126 | int ret; | ||
1127 | |||
1128 | uea_enters(INS_TO_USBDEV(sc)); | ||
1129 | memset(&cmv, 0, sizeof(cmv)); | ||
1130 | |||
1131 | uea_vdbg(INS_TO_USBDEV(sc), "Function : %d-%d, Group : 0x%04x, " | ||
1132 | "Address : 0x%04x, offset : 0x%04x, data : 0x%08x\n", | ||
1133 | E4_FUNCTION_TYPE(function), E4_FUNCTION_SUBTYPE(function), | ||
1134 | group, address, offset, data); | ||
1135 | |||
1136 | /* we send a request, but we expect a reply */ | ||
1137 | sc->cmv_dsc.e4.function = function | (0x1 << 4); | ||
1138 | sc->cmv_dsc.e4.offset = offset; | ||
1139 | sc->cmv_dsc.e4.address = address; | ||
1140 | sc->cmv_dsc.e4.group = group; | ||
1141 | |||
1142 | cmv.wFunction = cpu_to_be16(function); | ||
1143 | cmv.wGroup = cpu_to_be16(group); | ||
1144 | cmv.wAddress = cpu_to_be16(address); | ||
1145 | cmv.wOffset = cpu_to_be16(offset); | ||
1146 | cmv.dwData[0] = cpu_to_be32(data); | ||
1147 | |||
1148 | ret = uea_request(sc, UEA_E4_SET_BLOCK, UEA_MPTX_START, sizeof(cmv), &cmv); | ||
822 | if (ret < 0) | 1149 | if (ret < 0) |
823 | return ret; | 1150 | return ret; |
824 | ret = wait_cmv_ack(sc); | 1151 | ret = wait_cmv_ack(sc); |
@@ -826,10 +1153,10 @@ static int uea_cmv(struct uea_softc *sc, | |||
826 | return ret; | 1153 | return ret; |
827 | } | 1154 | } |
828 | 1155 | ||
829 | static inline int uea_read_cmv(struct uea_softc *sc, | 1156 | static inline int uea_read_cmv_e1(struct uea_softc *sc, |
830 | u32 address, u16 offset, u32 *data) | 1157 | u32 address, u16 offset, u32 *data) |
831 | { | 1158 | { |
832 | int ret = uea_cmv(sc, MAKEFUNCTION(MEMACCESS, REQUESTREAD), | 1159 | int ret = uea_cmv_e1(sc, E1_MAKEFUNCTION(E1_MEMACCESS, E1_REQUESTREAD), |
833 | address, offset, 0); | 1160 | address, offset, 0); |
834 | if (ret < 0) | 1161 | if (ret < 0) |
835 | uea_err(INS_TO_USBDEV(sc), | 1162 | uea_err(INS_TO_USBDEV(sc), |
@@ -840,10 +1167,27 @@ static inline int uea_read_cmv(struct uea_softc *sc, | |||
840 | return ret; | 1167 | return ret; |
841 | } | 1168 | } |
842 | 1169 | ||
843 | static inline int uea_write_cmv(struct uea_softc *sc, | 1170 | static inline int uea_read_cmv_e4(struct uea_softc *sc, |
1171 | u8 size, u16 group, u16 address, u16 offset, u32 *data) | ||
1172 | { | ||
1173 | int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS, E4_REQUESTREAD, size), | ||
1174 | group, address, offset, 0); | ||
1175 | if (ret < 0) | ||
1176 | uea_err(INS_TO_USBDEV(sc), | ||
1177 | "reading cmv failed with error %d\n", ret); | ||
1178 | else { | ||
1179 | *data = sc->data; | ||
1180 | /* size is in 16-bit word quantities */ | ||
1181 | if (size > 2) | ||
1182 | *(data + 1) = sc->data1; | ||
1183 | } | ||
1184 | return ret; | ||
1185 | } | ||
1186 | |||
1187 | static inline int uea_write_cmv_e1(struct uea_softc *sc, | ||
844 | u32 address, u16 offset, u32 data) | 1188 | u32 address, u16 offset, u32 data) |
845 | { | 1189 | { |
846 | int ret = uea_cmv(sc, MAKEFUNCTION(MEMACCESS, REQUESTWRITE), | 1190 | int ret = uea_cmv_e1(sc, E1_MAKEFUNCTION(E1_MEMACCESS, E1_REQUESTWRITE), |
847 | address, offset, data); | 1191 | address, offset, data); |
848 | if (ret < 0) | 1192 | if (ret < 0) |
849 | uea_err(INS_TO_USBDEV(sc), | 1193 | uea_err(INS_TO_USBDEV(sc), |
@@ -852,12 +1196,48 @@ static inline int uea_write_cmv(struct uea_softc *sc, | |||
852 | return ret; | 1196 | return ret; |
853 | } | 1197 | } |
854 | 1198 | ||
1199 | static inline int uea_write_cmv_e4(struct uea_softc *sc, | ||
1200 | u8 size, u16 group, u16 address, u16 offset, u32 data) | ||
1201 | { | ||
1202 | int ret = uea_cmv_e4(sc, E4_MAKEFUNCTION(E4_MEMACCESS, E4_REQUESTWRITE, size), | ||
1203 | group, address, offset, data); | ||
1204 | if (ret < 0) | ||
1205 | uea_err(INS_TO_USBDEV(sc), | ||
1206 | "writing cmv failed with error %d\n", ret); | ||
1207 | |||
1208 | return ret; | ||
1209 | } | ||
1210 | |||
1211 | static void uea_set_bulk_timeout(struct uea_softc *sc, u32 dsrate) | ||
1212 | { | ||
1213 | int ret; | ||
1214 | u16 timeout; | ||
1215 | |||
1216 | /* in bulk mode the modem have problem with high rate | ||
1217 | * changing internal timing could improve things, but the | ||
1218 | * value is misterious. | ||
1219 | * ADI930 don't support it (-EPIPE error). | ||
1220 | */ | ||
1221 | |||
1222 | if (UEA_CHIP_VERSION(sc) == ADI930 || | ||
1223 | use_iso[sc->modem_index] > 0 || | ||
1224 | sc->stats.phy.dsrate == dsrate) | ||
1225 | return; | ||
1226 | |||
1227 | /* Original timming (1Mbit/s) from ADI (used in windows driver) */ | ||
1228 | timeout = (dsrate <= 1024*1024) ? 0 : 1; | ||
1229 | ret = uea_request(sc, UEA_SET_TIMEOUT, timeout, 0, NULL); | ||
1230 | uea_info(INS_TO_USBDEV(sc), "setting new timeout %d%s\n", | ||
1231 | timeout, ret < 0 ? " failed" : ""); | ||
1232 | |||
1233 | } | ||
1234 | |||
855 | /* | 1235 | /* |
856 | * Monitor the modem and update the stat | 1236 | * Monitor the modem and update the stat |
857 | * return 0 if everything is ok | 1237 | * return 0 if everything is ok |
858 | * return < 0 if an error occurs (-EAGAIN reboot needed) | 1238 | * return < 0 if an error occurs (-EAGAIN reboot needed) |
859 | */ | 1239 | */ |
860 | static int uea_stat(struct uea_softc *sc) | 1240 | static int uea_stat_e1(struct uea_softc *sc) |
861 | { | 1241 | { |
862 | u32 data; | 1242 | u32 data; |
863 | int ret; | 1243 | int ret; |
@@ -865,7 +1245,7 @@ static int uea_stat(struct uea_softc *sc) | |||
865 | uea_enters(INS_TO_USBDEV(sc)); | 1245 | uea_enters(INS_TO_USBDEV(sc)); |
866 | data = sc->stats.phy.state; | 1246 | data = sc->stats.phy.state; |
867 | 1247 | ||
868 | ret = uea_read_cmv(sc, SA_STAT, 0, &sc->stats.phy.state); | 1248 | ret = uea_read_cmv_e1(sc, E1_SA_STAT, 0, &sc->stats.phy.state); |
869 | if (ret < 0) | 1249 | if (ret < 0) |
870 | return ret; | 1250 | return ret; |
871 | 1251 | ||
@@ -885,7 +1265,7 @@ static int uea_stat(struct uea_softc *sc) | |||
885 | 1265 | ||
886 | case 3: /* fail ... */ | 1266 | case 3: /* fail ... */ |
887 | uea_info(INS_TO_USBDEV(sc), "modem synchronization failed" | 1267 | uea_info(INS_TO_USBDEV(sc), "modem synchronization failed" |
888 | " (may be try other cmv/dsp)\n"); | 1268 | " (may be try other cmv/dsp)\n"); |
889 | return -EAGAIN; | 1269 | return -EAGAIN; |
890 | 1270 | ||
891 | case 4 ... 6: /* test state */ | 1271 | case 4 ... 6: /* test state */ |
@@ -923,7 +1303,7 @@ static int uea_stat(struct uea_softc *sc) | |||
923 | /* wake up processes waiting for synchronization */ | 1303 | /* wake up processes waiting for synchronization */ |
924 | wake_up(&sc->sync_q); | 1304 | wake_up(&sc->sync_q); |
925 | 1305 | ||
926 | ret = uea_read_cmv(sc, SA_DIAG, 2, &sc->stats.phy.flags); | 1306 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 2, &sc->stats.phy.flags); |
927 | if (ret < 0) | 1307 | if (ret < 0) |
928 | return ret; | 1308 | return ret; |
929 | sc->stats.phy.mflags |= sc->stats.phy.flags; | 1309 | sc->stats.phy.mflags |= sc->stats.phy.flags; |
@@ -937,105 +1317,223 @@ static int uea_stat(struct uea_softc *sc) | |||
937 | return 0; | 1317 | return 0; |
938 | } | 1318 | } |
939 | 1319 | ||
940 | ret = uea_read_cmv(sc, SA_RATE, 0, &data); | 1320 | ret = uea_read_cmv_e1(sc, E1_SA_RATE, 0, &data); |
941 | if (ret < 0) | 1321 | if (ret < 0) |
942 | return ret; | 1322 | return ret; |
943 | 1323 | ||
944 | /* in bulk mode the modem have problem with high rate | 1324 | uea_set_bulk_timeout(sc, (data >> 16) * 32); |
945 | * changing internal timing could improve things, but the | ||
946 | * value is misterious. | ||
947 | * ADI930 don't support it (-EPIPE error). | ||
948 | */ | ||
949 | if (UEA_CHIP_VERSION(sc) != ADI930 | ||
950 | && !use_iso[sc->modem_index] | ||
951 | && sc->stats.phy.dsrate != (data >> 16) * 32) { | ||
952 | /* Original timming from ADI(used in windows driver) | ||
953 | * 0x20ffff>>16 * 32 = 32 * 32 = 1Mbits | ||
954 | */ | ||
955 | u16 timeout = (data <= 0x20ffff) ? 0 : 1; | ||
956 | ret = uea_request(sc, UEA_SET_TIMEOUT, timeout, 0, NULL); | ||
957 | uea_info(INS_TO_USBDEV(sc), | ||
958 | "setting new timeout %d%s\n", timeout, | ||
959 | ret < 0?" failed":""); | ||
960 | } | ||
961 | sc->stats.phy.dsrate = (data >> 16) * 32; | 1325 | sc->stats.phy.dsrate = (data >> 16) * 32; |
962 | sc->stats.phy.usrate = (data & 0xffff) * 32; | 1326 | sc->stats.phy.usrate = (data & 0xffff) * 32; |
963 | UPDATE_ATM_STAT(link_rate, sc->stats.phy.dsrate * 1000 / 424); | 1327 | UPDATE_ATM_STAT(link_rate, sc->stats.phy.dsrate * 1000 / 424); |
964 | 1328 | ||
965 | ret = uea_read_cmv(sc, SA_DIAG, 23, &data); | 1329 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 23, &data); |
966 | if (ret < 0) | 1330 | if (ret < 0) |
967 | return ret; | 1331 | return ret; |
968 | sc->stats.phy.dsattenuation = (data & 0xff) / 2; | 1332 | sc->stats.phy.dsattenuation = (data & 0xff) / 2; |
969 | 1333 | ||
970 | ret = uea_read_cmv(sc, SA_DIAG, 47, &data); | 1334 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 47, &data); |
971 | if (ret < 0) | 1335 | if (ret < 0) |
972 | return ret; | 1336 | return ret; |
973 | sc->stats.phy.usattenuation = (data & 0xff) / 2; | 1337 | sc->stats.phy.usattenuation = (data & 0xff) / 2; |
974 | 1338 | ||
975 | ret = uea_read_cmv(sc, SA_DIAG, 25, &sc->stats.phy.dsmargin); | 1339 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 25, &sc->stats.phy.dsmargin); |
976 | if (ret < 0) | 1340 | if (ret < 0) |
977 | return ret; | 1341 | return ret; |
978 | 1342 | ||
979 | ret = uea_read_cmv(sc, SA_DIAG, 49, &sc->stats.phy.usmargin); | 1343 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 49, &sc->stats.phy.usmargin); |
980 | if (ret < 0) | 1344 | if (ret < 0) |
981 | return ret; | 1345 | return ret; |
982 | 1346 | ||
983 | ret = uea_read_cmv(sc, SA_DIAG, 51, &sc->stats.phy.rxflow); | 1347 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 51, &sc->stats.phy.rxflow); |
984 | if (ret < 0) | 1348 | if (ret < 0) |
985 | return ret; | 1349 | return ret; |
986 | 1350 | ||
987 | ret = uea_read_cmv(sc, SA_DIAG, 52, &sc->stats.phy.txflow); | 1351 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 52, &sc->stats.phy.txflow); |
988 | if (ret < 0) | 1352 | if (ret < 0) |
989 | return ret; | 1353 | return ret; |
990 | 1354 | ||
991 | ret = uea_read_cmv(sc, SA_DIAG, 54, &sc->stats.phy.dsunc); | 1355 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 54, &sc->stats.phy.dsunc); |
992 | if (ret < 0) | 1356 | if (ret < 0) |
993 | return ret; | 1357 | return ret; |
994 | 1358 | ||
995 | /* only for atu-c */ | 1359 | /* only for atu-c */ |
996 | ret = uea_read_cmv(sc, SA_DIAG, 58, &sc->stats.phy.usunc); | 1360 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 58, &sc->stats.phy.usunc); |
997 | if (ret < 0) | 1361 | if (ret < 0) |
998 | return ret; | 1362 | return ret; |
999 | 1363 | ||
1000 | ret = uea_read_cmv(sc, SA_DIAG, 53, &sc->stats.phy.dscorr); | 1364 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 53, &sc->stats.phy.dscorr); |
1001 | if (ret < 0) | 1365 | if (ret < 0) |
1002 | return ret; | 1366 | return ret; |
1003 | 1367 | ||
1004 | /* only for atu-c */ | 1368 | /* only for atu-c */ |
1005 | ret = uea_read_cmv(sc, SA_DIAG, 57, &sc->stats.phy.uscorr); | 1369 | ret = uea_read_cmv_e1(sc, E1_SA_DIAG, 57, &sc->stats.phy.uscorr); |
1006 | if (ret < 0) | 1370 | if (ret < 0) |
1007 | return ret; | 1371 | return ret; |
1008 | 1372 | ||
1009 | ret = uea_read_cmv(sc, SA_INFO, 8, &sc->stats.phy.vidco); | 1373 | ret = uea_read_cmv_e1(sc, E1_SA_INFO, 8, &sc->stats.phy.vidco); |
1010 | if (ret < 0) | 1374 | if (ret < 0) |
1011 | return ret; | 1375 | return ret; |
1012 | 1376 | ||
1013 | ret = uea_read_cmv(sc, SA_INFO, 13, &sc->stats.phy.vidcpe); | 1377 | ret = uea_read_cmv_e1(sc, E1_SA_INFO, 13, &sc->stats.phy.vidcpe); |
1014 | if (ret < 0) | 1378 | if (ret < 0) |
1015 | return ret; | 1379 | return ret; |
1016 | 1380 | ||
1017 | return 0; | 1381 | return 0; |
1018 | } | 1382 | } |
1019 | 1383 | ||
1020 | static int request_cmvs(struct uea_softc *sc, | 1384 | static int uea_stat_e4(struct uea_softc *sc) |
1021 | struct uea_cmvs **cmvs, const struct firmware **fw) | ||
1022 | { | 1385 | { |
1023 | int ret, size; | 1386 | u32 data; |
1024 | u8 *data; | 1387 | u32 tmp_arr[2]; |
1388 | int ret; | ||
1389 | |||
1390 | uea_enters(INS_TO_USBDEV(sc)); | ||
1391 | data = sc->stats.phy.state; | ||
1392 | |||
1393 | /* XXX only need to be done before operationnal... */ | ||
1394 | ret = uea_read_cmv_e4(sc, 1, E4_SA_STAT, 0, 0, &sc->stats.phy.state); | ||
1395 | if (ret < 0) | ||
1396 | return ret; | ||
1397 | |||
1398 | switch (sc->stats.phy.state) { | ||
1399 | case 0x0: /* not yet synchronized */ | ||
1400 | case 0x1: | ||
1401 | case 0x3: | ||
1402 | case 0x4: | ||
1403 | uea_dbg(INS_TO_USBDEV(sc), "modem not yet synchronized\n"); | ||
1404 | return 0; | ||
1405 | case 0x5: /* initialization */ | ||
1406 | case 0x6: | ||
1407 | case 0x9: | ||
1408 | case 0xa: | ||
1409 | uea_dbg(INS_TO_USBDEV(sc), "modem initializing\n"); | ||
1410 | return 0; | ||
1411 | case 0x2: /* fail ... */ | ||
1412 | uea_info(INS_TO_USBDEV(sc), "modem synchronization failed" | ||
1413 | " (may be try other cmv/dsp)\n"); | ||
1414 | return -EAGAIN; | ||
1415 | case 0x7: /* operational */ | ||
1416 | break; | ||
1417 | default: | ||
1418 | uea_warn(INS_TO_USBDEV(sc), "unknown state: %x\n", sc->stats.phy.state); | ||
1419 | return 0; | ||
1420 | } | ||
1421 | |||
1422 | if (data != 7) { | ||
1423 | uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_OFF, 0, NULL); | ||
1424 | uea_info(INS_TO_USBDEV(sc), "modem operational\n"); | ||
1425 | |||
1426 | /* release the dsp firmware as it is not needed until | ||
1427 | * the next failure | ||
1428 | */ | ||
1429 | if (sc->dsp_firm) { | ||
1430 | release_firmware(sc->dsp_firm); | ||
1431 | sc->dsp_firm = NULL; | ||
1432 | } | ||
1433 | } | ||
1434 | |||
1435 | /* always update it as atm layer could not be init when we switch to | ||
1436 | * operational state | ||
1437 | */ | ||
1438 | UPDATE_ATM_STAT(signal, ATM_PHY_SIG_FOUND); | ||
1439 | |||
1440 | /* wake up processes waiting for synchronization */ | ||
1441 | wake_up(&sc->sync_q); | ||
1442 | |||
1443 | /* TODO improve this state machine : | ||
1444 | * we need some CMV info : what they do and their unit | ||
1445 | * we should find the equivalent of eagle3- CMV | ||
1446 | */ | ||
1447 | /* check flags */ | ||
1448 | ret = uea_read_cmv_e4(sc, 1, E4_SA_DIAG, 0, 0, &sc->stats.phy.flags); | ||
1449 | if (ret < 0) | ||
1450 | return ret; | ||
1451 | sc->stats.phy.mflags |= sc->stats.phy.flags; | ||
1452 | |||
1453 | /* in case of a flags ( for example delineation LOSS (& 0x10)), | ||
1454 | * we check the status again in order to detect the failure earlier | ||
1455 | */ | ||
1456 | if (sc->stats.phy.flags) { | ||
1457 | uea_dbg(INS_TO_USBDEV(sc), "Stat flag = 0x%x\n", | ||
1458 | sc->stats.phy.flags); | ||
1459 | if (sc->stats.phy.flags & 1) //delineation LOSS | ||
1460 | return -EAGAIN; | ||
1461 | if (sc->stats.phy.flags & 0x4000) //Reset Flag | ||
1462 | return -EAGAIN; | ||
1463 | return 0; | ||
1464 | } | ||
1465 | |||
1466 | /* rate data may be in upper or lower half of 64 bit word, strange */ | ||
1467 | ret = uea_read_cmv_e4(sc, 4, E4_SA_RATE, 0, 0, tmp_arr); | ||
1468 | if (ret < 0) | ||
1469 | return ret; | ||
1470 | data = (tmp_arr[0]) ? tmp_arr[0] : tmp_arr[1]; | ||
1471 | sc->stats.phy.usrate = data / 1000; | ||
1472 | |||
1473 | ret = uea_read_cmv_e4(sc, 4, E4_SA_RATE, 1, 0, tmp_arr); | ||
1474 | if (ret < 0) | ||
1475 | return ret; | ||
1476 | data = (tmp_arr[0]) ? tmp_arr[0] : tmp_arr[1]; | ||
1477 | uea_set_bulk_timeout(sc, data / 1000); | ||
1478 | sc->stats.phy.dsrate = data / 1000; | ||
1479 | UPDATE_ATM_STAT(link_rate, sc->stats.phy.dsrate * 1000 / 424); | ||
1480 | |||
1481 | ret = uea_read_cmv_e4(sc, 1, E4_SA_INFO, 68, 1, &data); | ||
1482 | if (ret < 0) | ||
1483 | return ret; | ||
1484 | sc->stats.phy.dsattenuation = data / 10; | ||
1485 | |||
1486 | ret = uea_read_cmv_e4(sc, 1, E4_SA_INFO, 69, 1, &data); | ||
1487 | if (ret < 0) | ||
1488 | return ret; | ||
1489 | sc->stats.phy.usattenuation = data / 10; | ||
1490 | |||
1491 | ret = uea_read_cmv_e4(sc, 1, E4_SA_INFO, 68, 3, &data); | ||
1492 | if (ret < 0) | ||
1493 | return ret; | ||
1494 | sc->stats.phy.dsmargin = data / 2; | ||
1495 | |||
1496 | ret = uea_read_cmv_e4(sc, 1, E4_SA_INFO, 69, 3, &data); | ||
1497 | if (ret < 0) | ||
1498 | return ret; | ||
1499 | sc->stats.phy.usmargin = data / 10; | ||
1500 | |||
1501 | return 0; | ||
1502 | } | ||
1503 | |||
1504 | static void cmvs_file_name(struct uea_softc *sc, char *const cmv_name, int ver) | ||
1505 | { | ||
1506 | char file_arr[] = "CMVxy.bin"; | ||
1025 | char *file; | 1507 | char *file; |
1026 | char cmv_name[FIRMWARE_NAME_MAX]; /* 30 bytes stack variable */ | ||
1027 | 1508 | ||
1509 | /* set proper name corresponding modem version and line type */ | ||
1028 | if (cmv_file[sc->modem_index] == NULL) { | 1510 | if (cmv_file[sc->modem_index] == NULL) { |
1029 | if (UEA_CHIP_VERSION(sc) == ADI930) | 1511 | if (UEA_CHIP_VERSION(sc) == ADI930) |
1030 | file = (IS_ISDN(sc->usb_dev)) ? "CMV9i.bin" : "CMV9p.bin"; | 1512 | file_arr[3] = '9'; |
1513 | else if (UEA_CHIP_VERSION(sc) == EAGLE_IV) | ||
1514 | file_arr[3] = '4'; | ||
1031 | else | 1515 | else |
1032 | file = (IS_ISDN(sc->usb_dev)) ? "CMVei.bin" : "CMVep.bin"; | 1516 | file_arr[3] = 'e'; |
1517 | |||
1518 | file_arr[4] = IS_ISDN(sc->usb_dev) ? 'i' : 'p'; | ||
1519 | file = file_arr; | ||
1033 | } else | 1520 | } else |
1034 | file = cmv_file[sc->modem_index]; | 1521 | file = cmv_file[sc->modem_index]; |
1035 | 1522 | ||
1036 | strcpy(cmv_name, FW_DIR); | 1523 | strcpy(cmv_name, FW_DIR); |
1037 | strlcat(cmv_name, file, sizeof(cmv_name)); | 1524 | strlcat(cmv_name, file, FIRMWARE_NAME_MAX); |
1525 | if (ver == 2) | ||
1526 | strlcat(cmv_name, ".v2", FIRMWARE_NAME_MAX); | ||
1527 | } | ||
1528 | |||
1529 | static int request_cmvs_old(struct uea_softc *sc, | ||
1530 | void **cmvs, const struct firmware **fw) | ||
1531 | { | ||
1532 | int ret, size; | ||
1533 | u8 *data; | ||
1534 | char cmv_name[FIRMWARE_NAME_MAX]; /* 30 bytes stack variable */ | ||
1038 | 1535 | ||
1536 | cmvs_file_name(sc, cmv_name, 1); | ||
1039 | ret = request_firmware(fw, cmv_name, &sc->usb_dev->dev); | 1537 | ret = request_firmware(fw, cmv_name, &sc->usb_dev->dev); |
1040 | if (ret < 0) { | 1538 | if (ret < 0) { |
1041 | uea_err(INS_TO_USBDEV(sc), | 1539 | uea_err(INS_TO_USBDEV(sc), |
@@ -1045,16 +1543,197 @@ static int request_cmvs(struct uea_softc *sc, | |||
1045 | } | 1543 | } |
1046 | 1544 | ||
1047 | data = (u8 *) (*fw)->data; | 1545 | data = (u8 *) (*fw)->data; |
1048 | size = *data * sizeof(struct uea_cmvs) + 1; | 1546 | size = (*fw)->size; |
1049 | if (size != (*fw)->size) { | 1547 | if (size < 1) |
1050 | uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n", | 1548 | goto err_fw_corrupted; |
1051 | cmv_name); | 1549 | |
1052 | release_firmware(*fw); | 1550 | if (size != *data * sizeof(struct uea_cmvs_v1) + 1) |
1053 | return -EILSEQ; | 1551 | goto err_fw_corrupted; |
1552 | |||
1553 | *cmvs = (void *)(data + 1); | ||
1554 | return *data; | ||
1555 | |||
1556 | err_fw_corrupted: | ||
1557 | uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n", cmv_name); | ||
1558 | release_firmware(*fw); | ||
1559 | return -EILSEQ; | ||
1560 | } | ||
1561 | |||
1562 | static int request_cmvs(struct uea_softc *sc, | ||
1563 | void **cmvs, const struct firmware **fw, int *ver) | ||
1564 | { | ||
1565 | int ret, size; | ||
1566 | u32 crc; | ||
1567 | u8 *data; | ||
1568 | char cmv_name[FIRMWARE_NAME_MAX]; /* 30 bytes stack variable */ | ||
1569 | |||
1570 | cmvs_file_name(sc, cmv_name, 2); | ||
1571 | ret = request_firmware(fw, cmv_name, &sc->usb_dev->dev); | ||
1572 | if (ret < 0) { | ||
1573 | /* if caller can handle old version, try to provide it */ | ||
1574 | if (*ver == 1) { | ||
1575 | uea_warn(INS_TO_USBDEV(sc), "requesting firmware %s failed, " | ||
1576 | "try to get older cmvs\n", cmv_name); | ||
1577 | return request_cmvs_old(sc, cmvs, fw); | ||
1578 | } | ||
1579 | uea_err(INS_TO_USBDEV(sc), | ||
1580 | "requesting firmware %s failed with error %d\n", | ||
1581 | cmv_name, ret); | ||
1582 | return ret; | ||
1583 | } | ||
1584 | |||
1585 | size = (*fw)->size; | ||
1586 | data = (u8 *) (*fw)->data; | ||
1587 | if (size < 4 || strncmp(data, "cmv2", 4) != 0) { | ||
1588 | if (*ver == 1) { | ||
1589 | uea_warn(INS_TO_USBDEV(sc), "firmware %s is corrupted, " | ||
1590 | "try to get older cmvs\n", cmv_name); | ||
1591 | release_firmware(*fw); | ||
1592 | return request_cmvs_old(sc, cmvs, fw); | ||
1593 | } | ||
1594 | goto err_fw_corrupted; | ||
1054 | } | 1595 | } |
1055 | 1596 | ||
1056 | *cmvs = (struct uea_cmvs *)(data + 1); | 1597 | *ver = 2; |
1598 | |||
1599 | data += 4; | ||
1600 | size -= 4; | ||
1601 | if (size < 5) | ||
1602 | goto err_fw_corrupted; | ||
1603 | |||
1604 | crc = FW_GET_LONG(data); | ||
1605 | data += 4; | ||
1606 | size -= 4; | ||
1607 | if (crc32_be(0, data, size) != crc) | ||
1608 | goto err_fw_corrupted; | ||
1609 | |||
1610 | if (size != *data * sizeof(struct uea_cmvs_v2) + 1) | ||
1611 | goto err_fw_corrupted; | ||
1612 | |||
1613 | *cmvs = (void *) (data + 1); | ||
1057 | return *data; | 1614 | return *data; |
1615 | |||
1616 | err_fw_corrupted: | ||
1617 | uea_err(INS_TO_USBDEV(sc), "firmware %s is corrupted\n", cmv_name); | ||
1618 | release_firmware(*fw); | ||
1619 | return -EILSEQ; | ||
1620 | } | ||
1621 | |||
1622 | static int uea_send_cmvs_e1(struct uea_softc *sc) | ||
1623 | { | ||
1624 | int i, ret, len; | ||
1625 | void *cmvs_ptr; | ||
1626 | const struct firmware *cmvs_fw; | ||
1627 | int ver = 1; // we can handle v1 cmv firmware version; | ||
1628 | |||
1629 | /* Enter in R-IDLE (cmv) until instructed otherwise */ | ||
1630 | ret = uea_write_cmv_e1(sc, E1_SA_CNTL, 0, 1); | ||
1631 | if (ret < 0) | ||
1632 | return ret; | ||
1633 | |||
1634 | /* Dump firmware version */ | ||
1635 | ret = uea_read_cmv_e1(sc, E1_SA_INFO, 10, &sc->stats.phy.firmid); | ||
1636 | if (ret < 0) | ||
1637 | return ret; | ||
1638 | uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n", | ||
1639 | sc->stats.phy.firmid); | ||
1640 | |||
1641 | /* get options */ | ||
1642 | ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver); | ||
1643 | if (ret < 0) | ||
1644 | return ret; | ||
1645 | |||
1646 | /* send options */ | ||
1647 | if (ver == 1) { | ||
1648 | struct uea_cmvs_v1 *cmvs_v1 = cmvs_ptr; | ||
1649 | |||
1650 | uea_warn(INS_TO_USBDEV(sc), "use deprecated cmvs version, " | ||
1651 | "please update your firmware\n"); | ||
1652 | |||
1653 | for (i = 0; i < len; i++) { | ||
1654 | ret = uea_write_cmv_e1(sc, FW_GET_LONG(&cmvs_v1[i].address), | ||
1655 | FW_GET_WORD(&cmvs_v1[i].offset), | ||
1656 | FW_GET_LONG(&cmvs_v1[i].data)); | ||
1657 | if (ret < 0) | ||
1658 | goto out; | ||
1659 | } | ||
1660 | } else if (ver == 2) { | ||
1661 | struct uea_cmvs_v2 *cmvs_v2 = cmvs_ptr; | ||
1662 | |||
1663 | for (i = 0; i < len; i++) { | ||
1664 | ret = uea_write_cmv_e1(sc, FW_GET_LONG(&cmvs_v2[i].address), | ||
1665 | (u16) FW_GET_LONG(&cmvs_v2[i].offset), | ||
1666 | FW_GET_LONG(&cmvs_v2[i].data)); | ||
1667 | if (ret < 0) | ||
1668 | goto out; | ||
1669 | } | ||
1670 | } else { | ||
1671 | /* This realy should not happen */ | ||
1672 | uea_err(INS_TO_USBDEV(sc), "bad cmvs version %d\n", ver); | ||
1673 | goto out; | ||
1674 | } | ||
1675 | |||
1676 | /* Enter in R-ACT-REQ */ | ||
1677 | ret = uea_write_cmv_e1(sc, E1_SA_CNTL, 0, 2); | ||
1678 | uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n"); | ||
1679 | uea_info(INS_TO_USBDEV(sc), "modem started, waiting synchronization...\n"); | ||
1680 | out: | ||
1681 | release_firmware(cmvs_fw); | ||
1682 | return ret; | ||
1683 | } | ||
1684 | |||
1685 | static int uea_send_cmvs_e4(struct uea_softc *sc) | ||
1686 | { | ||
1687 | int i, ret, len; | ||
1688 | void *cmvs_ptr; | ||
1689 | const struct firmware *cmvs_fw; | ||
1690 | int ver = 2; // we can only handle v2 cmv firmware version; | ||
1691 | |||
1692 | /* Enter in R-IDLE (cmv) until instructed otherwise */ | ||
1693 | ret = uea_write_cmv_e4(sc, 1, E4_SA_CNTL, 0, 0, 1); | ||
1694 | if (ret < 0) | ||
1695 | return ret; | ||
1696 | |||
1697 | /* Dump firmware version */ | ||
1698 | /* XXX don't read the 3th byte as it is always 6 */ | ||
1699 | ret = uea_read_cmv_e4(sc, 2, E4_SA_INFO, 55, 0, &sc->stats.phy.firmid); | ||
1700 | if (ret < 0) | ||
1701 | return ret; | ||
1702 | uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n", | ||
1703 | sc->stats.phy.firmid); | ||
1704 | |||
1705 | |||
1706 | /* get options */ | ||
1707 | ret = len = request_cmvs(sc, &cmvs_ptr, &cmvs_fw, &ver); | ||
1708 | if (ret < 0) | ||
1709 | return ret; | ||
1710 | |||
1711 | /* send options */ | ||
1712 | if (ver == 2) { | ||
1713 | struct uea_cmvs_v2 *cmvs_v2 = cmvs_ptr; | ||
1714 | |||
1715 | for (i = 0; i < len; i++) { | ||
1716 | ret = uea_write_cmv_e4(sc, 1, | ||
1717 | FW_GET_LONG(&cmvs_v2[i].group), | ||
1718 | FW_GET_LONG(&cmvs_v2[i].address), | ||
1719 | FW_GET_LONG(&cmvs_v2[i].offset), | ||
1720 | FW_GET_LONG(&cmvs_v2[i].data)); | ||
1721 | if (ret < 0) | ||
1722 | goto out; | ||
1723 | } | ||
1724 | } else { | ||
1725 | /* This realy should not happen */ | ||
1726 | uea_err(INS_TO_USBDEV(sc), "bad cmvs version %d\n", ver); | ||
1727 | goto out; | ||
1728 | } | ||
1729 | |||
1730 | /* Enter in R-ACT-REQ */ | ||
1731 | ret = uea_write_cmv_e4(sc, 1, E4_SA_CNTL, 0, 0, 2); | ||
1732 | uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n"); | ||
1733 | uea_info(INS_TO_USBDEV(sc), "modem started, waiting synchronization...\n"); | ||
1734 | out: | ||
1735 | release_firmware(cmvs_fw); | ||
1736 | return ret; | ||
1058 | } | 1737 | } |
1059 | 1738 | ||
1060 | /* Start boot post firmware modem: | 1739 | /* Start boot post firmware modem: |
@@ -1066,9 +1745,7 @@ static int request_cmvs(struct uea_softc *sc, | |||
1066 | static int uea_start_reset(struct uea_softc *sc) | 1745 | static int uea_start_reset(struct uea_softc *sc) |
1067 | { | 1746 | { |
1068 | u16 zero = 0; /* ;-) */ | 1747 | u16 zero = 0; /* ;-) */ |
1069 | int i, len, ret; | 1748 | int ret; |
1070 | struct uea_cmvs *cmvs; | ||
1071 | const struct firmware *cmvs_fw; | ||
1072 | 1749 | ||
1073 | uea_enters(INS_TO_USBDEV(sc)); | 1750 | uea_enters(INS_TO_USBDEV(sc)); |
1074 | uea_info(INS_TO_USBDEV(sc), "(re)booting started\n"); | 1751 | uea_info(INS_TO_USBDEV(sc), "(re)booting started\n"); |
@@ -1098,13 +1775,20 @@ static int uea_start_reset(struct uea_softc *sc) | |||
1098 | /* leave reset mode */ | 1775 | /* leave reset mode */ |
1099 | uea_request(sc, UEA_SET_MODE, UEA_END_RESET, 0, NULL); | 1776 | uea_request(sc, UEA_SET_MODE, UEA_END_RESET, 0, NULL); |
1100 | 1777 | ||
1101 | /* clear tx and rx mailboxes */ | 1778 | if (UEA_CHIP_VERSION(sc) != EAGLE_IV) { |
1102 | uea_request(sc, UEA_SET_2183_DATA, UEA_MPTX_MAILBOX, 2, &zero); | 1779 | /* clear tx and rx mailboxes */ |
1103 | uea_request(sc, UEA_SET_2183_DATA, UEA_MPRX_MAILBOX, 2, &zero); | 1780 | uea_request(sc, UEA_SET_2183_DATA, UEA_MPTX_MAILBOX, 2, &zero); |
1104 | uea_request(sc, UEA_SET_2183_DATA, UEA_SWAP_MAILBOX, 2, &zero); | 1781 | uea_request(sc, UEA_SET_2183_DATA, UEA_MPRX_MAILBOX, 2, &zero); |
1782 | uea_request(sc, UEA_SET_2183_DATA, UEA_SWAP_MAILBOX, 2, &zero); | ||
1783 | } | ||
1105 | 1784 | ||
1106 | msleep(1000); | 1785 | msleep(1000); |
1107 | sc->cmv_function = MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY); | 1786 | |
1787 | if (UEA_CHIP_VERSION(sc) == EAGLE_IV) | ||
1788 | sc->cmv_dsc.e4.function = E4_MAKEFUNCTION(E4_ADSLDIRECTIVE, E4_MODEMREADY, 1); | ||
1789 | else | ||
1790 | sc->cmv_dsc.e1.function = E1_MAKEFUNCTION(E1_ADSLDIRECTIVE, E1_MODEMREADY); | ||
1791 | |||
1108 | /* demask interrupt */ | 1792 | /* demask interrupt */ |
1109 | sc->booting = 0; | 1793 | sc->booting = 0; |
1110 | 1794 | ||
@@ -1120,38 +1804,10 @@ static int uea_start_reset(struct uea_softc *sc) | |||
1120 | 1804 | ||
1121 | uea_vdbg(INS_TO_USBDEV(sc), "Ready CMV received\n"); | 1805 | uea_vdbg(INS_TO_USBDEV(sc), "Ready CMV received\n"); |
1122 | 1806 | ||
1123 | /* Enter in R-IDLE (cmv) until instructed otherwise */ | 1807 | ret = sc->send_cmvs(sc); |
1124 | ret = uea_write_cmv(sc, SA_CNTL, 0, 1); | ||
1125 | if (ret < 0) | ||
1126 | return ret; | ||
1127 | |||
1128 | /* Dump firmware version */ | ||
1129 | ret = uea_read_cmv(sc, SA_INFO, 10, &sc->stats.phy.firmid); | ||
1130 | if (ret < 0) | ||
1131 | return ret; | ||
1132 | uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n", | ||
1133 | sc->stats.phy.firmid); | ||
1134 | |||
1135 | /* get options */ | ||
1136 | ret = len = request_cmvs(sc, &cmvs, &cmvs_fw); | ||
1137 | if (ret < 0) | 1808 | if (ret < 0) |
1138 | return ret; | 1809 | return ret; |
1139 | 1810 | ||
1140 | /* send options */ | ||
1141 | for (i = 0; i < len; i++) { | ||
1142 | ret = uea_write_cmv(sc, FW_GET_LONG(&cmvs[i].address), | ||
1143 | FW_GET_WORD(&cmvs[i].offset), | ||
1144 | FW_GET_LONG(&cmvs[i].data)); | ||
1145 | if (ret < 0) | ||
1146 | goto out; | ||
1147 | } | ||
1148 | /* Enter in R-ACT-REQ */ | ||
1149 | ret = uea_write_cmv(sc, SA_CNTL, 0, 2); | ||
1150 | uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n"); | ||
1151 | uea_info(INS_TO_USBDEV(sc), "Modem started, " | ||
1152 | "waiting synchronization\n"); | ||
1153 | out: | ||
1154 | release_firmware(cmvs_fw); | ||
1155 | sc->reset = 0; | 1811 | sc->reset = 0; |
1156 | uea_leaves(INS_TO_USBDEV(sc)); | 1812 | uea_leaves(INS_TO_USBDEV(sc)); |
1157 | return ret; | 1813 | return ret; |
@@ -1174,7 +1830,7 @@ static int uea_kthread(void *data) | |||
1174 | if (ret < 0 || sc->reset) | 1830 | if (ret < 0 || sc->reset) |
1175 | ret = uea_start_reset(sc); | 1831 | ret = uea_start_reset(sc); |
1176 | if (!ret) | 1832 | if (!ret) |
1177 | ret = uea_stat(sc); | 1833 | ret = sc->stat(sc); |
1178 | if (ret != -EAGAIN) | 1834 | if (ret != -EAGAIN) |
1179 | msleep_interruptible(1000); | 1835 | msleep_interruptible(1000); |
1180 | if (try_to_freeze()) | 1836 | if (try_to_freeze()) |
@@ -1234,7 +1890,6 @@ static int load_XILINX_firmware(struct uea_softc *sc) | |||
1234 | if (ret < 0) | 1890 | if (ret < 0) |
1235 | uea_err(sc->usb_dev, "elsa de-assert failed with error %d\n", ret); | 1891 | uea_err(sc->usb_dev, "elsa de-assert failed with error %d\n", ret); |
1236 | 1892 | ||
1237 | |||
1238 | err1: | 1893 | err1: |
1239 | release_firmware(fw_entry); | 1894 | release_firmware(fw_entry); |
1240 | err0: | 1895 | err0: |
@@ -1243,40 +1898,41 @@ err0: | |||
1243 | } | 1898 | } |
1244 | 1899 | ||
1245 | /* The modem send us an ack. First with check if it right */ | 1900 | /* The modem send us an ack. First with check if it right */ |
1246 | static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv) | 1901 | static void uea_dispatch_cmv_e1(struct uea_softc *sc, struct intr_pkt *intr) |
1247 | { | 1902 | { |
1903 | struct cmv_dsc_e1 *dsc = &sc->cmv_dsc.e1; | ||
1904 | struct cmv_e1 *cmv = &intr->u.e1.s2.cmv; | ||
1905 | |||
1248 | uea_enters(INS_TO_USBDEV(sc)); | 1906 | uea_enters(INS_TO_USBDEV(sc)); |
1249 | if (le16_to_cpu(cmv->wPreamble) != PREAMBLE) | 1907 | if (le16_to_cpu(cmv->wPreamble) != E1_PREAMBLE) |
1250 | goto bad1; | 1908 | goto bad1; |
1251 | 1909 | ||
1252 | if (cmv->bDirection != MODEMTOHOST) | 1910 | if (cmv->bDirection != E1_MODEMTOHOST) |
1253 | goto bad1; | 1911 | goto bad1; |
1254 | 1912 | ||
1255 | /* FIXME : ADI930 reply wrong preambule (func = 2, sub = 2) to | 1913 | /* FIXME : ADI930 reply wrong preambule (func = 2, sub = 2) to |
1256 | * the first MEMACESS cmv. Ignore it... | 1914 | * the first MEMACESS cmv. Ignore it... |
1257 | */ | 1915 | */ |
1258 | if (cmv->bFunction != sc->cmv_function) { | 1916 | if (cmv->bFunction != dsc->function) { |
1259 | if (UEA_CHIP_VERSION(sc) == ADI930 | 1917 | if (UEA_CHIP_VERSION(sc) == ADI930 |
1260 | && cmv->bFunction == MAKEFUNCTION(2, 2)) { | 1918 | && cmv->bFunction == E1_MAKEFUNCTION(2, 2)) { |
1261 | cmv->wIndex = cpu_to_le16(sc->cmv_idx); | 1919 | cmv->wIndex = cpu_to_le16(dsc->idx); |
1262 | put_unaligned(cpu_to_le32(sc->cmv_address), &cmv->dwSymbolicAddress); | 1920 | put_unaligned(cpu_to_le32(dsc->address), &cmv->dwSymbolicAddress); |
1263 | cmv->wOffsetAddress = cpu_to_le16(sc->cmv_offset); | 1921 | cmv->wOffsetAddress = cpu_to_le16(dsc->offset); |
1264 | } | 1922 | } else |
1265 | else | ||
1266 | goto bad2; | 1923 | goto bad2; |
1267 | } | 1924 | } |
1268 | 1925 | ||
1269 | if (cmv->bFunction == MAKEFUNCTION(ADSLDIRECTIVE, MODEMREADY)) { | 1926 | if (cmv->bFunction == E1_MAKEFUNCTION(E1_ADSLDIRECTIVE, E1_MODEMREADY)) { |
1270 | wake_up_cmv_ack(sc); | 1927 | wake_up_cmv_ack(sc); |
1271 | uea_leaves(INS_TO_USBDEV(sc)); | 1928 | uea_leaves(INS_TO_USBDEV(sc)); |
1272 | return; | 1929 | return; |
1273 | } | 1930 | } |
1274 | 1931 | ||
1275 | /* in case of MEMACCESS */ | 1932 | /* in case of MEMACCESS */ |
1276 | if (le16_to_cpu(cmv->wIndex) != sc->cmv_idx || | 1933 | if (le16_to_cpu(cmv->wIndex) != dsc->idx || |
1277 | le32_to_cpu(get_unaligned(&cmv->dwSymbolicAddress)) != | 1934 | le32_to_cpu(get_unaligned(&cmv->dwSymbolicAddress)) != dsc->address || |
1278 | sc->cmv_address | 1935 | le16_to_cpu(cmv->wOffsetAddress) != dsc->offset) |
1279 | || le16_to_cpu(cmv->wOffsetAddress) != sc->cmv_offset) | ||
1280 | goto bad2; | 1936 | goto bad2; |
1281 | 1937 | ||
1282 | sc->data = le32_to_cpu(get_unaligned(&cmv->dwData)); | 1938 | sc->data = le32_to_cpu(get_unaligned(&cmv->dwData)); |
@@ -1289,8 +1945,8 @@ static void uea_dispatch_cmv(struct uea_softc *sc, struct cmv* cmv) | |||
1289 | bad2: | 1945 | bad2: |
1290 | uea_err(INS_TO_USBDEV(sc), "unexpected cmv received," | 1946 | uea_err(INS_TO_USBDEV(sc), "unexpected cmv received," |
1291 | "Function : %d, Subfunction : %d\n", | 1947 | "Function : %d, Subfunction : %d\n", |
1292 | FUNCTION_TYPE(cmv->bFunction), | 1948 | E1_FUNCTION_TYPE(cmv->bFunction), |
1293 | FUNCTION_SUBTYPE(cmv->bFunction)); | 1949 | E1_FUNCTION_SUBTYPE(cmv->bFunction)); |
1294 | uea_leaves(INS_TO_USBDEV(sc)); | 1950 | uea_leaves(INS_TO_USBDEV(sc)); |
1295 | return; | 1951 | return; |
1296 | 1952 | ||
@@ -1301,6 +1957,61 @@ bad1: | |||
1301 | uea_leaves(INS_TO_USBDEV(sc)); | 1957 | uea_leaves(INS_TO_USBDEV(sc)); |
1302 | } | 1958 | } |
1303 | 1959 | ||
1960 | /* The modem send us an ack. First with check if it right */ | ||
1961 | static void uea_dispatch_cmv_e4(struct uea_softc *sc, struct intr_pkt *intr) | ||
1962 | { | ||
1963 | struct cmv_dsc_e4 *dsc = &sc->cmv_dsc.e4; | ||
1964 | struct cmv_e4 *cmv = &intr->u.e4.s2.cmv; | ||
1965 | |||
1966 | uea_enters(INS_TO_USBDEV(sc)); | ||
1967 | uea_dbg(INS_TO_USBDEV(sc), "cmv %x %x %x %x %x %x\n", | ||
1968 | be16_to_cpu(cmv->wGroup), be16_to_cpu(cmv->wFunction), | ||
1969 | be16_to_cpu(cmv->wOffset), be16_to_cpu(cmv->wAddress), | ||
1970 | be32_to_cpu(cmv->dwData[0]), be32_to_cpu(cmv->dwData[1])); | ||
1971 | |||
1972 | if (be16_to_cpu(cmv->wFunction) != dsc->function) | ||
1973 | goto bad2; | ||
1974 | |||
1975 | if (be16_to_cpu(cmv->wFunction) == E4_MAKEFUNCTION(E4_ADSLDIRECTIVE, E4_MODEMREADY, 1)) { | ||
1976 | wake_up_cmv_ack(sc); | ||
1977 | uea_leaves(INS_TO_USBDEV(sc)); | ||
1978 | return; | ||
1979 | } | ||
1980 | |||
1981 | /* in case of MEMACCESS */ | ||
1982 | if (be16_to_cpu(cmv->wOffset) != dsc->offset || | ||
1983 | be16_to_cpu(cmv->wGroup) != dsc->group || | ||
1984 | be16_to_cpu(cmv->wAddress) != dsc->address) | ||
1985 | goto bad2; | ||
1986 | |||
1987 | sc->data = be32_to_cpu(cmv->dwData[0]); | ||
1988 | sc->data1 = be32_to_cpu(cmv->dwData[1]); | ||
1989 | wake_up_cmv_ack(sc); | ||
1990 | uea_leaves(INS_TO_USBDEV(sc)); | ||
1991 | return; | ||
1992 | |||
1993 | bad2: | ||
1994 | uea_err(INS_TO_USBDEV(sc), "unexpected cmv received," | ||
1995 | "Function : %d, Subfunction : %d\n", | ||
1996 | E4_FUNCTION_TYPE(cmv->wFunction), | ||
1997 | E4_FUNCTION_SUBTYPE(cmv->wFunction)); | ||
1998 | uea_leaves(INS_TO_USBDEV(sc)); | ||
1999 | return; | ||
2000 | } | ||
2001 | |||
2002 | static void uea_schedule_load_page_e1(struct uea_softc *sc, struct intr_pkt *intr) | ||
2003 | { | ||
2004 | sc->pageno = intr->e1_bSwapPageNo; | ||
2005 | sc->ovl = intr->e1_bOvl >> 4 | intr->e1_bOvl << 4; | ||
2006 | schedule_work(&sc->task); | ||
2007 | } | ||
2008 | |||
2009 | static void uea_schedule_load_page_e4(struct uea_softc *sc, struct intr_pkt *intr) | ||
2010 | { | ||
2011 | sc->pageno = intr->e4_bSwapPageNo; | ||
2012 | schedule_work(&sc->task); | ||
2013 | } | ||
2014 | |||
1304 | /* | 2015 | /* |
1305 | * interrupt handler | 2016 | * interrupt handler |
1306 | */ | 2017 | */ |
@@ -1326,13 +2037,11 @@ static void uea_intr(struct urb *urb) | |||
1326 | 2037 | ||
1327 | switch (le16_to_cpu(intr->wInterrupt)) { | 2038 | switch (le16_to_cpu(intr->wInterrupt)) { |
1328 | case INT_LOADSWAPPAGE: | 2039 | case INT_LOADSWAPPAGE: |
1329 | sc->pageno = intr->bSwapPageNo; | 2040 | sc->schedule_load_page(sc, intr); |
1330 | sc->ovl = intr->bOvl >> 4 | intr->bOvl << 4; | ||
1331 | schedule_work(&sc->task); | ||
1332 | break; | 2041 | break; |
1333 | 2042 | ||
1334 | case INT_INCOMINGCMV: | 2043 | case INT_INCOMINGCMV: |
1335 | uea_dispatch_cmv(sc, &intr->u.s2.cmv); | 2044 | sc->dispatch_cmv(sc, intr); |
1336 | break; | 2045 | break; |
1337 | 2046 | ||
1338 | default: | 2047 | default: |
@@ -1349,19 +2058,34 @@ resubmit: | |||
1349 | */ | 2058 | */ |
1350 | static int uea_boot(struct uea_softc *sc) | 2059 | static int uea_boot(struct uea_softc *sc) |
1351 | { | 2060 | { |
1352 | int ret; | 2061 | int ret, size; |
1353 | struct intr_pkt *intr; | 2062 | struct intr_pkt *intr; |
1354 | 2063 | ||
1355 | uea_enters(INS_TO_USBDEV(sc)); | 2064 | uea_enters(INS_TO_USBDEV(sc)); |
1356 | 2065 | ||
1357 | INIT_WORK(&sc->task, uea_load_page); | 2066 | if (UEA_CHIP_VERSION(sc) == EAGLE_IV) { |
2067 | size = E4_INTR_PKT_SIZE; | ||
2068 | sc->dispatch_cmv = uea_dispatch_cmv_e4; | ||
2069 | sc->schedule_load_page = uea_schedule_load_page_e4; | ||
2070 | sc->stat = uea_stat_e4; | ||
2071 | sc->send_cmvs = uea_send_cmvs_e4; | ||
2072 | INIT_WORK(&sc->task, uea_load_page_e4); | ||
2073 | } else { | ||
2074 | size = E1_INTR_PKT_SIZE; | ||
2075 | sc->dispatch_cmv = uea_dispatch_cmv_e1; | ||
2076 | sc->schedule_load_page = uea_schedule_load_page_e1; | ||
2077 | sc->stat = uea_stat_e1; | ||
2078 | sc->send_cmvs = uea_send_cmvs_e1; | ||
2079 | INIT_WORK(&sc->task, uea_load_page_e1); | ||
2080 | } | ||
2081 | |||
1358 | init_waitqueue_head(&sc->sync_q); | 2082 | init_waitqueue_head(&sc->sync_q); |
1359 | init_waitqueue_head(&sc->cmv_ack_wait); | 2083 | init_waitqueue_head(&sc->cmv_ack_wait); |
1360 | 2084 | ||
1361 | if (UEA_CHIP_VERSION(sc) == ADI930) | 2085 | if (UEA_CHIP_VERSION(sc) == ADI930) |
1362 | load_XILINX_firmware(sc); | 2086 | load_XILINX_firmware(sc); |
1363 | 2087 | ||
1364 | intr = kmalloc(INTR_PKT_SIZE, GFP_KERNEL); | 2088 | intr = kmalloc(size, GFP_KERNEL); |
1365 | if (!intr) { | 2089 | if (!intr) { |
1366 | uea_err(INS_TO_USBDEV(sc), | 2090 | uea_err(INS_TO_USBDEV(sc), |
1367 | "cannot allocate interrupt package\n"); | 2091 | "cannot allocate interrupt package\n"); |
@@ -1377,7 +2101,7 @@ static int uea_boot(struct uea_softc *sc) | |||
1377 | 2101 | ||
1378 | usb_fill_int_urb(sc->urb_int, sc->usb_dev, | 2102 | usb_fill_int_urb(sc->urb_int, sc->usb_dev, |
1379 | usb_rcvintpipe(sc->usb_dev, UEA_INTR_PIPE), | 2103 | usb_rcvintpipe(sc->usb_dev, UEA_INTR_PIPE), |
1380 | intr, INTR_PKT_SIZE, uea_intr, sc, | 2104 | intr, size, uea_intr, sc, |
1381 | sc->usb_dev->actconfig->interface[0]->altsetting[0]. | 2105 | sc->usb_dev->actconfig->interface[0]->altsetting[0]. |
1382 | endpoint[0].desc.bInterval); | 2106 | endpoint[0].desc.bInterval); |
1383 | 2107 | ||
@@ -1487,6 +2211,7 @@ static ssize_t read_human_status(struct device *dev, struct device_attribute *at | |||
1487 | char *buf) | 2211 | char *buf) |
1488 | { | 2212 | { |
1489 | int ret = -ENODEV; | 2213 | int ret = -ENODEV; |
2214 | int modem_state; | ||
1490 | struct uea_softc *sc; | 2215 | struct uea_softc *sc; |
1491 | 2216 | ||
1492 | mutex_lock(&uea_mutex); | 2217 | mutex_lock(&uea_mutex); |
@@ -1494,7 +2219,34 @@ static ssize_t read_human_status(struct device *dev, struct device_attribute *at | |||
1494 | if (!sc) | 2219 | if (!sc) |
1495 | goto out; | 2220 | goto out; |
1496 | 2221 | ||
1497 | switch (GET_STATUS(sc->stats.phy.state)) { | 2222 | if (UEA_CHIP_VERSION(sc) == EAGLE_IV) { |
2223 | switch (sc->stats.phy.state) { | ||
2224 | case 0x0: /* not yet synchronized */ | ||
2225 | case 0x1: | ||
2226 | case 0x3: | ||
2227 | case 0x4: | ||
2228 | modem_state = 0; | ||
2229 | break; | ||
2230 | case 0x5: /* initialization */ | ||
2231 | case 0x6: | ||
2232 | case 0x9: | ||
2233 | case 0xa: | ||
2234 | modem_state = 1; | ||
2235 | break; | ||
2236 | case 0x7: /* operational */ | ||
2237 | modem_state = 2; | ||
2238 | break; | ||
2239 | case 0x2: /* fail ... */ | ||
2240 | modem_state = 3; | ||
2241 | break; | ||
2242 | default: /* unknown */ | ||
2243 | modem_state = 4; | ||
2244 | break; | ||
2245 | } | ||
2246 | } else | ||
2247 | modem_state = GET_STATUS(sc->stats.phy.state); | ||
2248 | |||
2249 | switch (modem_state) { | ||
1498 | case 0: | 2250 | case 0: |
1499 | ret = sprintf(buf, "Modem is booting\n"); | 2251 | ret = sprintf(buf, "Modem is booting\n"); |
1500 | break; | 2252 | break; |
@@ -1504,9 +2256,12 @@ static ssize_t read_human_status(struct device *dev, struct device_attribute *at | |||
1504 | case 2: | 2256 | case 2: |
1505 | ret = sprintf(buf, "Modem is operational\n"); | 2257 | ret = sprintf(buf, "Modem is operational\n"); |
1506 | break; | 2258 | break; |
1507 | default: | 2259 | case 3: |
1508 | ret = sprintf(buf, "Modem synchronization failed\n"); | 2260 | ret = sprintf(buf, "Modem synchronization failed\n"); |
1509 | break; | 2261 | break; |
2262 | default: | ||
2263 | ret = sprintf(buf, "Modem state is unknown\n"); | ||
2264 | break; | ||
1510 | } | 2265 | } |
1511 | out: | 2266 | out: |
1512 | mutex_unlock(&uea_mutex); | 2267 | mutex_unlock(&uea_mutex); |
@@ -1520,18 +2275,26 @@ static ssize_t read_delin(struct device *dev, struct device_attribute *attr, | |||
1520 | { | 2275 | { |
1521 | int ret = -ENODEV; | 2276 | int ret = -ENODEV; |
1522 | struct uea_softc *sc; | 2277 | struct uea_softc *sc; |
2278 | char *delin = "GOOD"; | ||
1523 | 2279 | ||
1524 | mutex_lock(&uea_mutex); | 2280 | mutex_lock(&uea_mutex); |
1525 | sc = dev_to_uea(dev); | 2281 | sc = dev_to_uea(dev); |
1526 | if (!sc) | 2282 | if (!sc) |
1527 | goto out; | 2283 | goto out; |
1528 | 2284 | ||
1529 | if (sc->stats.phy.flags & 0x0C00) | 2285 | if (UEA_CHIP_VERSION(sc) == EAGLE_IV) { |
1530 | ret = sprintf(buf, "ERROR\n"); | 2286 | if (sc->stats.phy.flags & 0x4000) |
1531 | else if (sc->stats.phy.flags & 0x0030) | 2287 | delin = "RESET"; |
1532 | ret = sprintf(buf, "LOSS\n"); | 2288 | else if (sc->stats.phy.flags & 0x0001) |
1533 | else | 2289 | delin = "LOSS"; |
1534 | ret = sprintf(buf, "GOOD\n"); | 2290 | } else { |
2291 | if (sc->stats.phy.flags & 0x0C00) | ||
2292 | delin = "ERROR"; | ||
2293 | else if (sc->stats.phy.flags & 0x0030) | ||
2294 | delin = "LOSS"; | ||
2295 | } | ||
2296 | |||
2297 | ret = sprintf(buf, "%s\n", delin); | ||
1535 | out: | 2298 | out: |
1536 | mutex_unlock(&uea_mutex); | 2299 | mutex_unlock(&uea_mutex); |
1537 | return ret; | 2300 | return ret; |
@@ -1803,6 +2566,8 @@ static const struct usb_device_id uea_ids[] = { | |||
1803 | {USB_DEVICE(EAGLE_VID, EAGLE_IIC_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM}, | 2566 | {USB_DEVICE(EAGLE_VID, EAGLE_IIC_PID_PSTFIRM), .driver_info = EAGLE_II | PSTFIRM}, |
1804 | {USB_DEVICE(EAGLE_VID, EAGLE_III_PID_PREFIRM), .driver_info = EAGLE_III | PREFIRM}, | 2567 | {USB_DEVICE(EAGLE_VID, EAGLE_III_PID_PREFIRM), .driver_info = EAGLE_III | PREFIRM}, |
1805 | {USB_DEVICE(EAGLE_VID, EAGLE_III_PID_PSTFIRM), .driver_info = EAGLE_III | PSTFIRM}, | 2568 | {USB_DEVICE(EAGLE_VID, EAGLE_III_PID_PSTFIRM), .driver_info = EAGLE_III | PSTFIRM}, |
2569 | {USB_DEVICE(EAGLE_VID, EAGLE_IV_PID_PREFIRM), .driver_info = EAGLE_IV | PREFIRM}, | ||
2570 | {USB_DEVICE(EAGLE_VID, EAGLE_IV_PID_PSTFIRM), .driver_info = EAGLE_IV | PSTFIRM}, | ||
1806 | {USB_DEVICE(USR_VID, MILLER_A_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, | 2571 | {USB_DEVICE(USR_VID, MILLER_A_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, |
1807 | {USB_DEVICE(USR_VID, MILLER_A_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM}, | 2572 | {USB_DEVICE(USR_VID, MILLER_A_PID_PSTFIRM), .driver_info = EAGLE_I | PSTFIRM}, |
1808 | {USB_DEVICE(USR_VID, MILLER_B_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, | 2573 | {USB_DEVICE(USR_VID, MILLER_B_PID_PREFIRM), .driver_info = EAGLE_I | PREFIRM}, |