diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2008-04-30 03:53:39 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 11:29:42 -0400 |
commit | 037182346f0991683cc7320a257c3f6089432cee (patch) | |
tree | 476546c5af156b9fd01a8f0bf2f5d2f206b961aa /drivers/char/moxa.c | |
parent | 9e9fc313ffa3cb92f7f81a8e076566bc9d582351 (diff) |
Char: moxa, add firmware loading
Substitute ioctl load firmware interface by kernel firmware api.
Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Tested-by: Oyvind Aabling <Oyvind.Aabling@uni-c.dk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/moxa.c')
-rw-r--r-- | drivers/char/moxa.c | 1219 |
1 files changed, 511 insertions, 708 deletions
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 428c1380b771..133819cf2c5c 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/mm.h> | 25 | #include <linux/mm.h> |
26 | #include <linux/ioport.h> | 26 | #include <linux/ioport.h> |
27 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
28 | #include <linux/firmware.h> | ||
28 | #include <linux/signal.h> | 29 | #include <linux/signal.h> |
29 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
30 | #include <linux/timer.h> | 31 | #include <linux/timer.h> |
@@ -47,8 +48,12 @@ | |||
47 | #include <asm/io.h> | 48 | #include <asm/io.h> |
48 | #include <asm/uaccess.h> | 49 | #include <asm/uaccess.h> |
49 | 50 | ||
51 | #include "moxa.h" | ||
52 | |||
50 | #define MOXA_VERSION "5.1k" | 53 | #define MOXA_VERSION "5.1k" |
51 | 54 | ||
55 | #define MOXA_FW_HDRLEN 32 | ||
56 | |||
52 | #define MOXAMAJOR 172 | 57 | #define MOXAMAJOR 172 |
53 | #define MOXACUMAJOR 173 | 58 | #define MOXACUMAJOR 173 |
54 | 59 | ||
@@ -92,6 +97,8 @@ static struct pci_device_id moxa_pcibrds[] = { | |||
92 | MODULE_DEVICE_TABLE(pci, moxa_pcibrds); | 97 | MODULE_DEVICE_TABLE(pci, moxa_pcibrds); |
93 | #endif /* CONFIG_PCI */ | 98 | #endif /* CONFIG_PCI */ |
94 | 99 | ||
100 | struct moxa_port; | ||
101 | |||
95 | static struct moxa_board_conf { | 102 | static struct moxa_board_conf { |
96 | int boardType; | 103 | int boardType; |
97 | int numPorts; | 104 | int numPorts; |
@@ -99,6 +106,8 @@ static struct moxa_board_conf { | |||
99 | 106 | ||
100 | int loadstat; | 107 | int loadstat; |
101 | 108 | ||
109 | struct moxa_port *ports; | ||
110 | |||
102 | void __iomem *basemem; | 111 | void __iomem *basemem; |
103 | void __iomem *intNdx; | 112 | void __iomem *intNdx; |
104 | void __iomem *intPend; | 113 | void __iomem *intPend; |
@@ -156,6 +165,7 @@ struct moxa_port { | |||
156 | #define WAKEUP_CHARS 256 | 165 | #define WAKEUP_CHARS 256 |
157 | 166 | ||
158 | static int ttymajor = MOXAMAJOR; | 167 | static int ttymajor = MOXAMAJOR; |
168 | static int moxaCard; | ||
159 | /* Variables for insmod */ | 169 | /* Variables for insmod */ |
160 | #ifdef MODULE | 170 | #ifdef MODULE |
161 | static unsigned long baseaddr[MAX_BOARDS]; | 171 | static unsigned long baseaddr[MAX_BOARDS]; |
@@ -208,7 +218,6 @@ static void moxa_receive_data(struct moxa_port *); | |||
208 | /* | 218 | /* |
209 | * moxa board interface functions: | 219 | * moxa board interface functions: |
210 | */ | 220 | */ |
211 | static void MoxaDriverInit(void); | ||
212 | static int MoxaDriverIoctl(unsigned int, unsigned long, int); | 221 | static int MoxaDriverIoctl(unsigned int, unsigned long, int); |
213 | static int MoxaDriverPoll(void); | 222 | static int MoxaDriverPoll(void); |
214 | static int MoxaPortsOfCard(int); | 223 | static int MoxaPortsOfCard(int); |
@@ -263,6 +272,489 @@ static struct moxa_port moxa_ports[MAX_PORTS]; | |||
263 | static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); | 272 | static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0); |
264 | static DEFINE_SPINLOCK(moxa_lock); | 273 | static DEFINE_SPINLOCK(moxa_lock); |
265 | 274 | ||
275 | static int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model) | ||
276 | { | ||
277 | switch (brd->boardType) { | ||
278 | case MOXA_BOARD_C218_ISA: | ||
279 | case MOXA_BOARD_C218_PCI: | ||
280 | if (model != 1) | ||
281 | goto err; | ||
282 | break; | ||
283 | case MOXA_BOARD_CP204J: | ||
284 | if (model != 3) | ||
285 | goto err; | ||
286 | break; | ||
287 | default: | ||
288 | if (model != 2) | ||
289 | goto err; | ||
290 | break; | ||
291 | } | ||
292 | return 0; | ||
293 | err: | ||
294 | return -EINVAL; | ||
295 | } | ||
296 | |||
297 | static int moxa_check_fw(const void *ptr) | ||
298 | { | ||
299 | const __le16 *lptr = ptr; | ||
300 | |||
301 | if (*lptr != cpu_to_le16(0x7980)) | ||
302 | return -EINVAL; | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf, | ||
308 | size_t len) | ||
309 | { | ||
310 | void __iomem *baseAddr = brd->basemem; | ||
311 | u16 tmp; | ||
312 | |||
313 | writeb(HW_reset, baseAddr + Control_reg); /* reset */ | ||
314 | msleep(10); | ||
315 | memset_io(baseAddr, 0, 4096); | ||
316 | memcpy_toio(baseAddr, buf, len); /* download BIOS */ | ||
317 | writeb(0, baseAddr + Control_reg); /* restart */ | ||
318 | |||
319 | msleep(2000); | ||
320 | |||
321 | switch (brd->boardType) { | ||
322 | case MOXA_BOARD_C218_ISA: | ||
323 | case MOXA_BOARD_C218_PCI: | ||
324 | tmp = readw(baseAddr + C218_key); | ||
325 | if (tmp != C218_KeyCode) | ||
326 | goto err; | ||
327 | break; | ||
328 | case MOXA_BOARD_CP204J: | ||
329 | tmp = readw(baseAddr + C218_key); | ||
330 | if (tmp != CP204J_KeyCode) | ||
331 | goto err; | ||
332 | break; | ||
333 | default: | ||
334 | tmp = readw(baseAddr + C320_key); | ||
335 | if (tmp != C320_KeyCode) | ||
336 | goto err; | ||
337 | tmp = readw(baseAddr + C320_status); | ||
338 | if (tmp != STS_init) { | ||
339 | printk(KERN_ERR "moxa: bios upload failed -- CPU/Basic " | ||
340 | "module not found\n"); | ||
341 | return -EIO; | ||
342 | } | ||
343 | break; | ||
344 | } | ||
345 | |||
346 | return 0; | ||
347 | err: | ||
348 | printk(KERN_ERR "moxa: bios upload failed -- board not found\n"); | ||
349 | return -EIO; | ||
350 | } | ||
351 | |||
352 | static int moxa_load_320b(struct moxa_board_conf *brd, const u8 *ptr, | ||
353 | size_t len) | ||
354 | { | ||
355 | void __iomem *baseAddr = brd->basemem; | ||
356 | |||
357 | if (len < 7168) { | ||
358 | printk(KERN_ERR "moxa: invalid 320 bios -- too short\n"); | ||
359 | return -EINVAL; | ||
360 | } | ||
361 | |||
362 | writew(len - 7168 - 2, baseAddr + C320bapi_len); | ||
363 | writeb(1, baseAddr + Control_reg); /* Select Page 1 */ | ||
364 | memcpy_toio(baseAddr + DynPage_addr, ptr, 7168); | ||
365 | writeb(2, baseAddr + Control_reg); /* Select Page 2 */ | ||
366 | memcpy_toio(baseAddr + DynPage_addr, ptr + 7168, len - 7168); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static int moxa_load_c218(struct moxa_board_conf *brd, const void *ptr, | ||
372 | size_t len) | ||
373 | { | ||
374 | void __iomem *baseAddr = brd->basemem; | ||
375 | const u16 *uptr = ptr; | ||
376 | size_t wlen, len2, j; | ||
377 | unsigned int i, retry; | ||
378 | u16 usum, keycode; | ||
379 | |||
380 | if (brd->boardType == MOXA_BOARD_CP204J) | ||
381 | keycode = CP204J_KeyCode; | ||
382 | else | ||
383 | keycode = C218_KeyCode; | ||
384 | usum = 0; | ||
385 | wlen = len >> 1; | ||
386 | for (i = 0; i < wlen; i++) | ||
387 | usum += le16_to_cpu(uptr[i]); | ||
388 | retry = 0; | ||
389 | do { | ||
390 | wlen = len >> 1; | ||
391 | j = 0; | ||
392 | while (wlen) { | ||
393 | len2 = (wlen > 2048) ? 2048 : wlen; | ||
394 | wlen -= len2; | ||
395 | memcpy_toio(baseAddr + C218_LoadBuf, ptr + j, | ||
396 | len2 << 1); | ||
397 | j += len2 << 1; | ||
398 | |||
399 | writew(len2, baseAddr + C218DLoad_len); | ||
400 | writew(0, baseAddr + C218_key); | ||
401 | for (i = 0; i < 100; i++) { | ||
402 | if (readw(baseAddr + C218_key) == keycode) | ||
403 | break; | ||
404 | msleep(10); | ||
405 | } | ||
406 | if (readw(baseAddr + C218_key) != keycode) | ||
407 | return -EIO; | ||
408 | } | ||
409 | writew(0, baseAddr + C218DLoad_len); | ||
410 | writew(usum, baseAddr + C218check_sum); | ||
411 | writew(0, baseAddr + C218_key); | ||
412 | for (i = 0; i < 100; i++) { | ||
413 | if (readw(baseAddr + C218_key) == keycode) | ||
414 | break; | ||
415 | msleep(10); | ||
416 | } | ||
417 | retry++; | ||
418 | } while ((readb(baseAddr + C218chksum_ok) != 1) && (retry < 3)); | ||
419 | if (readb(baseAddr + C218chksum_ok) != 1) | ||
420 | return -EIO; | ||
421 | |||
422 | writew(0, baseAddr + C218_key); | ||
423 | for (i = 0; i < 100; i++) { | ||
424 | if (readw(baseAddr + Magic_no) == Magic_code) | ||
425 | break; | ||
426 | msleep(10); | ||
427 | } | ||
428 | if (readw(baseAddr + Magic_no) != Magic_code) | ||
429 | return -EIO; | ||
430 | |||
431 | writew(1, baseAddr + Disable_IRQ); | ||
432 | writew(0, baseAddr + Magic_no); | ||
433 | for (i = 0; i < 100; i++) { | ||
434 | if (readw(baseAddr + Magic_no) == Magic_code) | ||
435 | break; | ||
436 | msleep(10); | ||
437 | } | ||
438 | if (readw(baseAddr + Magic_no) != Magic_code) | ||
439 | return -EIO; | ||
440 | |||
441 | moxaCard = 1; | ||
442 | brd->intNdx = baseAddr + IRQindex; | ||
443 | brd->intPend = baseAddr + IRQpending; | ||
444 | brd->intTable = baseAddr + IRQtable; | ||
445 | |||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | static int moxa_load_c320(struct moxa_board_conf *brd, const void *ptr, | ||
450 | size_t len) | ||
451 | { | ||
452 | void __iomem *baseAddr = brd->basemem; | ||
453 | const u16 *uptr = ptr; | ||
454 | size_t wlen, len2, j; | ||
455 | unsigned int i, retry; | ||
456 | u16 usum; | ||
457 | |||
458 | usum = 0; | ||
459 | wlen = len >> 1; | ||
460 | for (i = 0; i < wlen; i++) | ||
461 | usum += le16_to_cpu(uptr[i]); | ||
462 | retry = 0; | ||
463 | do { | ||
464 | wlen = len >> 1; | ||
465 | j = 0; | ||
466 | while (wlen) { | ||
467 | len2 = (wlen > 2048) ? 2048 : wlen; | ||
468 | wlen -= len2; | ||
469 | memcpy_toio(baseAddr + C320_LoadBuf, ptr + j, | ||
470 | len2 << 1); | ||
471 | j += len2 << 1; | ||
472 | writew(len2, baseAddr + C320DLoad_len); | ||
473 | writew(0, baseAddr + C320_key); | ||
474 | for (i = 0; i < 10; i++) { | ||
475 | if (readw(baseAddr + C320_key) == C320_KeyCode) | ||
476 | break; | ||
477 | msleep(10); | ||
478 | } | ||
479 | if (readw(baseAddr + C320_key) != C320_KeyCode) | ||
480 | return -EIO; | ||
481 | } | ||
482 | writew(0, baseAddr + C320DLoad_len); | ||
483 | writew(usum, baseAddr + C320check_sum); | ||
484 | writew(0, baseAddr + C320_key); | ||
485 | for (i = 0; i < 10; i++) { | ||
486 | if (readw(baseAddr + C320_key) == C320_KeyCode) | ||
487 | break; | ||
488 | msleep(10); | ||
489 | } | ||
490 | retry++; | ||
491 | } while ((readb(baseAddr + C320chksum_ok) != 1) && (retry < 3)); | ||
492 | if (readb(baseAddr + C320chksum_ok) != 1) | ||
493 | return -EIO; | ||
494 | |||
495 | writew(0, baseAddr + C320_key); | ||
496 | for (i = 0; i < 600; i++) { | ||
497 | if (readw(baseAddr + Magic_no) == Magic_code) | ||
498 | break; | ||
499 | msleep(10); | ||
500 | } | ||
501 | if (readw(baseAddr + Magic_no) != Magic_code) | ||
502 | return -EIO; | ||
503 | |||
504 | if (brd->busType == MOXA_BUS_TYPE_PCI) { /* ASIC board */ | ||
505 | writew(0x3800, baseAddr + TMS320_PORT1); | ||
506 | writew(0x3900, baseAddr + TMS320_PORT2); | ||
507 | writew(28499, baseAddr + TMS320_CLOCK); | ||
508 | } else { | ||
509 | writew(0x3200, baseAddr + TMS320_PORT1); | ||
510 | writew(0x3400, baseAddr + TMS320_PORT2); | ||
511 | writew(19999, baseAddr + TMS320_CLOCK); | ||
512 | } | ||
513 | writew(1, baseAddr + Disable_IRQ); | ||
514 | writew(0, baseAddr + Magic_no); | ||
515 | for (i = 0; i < 500; i++) { | ||
516 | if (readw(baseAddr + Magic_no) == Magic_code) | ||
517 | break; | ||
518 | msleep(10); | ||
519 | } | ||
520 | if (readw(baseAddr + Magic_no) != Magic_code) | ||
521 | return -EIO; | ||
522 | |||
523 | j = readw(baseAddr + Module_cnt); | ||
524 | if (j <= 0) | ||
525 | return -EIO; | ||
526 | brd->numPorts = j * 8; | ||
527 | writew(j, baseAddr + Module_no); | ||
528 | writew(0, baseAddr + Magic_no); | ||
529 | for (i = 0; i < 600; i++) { | ||
530 | if (readw(baseAddr + Magic_no) == Magic_code) | ||
531 | break; | ||
532 | msleep(10); | ||
533 | } | ||
534 | if (readw(baseAddr + Magic_no) != Magic_code) | ||
535 | return -EIO; | ||
536 | moxaCard = 1; | ||
537 | brd->intNdx = baseAddr + IRQindex; | ||
538 | brd->intPend = baseAddr + IRQpending; | ||
539 | brd->intTable = baseAddr + IRQtable; | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr, | ||
545 | size_t len) | ||
546 | { | ||
547 | void __iomem *ofsAddr, *baseAddr = brd->basemem; | ||
548 | struct moxa_port *port; | ||
549 | int retval, i; | ||
550 | |||
551 | if (len % 2) { | ||
552 | printk(KERN_ERR "moxa: C2XX bios length is not even\n"); | ||
553 | return -EINVAL; | ||
554 | } | ||
555 | |||
556 | switch (brd->boardType) { | ||
557 | case MOXA_BOARD_C218_ISA: | ||
558 | case MOXA_BOARD_C218_PCI: | ||
559 | case MOXA_BOARD_CP204J: | ||
560 | retval = moxa_load_c218(brd, ptr, len); | ||
561 | if (retval) | ||
562 | return retval; | ||
563 | port = brd->ports; | ||
564 | for (i = 0; i < brd->numPorts; i++, port++) { | ||
565 | port->chkPort = 1; | ||
566 | port->curBaud = 9600L; | ||
567 | port->DCDState = 0; | ||
568 | port->tableAddr = baseAddr + Extern_table + | ||
569 | Extern_size * i; | ||
570 | ofsAddr = port->tableAddr; | ||
571 | writew(C218rx_mask, ofsAddr + RX_mask); | ||
572 | writew(C218tx_mask, ofsAddr + TX_mask); | ||
573 | writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb); | ||
574 | writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb); | ||
575 | |||
576 | writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb); | ||
577 | writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb); | ||
578 | |||
579 | } | ||
580 | break; | ||
581 | default: | ||
582 | retval = moxa_load_c320(brd, ptr, len); /* fills in numPorts */ | ||
583 | if (retval) | ||
584 | return retval; | ||
585 | port = brd->ports; | ||
586 | for (i = 0; i < brd->numPorts; i++, port++) { | ||
587 | port->chkPort = 1; | ||
588 | port->curBaud = 9600L; | ||
589 | port->DCDState = 0; | ||
590 | port->tableAddr = baseAddr + Extern_table + | ||
591 | Extern_size * i; | ||
592 | ofsAddr = port->tableAddr; | ||
593 | switch (brd->numPorts) { | ||
594 | case 8: | ||
595 | writew(C320p8rx_mask, ofsAddr + RX_mask); | ||
596 | writew(C320p8tx_mask, ofsAddr + TX_mask); | ||
597 | writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb); | ||
598 | writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb); | ||
599 | writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb); | ||
600 | writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb); | ||
601 | |||
602 | break; | ||
603 | case 16: | ||
604 | writew(C320p16rx_mask, ofsAddr + RX_mask); | ||
605 | writew(C320p16tx_mask, ofsAddr + TX_mask); | ||
606 | writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb); | ||
607 | writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb); | ||
608 | writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb); | ||
609 | writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb); | ||
610 | break; | ||
611 | |||
612 | case 24: | ||
613 | writew(C320p24rx_mask, ofsAddr + RX_mask); | ||
614 | writew(C320p24tx_mask, ofsAddr + TX_mask); | ||
615 | writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb); | ||
616 | writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb); | ||
617 | writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb); | ||
618 | writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb); | ||
619 | break; | ||
620 | case 32: | ||
621 | writew(C320p32rx_mask, ofsAddr + RX_mask); | ||
622 | writew(C320p32tx_mask, ofsAddr + TX_mask); | ||
623 | writew(C320p32tx_ofs, ofsAddr + Ofs_txb); | ||
624 | writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb); | ||
625 | writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb); | ||
626 | writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb); | ||
627 | writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb); | ||
628 | break; | ||
629 | } | ||
630 | } | ||
631 | break; | ||
632 | } | ||
633 | brd->loadstat = 1; | ||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | static int moxa_load_fw(struct moxa_board_conf *brd, const struct firmware *fw) | ||
638 | { | ||
639 | void *ptr = fw->data; | ||
640 | char rsn[64]; | ||
641 | u16 lens[5]; | ||
642 | size_t len; | ||
643 | unsigned int a, lenp, lencnt; | ||
644 | int ret = -EINVAL; | ||
645 | struct { | ||
646 | __le32 magic; /* 0x34303430 */ | ||
647 | u8 reserved1[2]; | ||
648 | u8 type; /* UNIX = 3 */ | ||
649 | u8 model; /* C218T=1, C320T=2, CP204=3 */ | ||
650 | u8 reserved2[8]; | ||
651 | __le16 len[5]; | ||
652 | } *hdr = ptr; | ||
653 | |||
654 | BUILD_BUG_ON(ARRAY_SIZE(hdr->len) != ARRAY_SIZE(lens)); | ||
655 | |||
656 | if (fw->size < MOXA_FW_HDRLEN) { | ||
657 | strcpy(rsn, "too short (even header won't fit)"); | ||
658 | goto err; | ||
659 | } | ||
660 | if (hdr->magic != cpu_to_le32(0x30343034)) { | ||
661 | sprintf(rsn, "bad magic: %.8x", le32_to_cpu(hdr->magic)); | ||
662 | goto err; | ||
663 | } | ||
664 | if (hdr->type != 3) { | ||
665 | sprintf(rsn, "not for linux, type is %u", hdr->type); | ||
666 | goto err; | ||
667 | } | ||
668 | if (moxa_check_fw_model(brd, hdr->model)) { | ||
669 | sprintf(rsn, "not for this card, model is %u", hdr->model); | ||
670 | goto err; | ||
671 | } | ||
672 | |||
673 | len = MOXA_FW_HDRLEN; | ||
674 | lencnt = hdr->model == 2 ? 5 : 3; | ||
675 | for (a = 0; a < ARRAY_SIZE(lens); a++) { | ||
676 | lens[a] = le16_to_cpu(hdr->len[a]); | ||
677 | if (lens[a] && len + lens[a] <= fw->size && | ||
678 | moxa_check_fw(&fw->data[len])) | ||
679 | printk(KERN_WARNING "moxa firmware: unexpected input " | ||
680 | "at offset %u, but going on\n", (u32)len); | ||
681 | if (!lens[a] && a < lencnt) { | ||
682 | sprintf(rsn, "too few entries in fw file"); | ||
683 | goto err; | ||
684 | } | ||
685 | len += lens[a]; | ||
686 | } | ||
687 | |||
688 | if (len != fw->size) { | ||
689 | sprintf(rsn, "bad length: %u (should be %u)", (u32)fw->size, | ||
690 | (u32)len); | ||
691 | goto err; | ||
692 | } | ||
693 | |||
694 | ptr += MOXA_FW_HDRLEN; | ||
695 | lenp = 0; /* bios */ | ||
696 | |||
697 | strcpy(rsn, "read above"); | ||
698 | |||
699 | ret = moxa_load_bios(brd, ptr, lens[lenp]); | ||
700 | if (ret) | ||
701 | goto err; | ||
702 | |||
703 | /* we skip the tty section (lens[1]), since we don't need it */ | ||
704 | ptr += lens[lenp] + lens[lenp + 1]; | ||
705 | lenp += 2; /* comm */ | ||
706 | |||
707 | if (hdr->model == 2) { | ||
708 | ret = moxa_load_320b(brd, ptr, lens[lenp]); | ||
709 | if (ret) | ||
710 | goto err; | ||
711 | /* skip another tty */ | ||
712 | ptr += lens[lenp] + lens[lenp + 1]; | ||
713 | lenp += 2; | ||
714 | } | ||
715 | |||
716 | ret = moxa_load_code(brd, ptr, lens[lenp]); | ||
717 | if (ret) | ||
718 | goto err; | ||
719 | |||
720 | return 0; | ||
721 | err: | ||
722 | printk(KERN_ERR "firmware failed to load, reason: %s\n", rsn); | ||
723 | return ret; | ||
724 | } | ||
725 | |||
726 | static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev) | ||
727 | { | ||
728 | const struct firmware *fw; | ||
729 | const char *file; | ||
730 | int ret; | ||
731 | |||
732 | switch (brd->boardType) { | ||
733 | case MOXA_BOARD_C218_ISA: | ||
734 | case MOXA_BOARD_C218_PCI: | ||
735 | file = "c218tunx.cod"; | ||
736 | break; | ||
737 | case MOXA_BOARD_CP204J: | ||
738 | file = "cp204unx.cod"; | ||
739 | break; | ||
740 | default: | ||
741 | file = "c320tunx.cod"; | ||
742 | break; | ||
743 | } | ||
744 | |||
745 | ret = request_firmware(&fw, file, dev); | ||
746 | if (ret) { | ||
747 | printk(KERN_ERR "request_firmware failed\n"); | ||
748 | goto end; | ||
749 | } | ||
750 | |||
751 | ret = moxa_load_fw(brd, fw); | ||
752 | |||
753 | release_firmware(fw); | ||
754 | end: | ||
755 | return ret; | ||
756 | } | ||
757 | |||
266 | #ifdef CONFIG_PCI | 758 | #ifdef CONFIG_PCI |
267 | static int __devinit moxa_pci_probe(struct pci_dev *pdev, | 759 | static int __devinit moxa_pci_probe(struct pci_dev *pdev, |
268 | const struct pci_device_id *ent) | 760 | const struct pci_device_id *ent) |
@@ -290,6 +782,7 @@ static int __devinit moxa_pci_probe(struct pci_dev *pdev, | |||
290 | } | 782 | } |
291 | 783 | ||
292 | board = &moxa_boards[i]; | 784 | board = &moxa_boards[i]; |
785 | board->ports = &moxa_ports[i * MAX_PORTS_PER_BOARD]; | ||
293 | 786 | ||
294 | retval = pci_request_region(pdev, 2, "moxa-base"); | 787 | retval = pci_request_region(pdev, 2, "moxa-base"); |
295 | if (retval) { | 788 | if (retval) { |
@@ -319,9 +812,16 @@ static int __devinit moxa_pci_probe(struct pci_dev *pdev, | |||
319 | } | 812 | } |
320 | board->busType = MOXA_BUS_TYPE_PCI; | 813 | board->busType = MOXA_BUS_TYPE_PCI; |
321 | 814 | ||
815 | retval = moxa_init_board(board, &pdev->dev); | ||
816 | if (retval) | ||
817 | goto err_base; | ||
818 | |||
322 | pci_set_drvdata(pdev, board); | 819 | pci_set_drvdata(pdev, board); |
323 | 820 | ||
324 | return (0); | 821 | return (0); |
822 | err_base: | ||
823 | iounmap(board->basemem); | ||
824 | board->basemem = NULL; | ||
325 | err_reg: | 825 | err_reg: |
326 | pci_release_region(pdev, 2); | 826 | pci_release_region(pdev, 2); |
327 | err: | 827 | err: |
@@ -406,6 +906,7 @@ static int __init moxa_init(void) | |||
406 | isabrds + 1, moxa_brdname[type[i] - 1], | 906 | isabrds + 1, moxa_brdname[type[i] - 1], |
407 | baseaddr[i]); | 907 | baseaddr[i]); |
408 | brd->boardType = type[i]; | 908 | brd->boardType = type[i]; |
909 | brd->ports = &moxa_ports[isabrds * MAX_PORTS_PER_BOARD]; | ||
409 | brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 : | 910 | brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 : |
410 | numports[i]; | 911 | numports[i]; |
411 | brd->busType = MOXA_BUS_TYPE_ISA; | 912 | brd->busType = MOXA_BUS_TYPE_ISA; |
@@ -415,6 +916,11 @@ static int __init moxa_init(void) | |||
415 | baseaddr[i]); | 916 | baseaddr[i]); |
416 | continue; | 917 | continue; |
417 | } | 918 | } |
919 | if (moxa_init_board(brd, NULL)) { | ||
920 | iounmap(brd->basemem); | ||
921 | brd->basemem = NULL; | ||
922 | continue; | ||
923 | } | ||
418 | 924 | ||
419 | brd++; | 925 | brd++; |
420 | isabrds++; | 926 | isabrds++; |
@@ -1074,297 +1580,6 @@ static void moxa_receive_data(struct moxa_port *ch) | |||
1074 | tty_schedule_flip(tp); | 1580 | tty_schedule_flip(tp); |
1075 | } | 1581 | } |
1076 | 1582 | ||
1077 | #define Magic_code 0x404 | ||
1078 | |||
1079 | /* | ||
1080 | * System Configuration | ||
1081 | */ | ||
1082 | /* | ||
1083 | * for C218 BIOS initialization | ||
1084 | */ | ||
1085 | #define C218_ConfBase 0x800 | ||
1086 | #define C218_status (C218_ConfBase + 0) /* BIOS running status */ | ||
1087 | #define C218_diag (C218_ConfBase + 2) /* diagnostic status */ | ||
1088 | #define C218_key (C218_ConfBase + 4) /* WORD (0x218 for C218) */ | ||
1089 | #define C218DLoad_len (C218_ConfBase + 6) /* WORD */ | ||
1090 | #define C218check_sum (C218_ConfBase + 8) /* BYTE */ | ||
1091 | #define C218chksum_ok (C218_ConfBase + 0x0a) /* BYTE (1:ok) */ | ||
1092 | #define C218_TestRx (C218_ConfBase + 0x10) /* 8 bytes for 8 ports */ | ||
1093 | #define C218_TestTx (C218_ConfBase + 0x18) /* 8 bytes for 8 ports */ | ||
1094 | #define C218_RXerr (C218_ConfBase + 0x20) /* 8 bytes for 8 ports */ | ||
1095 | #define C218_ErrFlag (C218_ConfBase + 0x28) /* 8 bytes for 8 ports */ | ||
1096 | |||
1097 | #define C218_LoadBuf 0x0F00 | ||
1098 | #define C218_KeyCode 0x218 | ||
1099 | #define CP204J_KeyCode 0x204 | ||
1100 | |||
1101 | /* | ||
1102 | * for C320 BIOS initialization | ||
1103 | */ | ||
1104 | #define C320_ConfBase 0x800 | ||
1105 | #define C320_LoadBuf 0x0f00 | ||
1106 | #define STS_init 0x05 /* for C320_status */ | ||
1107 | |||
1108 | #define C320_status C320_ConfBase + 0 /* BIOS running status */ | ||
1109 | #define C320_diag C320_ConfBase + 2 /* diagnostic status */ | ||
1110 | #define C320_key C320_ConfBase + 4 /* WORD (0320H for C320) */ | ||
1111 | #define C320DLoad_len C320_ConfBase + 6 /* WORD */ | ||
1112 | #define C320check_sum C320_ConfBase + 8 /* WORD */ | ||
1113 | #define C320chksum_ok C320_ConfBase + 0x0a /* WORD (1:ok) */ | ||
1114 | #define C320bapi_len C320_ConfBase + 0x0c /* WORD */ | ||
1115 | #define C320UART_no C320_ConfBase + 0x0e /* WORD */ | ||
1116 | |||
1117 | #define C320_KeyCode 0x320 | ||
1118 | |||
1119 | #define FixPage_addr 0x0000 /* starting addr of static page */ | ||
1120 | #define DynPage_addr 0x2000 /* starting addr of dynamic page */ | ||
1121 | #define C218_start 0x3000 /* starting addr of C218 BIOS prg */ | ||
1122 | #define Control_reg 0x1ff0 /* select page and reset control */ | ||
1123 | #define HW_reset 0x80 | ||
1124 | |||
1125 | /* | ||
1126 | * Function Codes | ||
1127 | */ | ||
1128 | #define FC_CardReset 0x80 | ||
1129 | #define FC_ChannelReset 1 /* C320 firmware not supported */ | ||
1130 | #define FC_EnableCH 2 | ||
1131 | #define FC_DisableCH 3 | ||
1132 | #define FC_SetParam 4 | ||
1133 | #define FC_SetMode 5 | ||
1134 | #define FC_SetRate 6 | ||
1135 | #define FC_LineControl 7 | ||
1136 | #define FC_LineStatus 8 | ||
1137 | #define FC_XmitControl 9 | ||
1138 | #define FC_FlushQueue 10 | ||
1139 | #define FC_SendBreak 11 | ||
1140 | #define FC_StopBreak 12 | ||
1141 | #define FC_LoopbackON 13 | ||
1142 | #define FC_LoopbackOFF 14 | ||
1143 | #define FC_ClrIrqTable 15 | ||
1144 | #define FC_SendXon 16 | ||
1145 | #define FC_SetTermIrq 17 /* C320 firmware not supported */ | ||
1146 | #define FC_SetCntIrq 18 /* C320 firmware not supported */ | ||
1147 | #define FC_SetBreakIrq 19 | ||
1148 | #define FC_SetLineIrq 20 | ||
1149 | #define FC_SetFlowCtl 21 | ||
1150 | #define FC_GenIrq 22 | ||
1151 | #define FC_InCD180 23 | ||
1152 | #define FC_OutCD180 24 | ||
1153 | #define FC_InUARTreg 23 | ||
1154 | #define FC_OutUARTreg 24 | ||
1155 | #define FC_SetXonXoff 25 | ||
1156 | #define FC_OutCD180CCR 26 | ||
1157 | #define FC_ExtIQueue 27 | ||
1158 | #define FC_ExtOQueue 28 | ||
1159 | #define FC_ClrLineIrq 29 | ||
1160 | #define FC_HWFlowCtl 30 | ||
1161 | #define FC_GetClockRate 35 | ||
1162 | #define FC_SetBaud 36 | ||
1163 | #define FC_SetDataMode 41 | ||
1164 | #define FC_GetCCSR 43 | ||
1165 | #define FC_GetDataError 45 | ||
1166 | #define FC_RxControl 50 | ||
1167 | #define FC_ImmSend 51 | ||
1168 | #define FC_SetXonState 52 | ||
1169 | #define FC_SetXoffState 53 | ||
1170 | #define FC_SetRxFIFOTrig 54 | ||
1171 | #define FC_SetTxFIFOCnt 55 | ||
1172 | #define FC_UnixRate 56 | ||
1173 | #define FC_UnixResetTimer 57 | ||
1174 | |||
1175 | #define RxFIFOTrig1 0 | ||
1176 | #define RxFIFOTrig4 1 | ||
1177 | #define RxFIFOTrig8 2 | ||
1178 | #define RxFIFOTrig14 3 | ||
1179 | |||
1180 | /* | ||
1181 | * Dual-Ported RAM | ||
1182 | */ | ||
1183 | #define DRAM_global 0 | ||
1184 | #define INT_data (DRAM_global + 0) | ||
1185 | #define Config_base (DRAM_global + 0x108) | ||
1186 | |||
1187 | #define IRQindex (INT_data + 0) | ||
1188 | #define IRQpending (INT_data + 4) | ||
1189 | #define IRQtable (INT_data + 8) | ||
1190 | |||
1191 | /* | ||
1192 | * Interrupt Status | ||
1193 | */ | ||
1194 | #define IntrRx 0x01 /* receiver data O.K. */ | ||
1195 | #define IntrTx 0x02 /* transmit buffer empty */ | ||
1196 | #define IntrFunc 0x04 /* function complete */ | ||
1197 | #define IntrBreak 0x08 /* received break */ | ||
1198 | #define IntrLine 0x10 /* line status change | ||
1199 | for transmitter */ | ||
1200 | #define IntrIntr 0x20 /* received INTR code */ | ||
1201 | #define IntrQuit 0x40 /* received QUIT code */ | ||
1202 | #define IntrEOF 0x80 /* received EOF code */ | ||
1203 | |||
1204 | #define IntrRxTrigger 0x100 /* rx data count reach tigger value */ | ||
1205 | #define IntrTxTrigger 0x200 /* tx data count below trigger value */ | ||
1206 | |||
1207 | #define Magic_no (Config_base + 0) | ||
1208 | #define Card_model_no (Config_base + 2) | ||
1209 | #define Total_ports (Config_base + 4) | ||
1210 | #define Module_cnt (Config_base + 8) | ||
1211 | #define Module_no (Config_base + 10) | ||
1212 | #define Timer_10ms (Config_base + 14) | ||
1213 | #define Disable_IRQ (Config_base + 20) | ||
1214 | #define TMS320_PORT1 (Config_base + 22) | ||
1215 | #define TMS320_PORT2 (Config_base + 24) | ||
1216 | #define TMS320_CLOCK (Config_base + 26) | ||
1217 | |||
1218 | /* | ||
1219 | * DATA BUFFER in DRAM | ||
1220 | */ | ||
1221 | #define Extern_table 0x400 /* Base address of the external table | ||
1222 | (24 words * 64) total 3K bytes | ||
1223 | (24 words * 128) total 6K bytes */ | ||
1224 | #define Extern_size 0x60 /* 96 bytes */ | ||
1225 | #define RXrptr 0x00 /* read pointer for RX buffer */ | ||
1226 | #define RXwptr 0x02 /* write pointer for RX buffer */ | ||
1227 | #define TXrptr 0x04 /* read pointer for TX buffer */ | ||
1228 | #define TXwptr 0x06 /* write pointer for TX buffer */ | ||
1229 | #define HostStat 0x08 /* IRQ flag and general flag */ | ||
1230 | #define FlagStat 0x0A | ||
1231 | #define FlowControl 0x0C /* B7 B6 B5 B4 B3 B2 B1 B0 */ | ||
1232 | /* x x x x | | | | */ | ||
1233 | /* | | | + CTS flow */ | ||
1234 | /* | | +--- RTS flow */ | ||
1235 | /* | +------ TX Xon/Xoff */ | ||
1236 | /* +--------- RX Xon/Xoff */ | ||
1237 | #define Break_cnt 0x0E /* received break count */ | ||
1238 | #define CD180TXirq 0x10 /* if non-0: enable TX irq */ | ||
1239 | #define RX_mask 0x12 | ||
1240 | #define TX_mask 0x14 | ||
1241 | #define Ofs_rxb 0x16 | ||
1242 | #define Ofs_txb 0x18 | ||
1243 | #define Page_rxb 0x1A | ||
1244 | #define Page_txb 0x1C | ||
1245 | #define EndPage_rxb 0x1E | ||
1246 | #define EndPage_txb 0x20 | ||
1247 | #define Data_error 0x22 | ||
1248 | #define RxTrigger 0x28 | ||
1249 | #define TxTrigger 0x2a | ||
1250 | |||
1251 | #define rRXwptr 0x34 | ||
1252 | #define Low_water 0x36 | ||
1253 | |||
1254 | #define FuncCode 0x40 | ||
1255 | #define FuncArg 0x42 | ||
1256 | #define FuncArg1 0x44 | ||
1257 | |||
1258 | #define C218rx_size 0x2000 /* 8K bytes */ | ||
1259 | #define C218tx_size 0x8000 /* 32K bytes */ | ||
1260 | |||
1261 | #define C218rx_mask (C218rx_size - 1) | ||
1262 | #define C218tx_mask (C218tx_size - 1) | ||
1263 | |||
1264 | #define C320p8rx_size 0x2000 | ||
1265 | #define C320p8tx_size 0x8000 | ||
1266 | #define C320p8rx_mask (C320p8rx_size - 1) | ||
1267 | #define C320p8tx_mask (C320p8tx_size - 1) | ||
1268 | |||
1269 | #define C320p16rx_size 0x2000 | ||
1270 | #define C320p16tx_size 0x4000 | ||
1271 | #define C320p16rx_mask (C320p16rx_size - 1) | ||
1272 | #define C320p16tx_mask (C320p16tx_size - 1) | ||
1273 | |||
1274 | #define C320p24rx_size 0x2000 | ||
1275 | #define C320p24tx_size 0x2000 | ||
1276 | #define C320p24rx_mask (C320p24rx_size - 1) | ||
1277 | #define C320p24tx_mask (C320p24tx_size - 1) | ||
1278 | |||
1279 | #define C320p32rx_size 0x1000 | ||
1280 | #define C320p32tx_size 0x1000 | ||
1281 | #define C320p32rx_mask (C320p32rx_size - 1) | ||
1282 | #define C320p32tx_mask (C320p32tx_size - 1) | ||
1283 | |||
1284 | #define Page_size 0x2000 | ||
1285 | #define Page_mask (Page_size - 1) | ||
1286 | #define C218rx_spage 3 | ||
1287 | #define C218tx_spage 4 | ||
1288 | #define C218rx_pageno 1 | ||
1289 | #define C218tx_pageno 4 | ||
1290 | #define C218buf_pageno 5 | ||
1291 | |||
1292 | #define C320p8rx_spage 3 | ||
1293 | #define C320p8tx_spage 4 | ||
1294 | #define C320p8rx_pgno 1 | ||
1295 | #define C320p8tx_pgno 4 | ||
1296 | #define C320p8buf_pgno 5 | ||
1297 | |||
1298 | #define C320p16rx_spage 3 | ||
1299 | #define C320p16tx_spage 4 | ||
1300 | #define C320p16rx_pgno 1 | ||
1301 | #define C320p16tx_pgno 2 | ||
1302 | #define C320p16buf_pgno 3 | ||
1303 | |||
1304 | #define C320p24rx_spage 3 | ||
1305 | #define C320p24tx_spage 4 | ||
1306 | #define C320p24rx_pgno 1 | ||
1307 | #define C320p24tx_pgno 1 | ||
1308 | #define C320p24buf_pgno 2 | ||
1309 | |||
1310 | #define C320p32rx_spage 3 | ||
1311 | #define C320p32tx_ofs C320p32rx_size | ||
1312 | #define C320p32tx_spage 3 | ||
1313 | #define C320p32buf_pgno 1 | ||
1314 | |||
1315 | /* | ||
1316 | * Host Status | ||
1317 | */ | ||
1318 | #define WakeupRx 0x01 | ||
1319 | #define WakeupTx 0x02 | ||
1320 | #define WakeupBreak 0x08 | ||
1321 | #define WakeupLine 0x10 | ||
1322 | #define WakeupIntr 0x20 | ||
1323 | #define WakeupQuit 0x40 | ||
1324 | #define WakeupEOF 0x80 /* used in VTIME control */ | ||
1325 | #define WakeupRxTrigger 0x100 | ||
1326 | #define WakeupTxTrigger 0x200 | ||
1327 | /* | ||
1328 | * Flag status | ||
1329 | */ | ||
1330 | #define Rx_over 0x01 | ||
1331 | #define Xoff_state 0x02 | ||
1332 | #define Tx_flowOff 0x04 | ||
1333 | #define Tx_enable 0x08 | ||
1334 | #define CTS_state 0x10 | ||
1335 | #define DSR_state 0x20 | ||
1336 | #define DCD_state 0x80 | ||
1337 | /* | ||
1338 | * FlowControl | ||
1339 | */ | ||
1340 | #define CTS_FlowCtl 1 | ||
1341 | #define RTS_FlowCtl 2 | ||
1342 | #define Tx_FlowCtl 4 | ||
1343 | #define Rx_FlowCtl 8 | ||
1344 | #define IXM_IXANY 0x10 | ||
1345 | |||
1346 | #define LowWater 128 | ||
1347 | |||
1348 | #define DTR_ON 1 | ||
1349 | #define RTS_ON 2 | ||
1350 | #define CTS_ON 1 | ||
1351 | #define DSR_ON 2 | ||
1352 | #define DCD_ON 8 | ||
1353 | |||
1354 | /* mode definition */ | ||
1355 | #define MX_CS8 0x03 | ||
1356 | #define MX_CS7 0x02 | ||
1357 | #define MX_CS6 0x01 | ||
1358 | #define MX_CS5 0x00 | ||
1359 | |||
1360 | #define MX_STOP1 0x00 | ||
1361 | #define MX_STOP15 0x04 | ||
1362 | #define MX_STOP2 0x08 | ||
1363 | |||
1364 | #define MX_PARNONE 0x00 | ||
1365 | #define MX_PAREVEN 0x40 | ||
1366 | #define MX_PARODD 0xC0 | ||
1367 | |||
1368 | /* | 1583 | /* |
1369 | * Query | 1584 | * Query |
1370 | */ | 1585 | */ |
@@ -1378,55 +1593,22 @@ struct mon_str { | |||
1378 | #define DCD_changed 0x01 | 1593 | #define DCD_changed 0x01 |
1379 | #define DCD_oldstate 0x80 | 1594 | #define DCD_oldstate 0x80 |
1380 | 1595 | ||
1381 | static unsigned char moxaBuff[10240]; | ||
1382 | static int moxaLowWaterChk; | 1596 | static int moxaLowWaterChk; |
1383 | static int moxaCard; | ||
1384 | static struct mon_str moxaLog; | 1597 | static struct mon_str moxaLog; |
1385 | static int moxaFuncTout = HZ / 2; | 1598 | static int moxaFuncTout = HZ / 2; |
1386 | 1599 | ||
1387 | static void moxafunc(void __iomem *, int, ushort); | 1600 | static void moxafunc(void __iomem *, int, ushort); |
1388 | static void moxa_wait_finish(void __iomem *); | 1601 | static void moxa_wait_finish(void __iomem *); |
1389 | static void moxa_low_water_check(void __iomem *); | 1602 | static void moxa_low_water_check(void __iomem *); |
1390 | static int moxaloadbios(int, unsigned char __user *, int); | ||
1391 | static int moxafindcard(int); | ||
1392 | static int moxaload320b(int, unsigned char __user *, int); | ||
1393 | static int moxaloadcode(int, unsigned char __user *, int); | ||
1394 | static int moxaloadc218(int, void __iomem *, int); | ||
1395 | static int moxaloadc320(int, void __iomem *, int, int *); | ||
1396 | 1603 | ||
1397 | /***************************************************************************** | 1604 | /***************************************************************************** |
1398 | * Driver level functions: * | 1605 | * Driver level functions: * |
1399 | * 1. MoxaDriverInit(void); * | ||
1400 | * 2. MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port); * | 1606 | * 2. MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port); * |
1401 | * 3. MoxaDriverPoll(void); * | 1607 | * 3. MoxaDriverPoll(void); * |
1402 | *****************************************************************************/ | 1608 | *****************************************************************************/ |
1403 | void MoxaDriverInit(void) | ||
1404 | { | ||
1405 | struct moxa_port *p; | ||
1406 | unsigned int i; | ||
1407 | |||
1408 | moxaFuncTout = HZ / 2; /* 500 mini-seconds */ | ||
1409 | moxaCard = 0; | ||
1410 | moxaLog.tick = 0; | ||
1411 | moxaLowWaterChk = 0; | ||
1412 | for (i = 0; i < MAX_PORTS; i++) { | ||
1413 | p = &moxa_ports[i]; | ||
1414 | p->chkPort = 0; | ||
1415 | p->lowChkFlag = 0; | ||
1416 | p->lineCtrl = 0; | ||
1417 | moxaLog.rxcnt[i] = 0; | ||
1418 | moxaLog.txcnt[i] = 0; | ||
1419 | } | ||
1420 | } | ||
1421 | |||
1422 | #define MOXA 0x400 | 1609 | #define MOXA 0x400 |
1423 | #define MOXA_GET_IQUEUE (MOXA + 1) /* get input buffered count */ | 1610 | #define MOXA_GET_IQUEUE (MOXA + 1) /* get input buffered count */ |
1424 | #define MOXA_GET_OQUEUE (MOXA + 2) /* get output buffered count */ | 1611 | #define MOXA_GET_OQUEUE (MOXA + 2) /* get output buffered count */ |
1425 | #define MOXA_INIT_DRIVER (MOXA + 6) /* moxaCard=0 */ | ||
1426 | #define MOXA_LOAD_BIOS (MOXA + 9) /* download BIOS */ | ||
1427 | #define MOXA_FIND_BOARD (MOXA + 10) /* Check if MOXA card exist? */ | ||
1428 | #define MOXA_LOAD_C320B (MOXA + 11) /* download 320B firmware */ | ||
1429 | #define MOXA_LOAD_CODE (MOXA + 12) /* download firmware */ | ||
1430 | #define MOXA_GETDATACOUNT (MOXA + 23) | 1612 | #define MOXA_GETDATACOUNT (MOXA + 23) |
1431 | #define MOXA_GET_IOQUEUE (MOXA + 27) | 1613 | #define MOXA_GET_IOQUEUE (MOXA + 27) |
1432 | #define MOXA_FLUSH_QUEUE (MOXA + 28) | 1614 | #define MOXA_FLUSH_QUEUE (MOXA + 28) |
@@ -1435,14 +1617,6 @@ void MoxaDriverInit(void) | |||
1435 | #define MOXA_GET_CUMAJOR (MOXA + 64) | 1617 | #define MOXA_GET_CUMAJOR (MOXA + 64) |
1436 | #define MOXA_GETMSTATUS (MOXA + 65) | 1618 | #define MOXA_GETMSTATUS (MOXA + 65) |
1437 | 1619 | ||
1438 | struct dl_str { | ||
1439 | char __user *buf; | ||
1440 | int len; | ||
1441 | int cardno; | ||
1442 | }; | ||
1443 | |||
1444 | static struct dl_str dltmp; | ||
1445 | |||
1446 | void MoxaPortFlushData(int port, int mode) | 1620 | void MoxaPortFlushData(int port, int mode) |
1447 | { | 1621 | { |
1448 | void __iomem *ofsAddr; | 1622 | void __iomem *ofsAddr; |
@@ -1464,23 +1638,12 @@ int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port) | |||
1464 | void __user *argp = (void __user *)arg; | 1638 | void __user *argp = (void __user *)arg; |
1465 | 1639 | ||
1466 | if (port == MAX_PORTS) { | 1640 | if (port == MAX_PORTS) { |
1467 | if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_INIT_DRIVER) && | 1641 | if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_GETDATACOUNT) && |
1468 | (cmd != MOXA_LOAD_BIOS) && (cmd != MOXA_FIND_BOARD) && (cmd != MOXA_LOAD_C320B) && | 1642 | (cmd != MOXA_GET_IOQUEUE) && (cmd != MOXA_GET_MAJOR) && |
1469 | (cmd != MOXA_LOAD_CODE) && (cmd != MOXA_GETDATACOUNT) && | ||
1470 | (cmd != MOXA_GET_IOQUEUE) && (cmd != MOXA_GET_MAJOR) && | ||
1471 | (cmd != MOXA_GET_CUMAJOR) && (cmd != MOXA_GETMSTATUS)) | 1643 | (cmd != MOXA_GET_CUMAJOR) && (cmd != MOXA_GETMSTATUS)) |
1472 | return (-EINVAL); | 1644 | return (-EINVAL); |
1473 | } | 1645 | } |
1474 | switch (cmd) { | 1646 | switch (cmd) { |
1475 | case MOXA_GET_CONF: | ||
1476 | if(copy_to_user(argp, &moxa_boards, MAX_BOARDS * | ||
1477 | sizeof(struct moxa_board_conf))) | ||
1478 | return -EFAULT; | ||
1479 | return (0); | ||
1480 | case MOXA_INIT_DRIVER: | ||
1481 | if ((int) arg == 0x404) | ||
1482 | MoxaDriverInit(); | ||
1483 | return (0); | ||
1484 | case MOXA_GETDATACOUNT: | 1647 | case MOXA_GETDATACOUNT: |
1485 | moxaLog.tick = jiffies; | 1648 | moxaLog.tick = jiffies; |
1486 | if(copy_to_user(argp, &moxaLog, sizeof(struct mon_str))) | 1649 | if(copy_to_user(argp, &moxaLog, sizeof(struct mon_str))) |
@@ -1547,40 +1710,10 @@ copy: | |||
1547 | return -EFAULT; | 1710 | return -EFAULT; |
1548 | } | 1711 | } |
1549 | return 0; | 1712 | return 0; |
1550 | } default: | ||
1551 | return (-ENOIOCTLCMD); | ||
1552 | case MOXA_LOAD_BIOS: | ||
1553 | case MOXA_FIND_BOARD: | ||
1554 | case MOXA_LOAD_C320B: | ||
1555 | case MOXA_LOAD_CODE: | ||
1556 | if (!capable(CAP_SYS_RAWIO)) | ||
1557 | return -EPERM; | ||
1558 | break; | ||
1559 | } | 1713 | } |
1560 | |||
1561 | if(copy_from_user(&dltmp, argp, sizeof(struct dl_str))) | ||
1562 | return -EFAULT; | ||
1563 | if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS || dltmp.len < 0) | ||
1564 | return -EINVAL; | ||
1565 | |||
1566 | switch(cmd) | ||
1567 | { | ||
1568 | case MOXA_LOAD_BIOS: | ||
1569 | i = moxaloadbios(dltmp.cardno, dltmp.buf, dltmp.len); | ||
1570 | return (i); | ||
1571 | case MOXA_FIND_BOARD: | ||
1572 | return moxafindcard(dltmp.cardno); | ||
1573 | case MOXA_LOAD_C320B: | ||
1574 | moxaload320b(dltmp.cardno, dltmp.buf, dltmp.len); | ||
1575 | default: /* to keep gcc happy */ | ||
1576 | return (0); | ||
1577 | case MOXA_LOAD_CODE: | ||
1578 | i = moxaloadcode(dltmp.cardno, dltmp.buf, dltmp.len); | ||
1579 | if (i == -1) | ||
1580 | return (-EFAULT); | ||
1581 | return (i); | ||
1582 | |||
1583 | } | 1714 | } |
1715 | |||
1716 | return -ENOIOCTLCMD; | ||
1584 | } | 1717 | } |
1585 | 1718 | ||
1586 | int MoxaDriverPoll(void) | 1719 | int MoxaDriverPoll(void) |
@@ -1935,7 +2068,6 @@ int MoxaPortsOfCard(int cardno) | |||
1935 | */ | 2068 | */ |
1936 | int MoxaPortIsValid(int port) | 2069 | int MoxaPortIsValid(int port) |
1937 | { | 2070 | { |
1938 | |||
1939 | if (moxaCard == 0) | 2071 | if (moxaCard == 0) |
1940 | return (0); | 2072 | return (0); |
1941 | if (moxa_ports[port].chkPort == 0) | 2073 | if (moxa_ports[port].chkPort == 0) |
@@ -2490,335 +2622,6 @@ static void moxa_low_water_check(void __iomem *ofsAddr) | |||
2490 | } | 2622 | } |
2491 | } | 2623 | } |
2492 | 2624 | ||
2493 | static int moxaloadbios(int cardno, unsigned char __user *tmp, int len) | ||
2494 | { | ||
2495 | void __iomem *baseAddr; | ||
2496 | int i; | ||
2497 | |||
2498 | if(len < 0 || len > sizeof(moxaBuff)) | ||
2499 | return -EINVAL; | ||
2500 | if(copy_from_user(moxaBuff, tmp, len)) | ||
2501 | return -EFAULT; | ||
2502 | baseAddr = moxa_boards[cardno].basemem; | ||
2503 | writeb(HW_reset, baseAddr + Control_reg); /* reset */ | ||
2504 | msleep(10); | ||
2505 | for (i = 0; i < 4096; i++) | ||
2506 | writeb(0, baseAddr + i); /* clear fix page */ | ||
2507 | for (i = 0; i < len; i++) | ||
2508 | writeb(moxaBuff[i], baseAddr + i); /* download BIOS */ | ||
2509 | writeb(0, baseAddr + Control_reg); /* restart */ | ||
2510 | return (0); | ||
2511 | } | ||
2512 | |||
2513 | static int moxafindcard(int cardno) | ||
2514 | { | ||
2515 | void __iomem *baseAddr; | ||
2516 | ushort tmp; | ||
2517 | |||
2518 | baseAddr = moxa_boards[cardno].basemem; | ||
2519 | switch (moxa_boards[cardno].boardType) { | ||
2520 | case MOXA_BOARD_C218_ISA: | ||
2521 | case MOXA_BOARD_C218_PCI: | ||
2522 | if ((tmp = readw(baseAddr + C218_key)) != C218_KeyCode) { | ||
2523 | return (-1); | ||
2524 | } | ||
2525 | break; | ||
2526 | case MOXA_BOARD_CP204J: | ||
2527 | if ((tmp = readw(baseAddr + C218_key)) != CP204J_KeyCode) { | ||
2528 | return (-1); | ||
2529 | } | ||
2530 | break; | ||
2531 | default: | ||
2532 | if ((tmp = readw(baseAddr + C320_key)) != C320_KeyCode) { | ||
2533 | return (-1); | ||
2534 | } | ||
2535 | if ((tmp = readw(baseAddr + C320_status)) != STS_init) { | ||
2536 | return (-2); | ||
2537 | } | ||
2538 | } | ||
2539 | return (0); | ||
2540 | } | ||
2541 | |||
2542 | static int moxaload320b(int cardno, unsigned char __user *tmp, int len) | ||
2543 | { | ||
2544 | void __iomem *baseAddr; | ||
2545 | int i; | ||
2546 | |||
2547 | if(len < 0 || len > sizeof(moxaBuff)) | ||
2548 | return -EINVAL; | ||
2549 | if(copy_from_user(moxaBuff, tmp, len)) | ||
2550 | return -EFAULT; | ||
2551 | baseAddr = moxa_boards[cardno].basemem; | ||
2552 | writew(len - 7168 - 2, baseAddr + C320bapi_len); | ||
2553 | writeb(1, baseAddr + Control_reg); /* Select Page 1 */ | ||
2554 | for (i = 0; i < 7168; i++) | ||
2555 | writeb(moxaBuff[i], baseAddr + DynPage_addr + i); | ||
2556 | writeb(2, baseAddr + Control_reg); /* Select Page 2 */ | ||
2557 | for (i = 0; i < (len - 7168); i++) | ||
2558 | writeb(moxaBuff[i + 7168], baseAddr + DynPage_addr + i); | ||
2559 | return (0); | ||
2560 | } | ||
2561 | |||
2562 | static int moxaloadcode(int cardno, unsigned char __user *tmp, int len) | ||
2563 | { | ||
2564 | void __iomem *baseAddr, *ofsAddr; | ||
2565 | int retval, port, i; | ||
2566 | |||
2567 | if(len < 0 || len > sizeof(moxaBuff)) | ||
2568 | return -EINVAL; | ||
2569 | if(copy_from_user(moxaBuff, tmp, len)) | ||
2570 | return -EFAULT; | ||
2571 | baseAddr = moxa_boards[cardno].basemem; | ||
2572 | switch (moxa_boards[cardno].boardType) { | ||
2573 | case MOXA_BOARD_C218_ISA: | ||
2574 | case MOXA_BOARD_C218_PCI: | ||
2575 | case MOXA_BOARD_CP204J: | ||
2576 | retval = moxaloadc218(cardno, baseAddr, len); | ||
2577 | if (retval) | ||
2578 | return (retval); | ||
2579 | port = cardno * MAX_PORTS_PER_BOARD; | ||
2580 | for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) { | ||
2581 | struct moxa_port *p = &moxa_ports[port]; | ||
2582 | |||
2583 | p->chkPort = 1; | ||
2584 | p->curBaud = 9600L; | ||
2585 | p->DCDState = 0; | ||
2586 | p->tableAddr = baseAddr + Extern_table + Extern_size * i; | ||
2587 | ofsAddr = p->tableAddr; | ||
2588 | writew(C218rx_mask, ofsAddr + RX_mask); | ||
2589 | writew(C218tx_mask, ofsAddr + TX_mask); | ||
2590 | writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb); | ||
2591 | writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb); | ||
2592 | |||
2593 | writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb); | ||
2594 | writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb); | ||
2595 | |||
2596 | } | ||
2597 | break; | ||
2598 | default: | ||
2599 | retval = moxaloadc320(cardno, baseAddr, len, | ||
2600 | &moxa_boards[cardno].numPorts); | ||
2601 | if (retval) | ||
2602 | return (retval); | ||
2603 | port = cardno * MAX_PORTS_PER_BOARD; | ||
2604 | for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) { | ||
2605 | struct moxa_port *p = &moxa_ports[port]; | ||
2606 | |||
2607 | p->chkPort = 1; | ||
2608 | p->curBaud = 9600L; | ||
2609 | p->DCDState = 0; | ||
2610 | p->tableAddr = baseAddr + Extern_table + Extern_size * i; | ||
2611 | ofsAddr = p->tableAddr; | ||
2612 | if (moxa_boards[cardno].numPorts == 8) { | ||
2613 | writew(C320p8rx_mask, ofsAddr + RX_mask); | ||
2614 | writew(C320p8tx_mask, ofsAddr + TX_mask); | ||
2615 | writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb); | ||
2616 | writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb); | ||
2617 | writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb); | ||
2618 | writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb); | ||
2619 | |||
2620 | } else if (moxa_boards[cardno].numPorts == 16) { | ||
2621 | writew(C320p16rx_mask, ofsAddr + RX_mask); | ||
2622 | writew(C320p16tx_mask, ofsAddr + TX_mask); | ||
2623 | writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb); | ||
2624 | writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb); | ||
2625 | writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb); | ||
2626 | writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb); | ||
2627 | |||
2628 | } else if (moxa_boards[cardno].numPorts == 24) { | ||
2629 | writew(C320p24rx_mask, ofsAddr + RX_mask); | ||
2630 | writew(C320p24tx_mask, ofsAddr + TX_mask); | ||
2631 | writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb); | ||
2632 | writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb); | ||
2633 | writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb); | ||
2634 | writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb); | ||
2635 | } else if (moxa_boards[cardno].numPorts == 32) { | ||
2636 | writew(C320p32rx_mask, ofsAddr + RX_mask); | ||
2637 | writew(C320p32tx_mask, ofsAddr + TX_mask); | ||
2638 | writew(C320p32tx_ofs, ofsAddr + Ofs_txb); | ||
2639 | writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb); | ||
2640 | writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb); | ||
2641 | writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb); | ||
2642 | writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb); | ||
2643 | } | ||
2644 | } | ||
2645 | break; | ||
2646 | } | ||
2647 | moxa_boards[cardno].loadstat = 1; | ||
2648 | return (0); | ||
2649 | } | ||
2650 | |||
2651 | static int moxaloadc218(int cardno, void __iomem *baseAddr, int len) | ||
2652 | { | ||
2653 | char retry; | ||
2654 | int i, j, len1, len2; | ||
2655 | ushort usum, *ptr, keycode; | ||
2656 | |||
2657 | if (moxa_boards[cardno].boardType == MOXA_BOARD_CP204J) | ||
2658 | keycode = CP204J_KeyCode; | ||
2659 | else | ||
2660 | keycode = C218_KeyCode; | ||
2661 | usum = 0; | ||
2662 | len1 = len >> 1; | ||
2663 | ptr = (ushort *) moxaBuff; | ||
2664 | for (i = 0; i < len1; i++) | ||
2665 | usum += le16_to_cpu(*(ptr + i)); | ||
2666 | retry = 0; | ||
2667 | do { | ||
2668 | len1 = len >> 1; | ||
2669 | j = 0; | ||
2670 | while (len1) { | ||
2671 | len2 = (len1 > 2048) ? 2048 : len1; | ||
2672 | len1 -= len2; | ||
2673 | for (i = 0; i < len2 << 1; i++) | ||
2674 | writeb(moxaBuff[i + j], baseAddr + C218_LoadBuf + i); | ||
2675 | j += i; | ||
2676 | |||
2677 | writew(len2, baseAddr + C218DLoad_len); | ||
2678 | writew(0, baseAddr + C218_key); | ||
2679 | for (i = 0; i < 100; i++) { | ||
2680 | if (readw(baseAddr + C218_key) == keycode) | ||
2681 | break; | ||
2682 | msleep(10); | ||
2683 | } | ||
2684 | if (readw(baseAddr + C218_key) != keycode) { | ||
2685 | return (-1); | ||
2686 | } | ||
2687 | } | ||
2688 | writew(0, baseAddr + C218DLoad_len); | ||
2689 | writew(usum, baseAddr + C218check_sum); | ||
2690 | writew(0, baseAddr + C218_key); | ||
2691 | for (i = 0; i < 100; i++) { | ||
2692 | if (readw(baseAddr + C218_key) == keycode) | ||
2693 | break; | ||
2694 | msleep(10); | ||
2695 | } | ||
2696 | retry++; | ||
2697 | } while ((readb(baseAddr + C218chksum_ok) != 1) && (retry < 3)); | ||
2698 | if (readb(baseAddr + C218chksum_ok) != 1) { | ||
2699 | return (-1); | ||
2700 | } | ||
2701 | writew(0, baseAddr + C218_key); | ||
2702 | for (i = 0; i < 100; i++) { | ||
2703 | if (readw(baseAddr + Magic_no) == Magic_code) | ||
2704 | break; | ||
2705 | msleep(10); | ||
2706 | } | ||
2707 | if (readw(baseAddr + Magic_no) != Magic_code) { | ||
2708 | return (-1); | ||
2709 | } | ||
2710 | writew(1, baseAddr + Disable_IRQ); | ||
2711 | writew(0, baseAddr + Magic_no); | ||
2712 | for (i = 0; i < 100; i++) { | ||
2713 | if (readw(baseAddr + Magic_no) == Magic_code) | ||
2714 | break; | ||
2715 | msleep(10); | ||
2716 | } | ||
2717 | if (readw(baseAddr + Magic_no) != Magic_code) { | ||
2718 | return (-1); | ||
2719 | } | ||
2720 | moxaCard = 1; | ||
2721 | moxa_boards[cardno].intNdx = baseAddr + IRQindex; | ||
2722 | moxa_boards[cardno].intPend = baseAddr + IRQpending; | ||
2723 | moxa_boards[cardno].intTable = baseAddr + IRQtable; | ||
2724 | return (0); | ||
2725 | } | ||
2726 | |||
2727 | static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPorts) | ||
2728 | { | ||
2729 | ushort usum; | ||
2730 | int i, j, wlen, len2, retry; | ||
2731 | ushort *uptr; | ||
2732 | |||
2733 | usum = 0; | ||
2734 | wlen = len >> 1; | ||
2735 | uptr = (ushort *) moxaBuff; | ||
2736 | for (i = 0; i < wlen; i++) | ||
2737 | usum += le16_to_cpu(uptr[i]); | ||
2738 | retry = 0; | ||
2739 | j = 0; | ||
2740 | do { | ||
2741 | while (wlen) { | ||
2742 | if (wlen > 2048) | ||
2743 | len2 = 2048; | ||
2744 | else | ||
2745 | len2 = wlen; | ||
2746 | wlen -= len2; | ||
2747 | len2 <<= 1; | ||
2748 | for (i = 0; i < len2; i++) | ||
2749 | writeb(moxaBuff[j + i], baseAddr + C320_LoadBuf + i); | ||
2750 | len2 >>= 1; | ||
2751 | j += i; | ||
2752 | writew(len2, baseAddr + C320DLoad_len); | ||
2753 | writew(0, baseAddr + C320_key); | ||
2754 | for (i = 0; i < 10; i++) { | ||
2755 | if (readw(baseAddr + C320_key) == C320_KeyCode) | ||
2756 | break; | ||
2757 | msleep(10); | ||
2758 | } | ||
2759 | if (readw(baseAddr + C320_key) != C320_KeyCode) | ||
2760 | return (-1); | ||
2761 | } | ||
2762 | writew(0, baseAddr + C320DLoad_len); | ||
2763 | writew(usum, baseAddr + C320check_sum); | ||
2764 | writew(0, baseAddr + C320_key); | ||
2765 | for (i = 0; i < 10; i++) { | ||
2766 | if (readw(baseAddr + C320_key) == C320_KeyCode) | ||
2767 | break; | ||
2768 | msleep(10); | ||
2769 | } | ||
2770 | retry++; | ||
2771 | } while ((readb(baseAddr + C320chksum_ok) != 1) && (retry < 3)); | ||
2772 | if (readb(baseAddr + C320chksum_ok) != 1) | ||
2773 | return (-1); | ||
2774 | writew(0, baseAddr + C320_key); | ||
2775 | for (i = 0; i < 600; i++) { | ||
2776 | if (readw(baseAddr + Magic_no) == Magic_code) | ||
2777 | break; | ||
2778 | msleep(10); | ||
2779 | } | ||
2780 | if (readw(baseAddr + Magic_no) != Magic_code) | ||
2781 | return (-100); | ||
2782 | |||
2783 | if (moxa_boards[cardno].busType == MOXA_BUS_TYPE_PCI) { /* ASIC board */ | ||
2784 | writew(0x3800, baseAddr + TMS320_PORT1); | ||
2785 | writew(0x3900, baseAddr + TMS320_PORT2); | ||
2786 | writew(28499, baseAddr + TMS320_CLOCK); | ||
2787 | } else { | ||
2788 | writew(0x3200, baseAddr + TMS320_PORT1); | ||
2789 | writew(0x3400, baseAddr + TMS320_PORT2); | ||
2790 | writew(19999, baseAddr + TMS320_CLOCK); | ||
2791 | } | ||
2792 | writew(1, baseAddr + Disable_IRQ); | ||
2793 | writew(0, baseAddr + Magic_no); | ||
2794 | for (i = 0; i < 500; i++) { | ||
2795 | if (readw(baseAddr + Magic_no) == Magic_code) | ||
2796 | break; | ||
2797 | msleep(10); | ||
2798 | } | ||
2799 | if (readw(baseAddr + Magic_no) != Magic_code) | ||
2800 | return (-102); | ||
2801 | |||
2802 | j = readw(baseAddr + Module_cnt); | ||
2803 | if (j <= 0) | ||
2804 | return (-101); | ||
2805 | *numPorts = j * 8; | ||
2806 | writew(j, baseAddr + Module_no); | ||
2807 | writew(0, baseAddr + Magic_no); | ||
2808 | for (i = 0; i < 600; i++) { | ||
2809 | if (readw(baseAddr + Magic_no) == Magic_code) | ||
2810 | break; | ||
2811 | msleep(10); | ||
2812 | } | ||
2813 | if (readw(baseAddr + Magic_no) != Magic_code) | ||
2814 | return (-102); | ||
2815 | moxaCard = 1; | ||
2816 | moxa_boards[cardno].intNdx = baseAddr + IRQindex; | ||
2817 | moxa_boards[cardno].intPend = baseAddr + IRQpending; | ||
2818 | moxa_boards[cardno].intTable = baseAddr + IRQtable; | ||
2819 | return (0); | ||
2820 | } | ||
2821 | |||
2822 | static void MoxaSetFifo(int port, int enable) | 2625 | static void MoxaSetFifo(int port, int enable) |
2823 | { | 2626 | { |
2824 | void __iomem *ofsAddr = moxa_ports[port].tableAddr; | 2627 | void __iomem *ofsAddr = moxa_ports[port].tableAddr; |