[PATCH] char/isicom: Firmware loading

Firmware loading via hotplug added.
Cleanup firmware old-way fields in header file.

Signed-off-by: Jiri Slaby <xslaby@fi.muni.cz>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Jiri Slaby and committed by
Linus Torvalds
e65c1db1 9ac0948b

+174 -271
+174 -236
drivers/char/isicom.c
··· 112 112 */ 113 113 114 114 #include <linux/module.h> 115 + #include <linux/firmware.h> 115 116 #include <linux/kernel.h> 116 117 #include <linux/tty.h> 117 118 #include <linux/tty_flip.h> ··· 121 120 #include <linux/sched.h> 122 121 #include <linux/serial.h> 123 122 #include <linux/mm.h> 124 - #include <linux/miscdevice.h> 125 123 #include <linux/interrupt.h> 126 124 #include <linux/timer.h> 127 125 #include <linux/delay.h> ··· 174 174 175 175 static struct timer_list tx; 176 176 static char re_schedule = 1; 177 - 178 - static int ISILoad_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); 179 177 180 178 static void isicom_tx(unsigned long _data); 181 179 static void isicom_start(struct tty_struct *tty); ··· 381 383 InterruptTheCard(base); 382 384 unlock_card(card); 383 385 } 384 - 385 - 386 - /* 387 - * Firmware loader driver specific routines. This needs to mostly die 388 - * and be replaced with request_firmware. 389 - */ 390 - 391 - static struct file_operations ISILoad_fops = { 392 - .owner = THIS_MODULE, 393 - .ioctl = ISILoad_ioctl, 394 - }; 395 - 396 - static struct miscdevice isiloader_device = { 397 - ISILOAD_MISC_MINOR, "isictl", &ISILoad_fops 398 - }; 399 - 400 - 401 - static inline int WaitTillCardIsFree(unsigned long base) 402 - { 403 - unsigned long count=0; 404 - while( (!(inw(base+0xe) & 0x1)) && (count++ < 6000000)); 405 - if (inw(base+0xe)&0x1) 406 - return 0; 407 - else 408 - return 1; 409 - } 410 - 411 - static int ISILoad_ioctl(struct inode *inode, struct file *filp, 412 - unsigned int cmd, unsigned long arg) 413 - { 414 - unsigned int card, i, j, signature, status, portcount = 0; 415 - unsigned long t, base; 416 - u16 word_count; 417 - bin_frame frame; 418 - void __user *argp = (void __user *)arg; 419 - /* exec_record exec_rec; */ 420 - 421 - if (get_user(card, (int __user *)argp)) 422 - return -EFAULT; 423 - 424 - if (card < 0 || card >= BOARD_COUNT) 425 - return -ENXIO; 426 - 427 - base=isi_card[card].base; 428 - 429 - if (base==0) 430 - return -ENXIO; /* disabled or not used */ 431 - 432 - switch(cmd) { 433 - case MIOCTL_RESET_CARD: 434 - if (!capable(CAP_SYS_ADMIN)) 435 - return -EPERM; 436 - printk(KERN_DEBUG "ISILoad:Resetting Card%d at 0x%lx ",card+1,base); 437 - 438 - inw(base+0x8); 439 - 440 - for (t=jiffies+HZ/100;time_before(jiffies, t);); 441 - 442 - outw(0,base+0x8); /* Reset */ 443 - 444 - for (j=1;j<=3;j++) { 445 - for (t=jiffies+HZ;time_before(jiffies, t);); 446 - printk("."); 447 - } 448 - signature=(inw(base+0x4)) & 0xff; 449 - if (isi_card[card].isa) { 450 - 451 - if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) { 452 - #ifdef ISICOM_DEBUG 453 - printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe)); 454 - #endif 455 - printk("\nISILoad:ISA Card%d reset failure (Possible bad I/O Port Address 0x%lx).\n",card+1,base); 456 - return -EIO; 457 - } 458 - } 459 - else { 460 - portcount = inw(base+0x2); 461 - if (!(inw(base+0xe) & 0x1) || ((portcount!=0) && (portcount!=4) && (portcount!=8))) { 462 - #ifdef ISICOM_DEBUG 463 - printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe)); 464 - #endif 465 - printk("\nISILoad:PCI Card%d reset failure (Possible bad I/O Port Address 0x%lx).\n",card+1,base); 466 - return -EIO; 467 - } 468 - } 469 - switch(signature) { 470 - case 0xa5: 471 - case 0xbb: 472 - case 0xdd: 473 - if (isi_card[card].isa) 474 - isi_card[card].port_count = 8; 475 - else { 476 - if (portcount == 4) 477 - isi_card[card].port_count = 4; 478 - else 479 - isi_card[card].port_count = 8; 480 - } 481 - isi_card[card].shift_count = 12; 482 - break; 483 - 484 - case 0xcc: isi_card[card].port_count = 16; 485 - isi_card[card].shift_count = 11; 486 - break; 487 - 488 - default: printk("ISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%lx).\n",card+1,base); 489 - #ifdef ISICOM_DEBUG 490 - printk("Sig=0x%x\n",signature); 491 - #endif 492 - return -EIO; 493 - } 494 - printk("-Done\n"); 495 - return put_user(signature,(unsigned __user *)argp); 496 - 497 - case MIOCTL_LOAD_FIRMWARE: 498 - if (!capable(CAP_SYS_ADMIN)) 499 - return -EPERM; 500 - 501 - if (copy_from_user(&frame, argp, sizeof(bin_frame))) 502 - return -EFAULT; 503 - 504 - if (WaitTillCardIsFree(base)) 505 - return -EIO; 506 - 507 - outw(0xf0,base); /* start upload sequence */ 508 - outw(0x00,base); 509 - outw((frame.addr), base); /* lsb of adderess */ 510 - 511 - word_count=(frame.count >> 1) + frame.count % 2; 512 - outw(word_count, base); 513 - InterruptTheCard(base); 514 - 515 - for (i=0;i<=0x2f;i++); /* a wee bit of delay */ 516 - 517 - if (WaitTillCardIsFree(base)) 518 - return -EIO; 519 - 520 - if ((status=inw(base+0x4))!=0) { 521 - printk(KERN_WARNING "ISILoad:Card%d rejected load header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n", 522 - card+1, frame.addr, frame.count, status); 523 - return -EIO; 524 - } 525 - outsw(base, (void *) frame.bin_data, word_count); 526 - 527 - InterruptTheCard(base); 528 - 529 - for (i=0;i<=0x0f;i++); /* another wee bit of delay */ 530 - 531 - if (WaitTillCardIsFree(base)) 532 - return -EIO; 533 - 534 - if ((status=inw(base+0x4))!=0) { 535 - printk(KERN_ERR "ISILoad:Card%d got out of sync.Card Status:0x%x\n",card+1, status); 536 - return -EIO; 537 - } 538 - return 0; 539 - 540 - case MIOCTL_READ_FIRMWARE: 541 - if (!capable(CAP_SYS_ADMIN)) 542 - return -EPERM; 543 - 544 - if (copy_from_user(&frame, argp, sizeof(bin_header))) 545 - return -EFAULT; 546 - 547 - if (WaitTillCardIsFree(base)) 548 - return -EIO; 549 - 550 - outw(0xf1,base); /* start download sequence */ 551 - outw(0x00,base); 552 - outw((frame.addr), base); /* lsb of adderess */ 553 - 554 - word_count=(frame.count >> 1) + frame.count % 2; 555 - outw(word_count+1, base); 556 - InterruptTheCard(base); 557 - 558 - for (i=0;i<=0xf;i++); /* a wee bit of delay */ 559 - 560 - if (WaitTillCardIsFree(base)) 561 - return -EIO; 562 - 563 - if ((status=inw(base+0x4))!=0) { 564 - printk(KERN_WARNING "ISILoad:Card%d rejected verify header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n", 565 - card+1, frame.addr, frame.count, status); 566 - return -EIO; 567 - } 568 - 569 - inw(base); 570 - insw(base, frame.bin_data, word_count); 571 - InterruptTheCard(base); 572 - 573 - for (i=0;i<=0x0f;i++); /* another wee bit of delay */ 574 - 575 - if (WaitTillCardIsFree(base)) 576 - return -EIO; 577 - 578 - if ((status=inw(base+0x4))!=0) { 579 - printk(KERN_ERR "ISILoad:Card%d verify got out of sync.Card Status:0x%x\n",card+1, status); 580 - return -EIO; 581 - } 582 - 583 - if (copy_to_user(argp, &frame, sizeof(bin_frame))) 584 - return -EFAULT; 585 - return 0; 586 - 587 - case MIOCTL_XFER_CTRL: 588 - if (!capable(CAP_SYS_ADMIN)) 589 - return -EPERM; 590 - if (WaitTillCardIsFree(base)) 591 - return -EIO; 592 - 593 - outw(0xf2, base); 594 - outw(0x800, base); 595 - outw(0x0, base); 596 - outw(0x0, base); 597 - InterruptTheCard(base); 598 - outw(0x0, base+0x4); /* for ISI4608 cards */ 599 - 600 - isi_card[card].status |= FIRMWARE_LOADED; 601 - return 0; 602 - 603 - default: 604 - #ifdef ISICOM_DEBUG 605 - printk(KERN_DEBUG "ISILoad: Received Ioctl cmd 0x%x.\n", cmd); 606 - #endif 607 - return -ENOIOCTLCMD; 608 - } 609 - } 610 - 611 386 612 387 /* 613 388 * ISICOM Driver specific routines ... ··· 1698 1927 return retval; 1699 1928 } 1700 1929 1930 + static inline int WaitTillCardIsFree(u16 base) 1931 + { 1932 + unsigned long count = 0; 1933 + 1934 + while (!(inw(base + 0xe) & 0x1) && count++ < 100) 1935 + msleep(5); 1936 + 1937 + return !(inw(base + 0xe) & 0x1); 1938 + } 1939 + 1940 + static int __devinit load_firmware(struct pci_dev *pdev, 1941 + const unsigned int index, const unsigned int signature) 1942 + { 1943 + struct isi_board *board = pci_get_drvdata(pdev); 1944 + const struct firmware *fw; 1945 + unsigned long base = board->base; 1946 + unsigned int a; 1947 + u16 word_count, status; 1948 + int retval = -EIO; 1949 + char *name; 1950 + u8 *data; 1951 + 1952 + struct stframe { 1953 + u16 addr; 1954 + u16 count; 1955 + u8 data[0]; 1956 + } *frame; 1957 + 1958 + switch (signature) { 1959 + case 0xa5: 1960 + name = "isi608.bin"; 1961 + break; 1962 + case 0xbb: 1963 + name = "isi608em.bin"; 1964 + break; 1965 + case 0xcc: 1966 + name = "isi616em.bin"; 1967 + break; 1968 + case 0xdd: 1969 + name = "isi4608.bin"; 1970 + break; 1971 + case 0xee: 1972 + name = "isi4616.bin"; 1973 + break; 1974 + default: 1975 + dev_err(&pdev->dev, "Unknown signature.\n"); 1976 + goto end; 1977 + } 1978 + 1979 + retval = request_firmware(&fw, name, &pdev->dev); 1980 + if (retval) 1981 + goto end; 1982 + 1983 + for (frame = (struct stframe *)fw->data; 1984 + frame < (struct stframe *)(fw->data + fw->size); 1985 + frame++) { 1986 + if (WaitTillCardIsFree(base)) 1987 + goto errrelfw; 1988 + 1989 + outw(0xf0, base); /* start upload sequence */ 1990 + outw(0x00, base); 1991 + outw(frame->addr, base); /* lsb of address */ 1992 + 1993 + word_count = frame->count / 2 + frame->count % 2; 1994 + outw(word_count, base); 1995 + InterruptTheCard(base); 1996 + 1997 + udelay(100); /* 0x2f */ 1998 + 1999 + if (WaitTillCardIsFree(base)) 2000 + goto errrelfw; 2001 + 2002 + if ((status = inw(base + 0x4)) != 0) { 2003 + dev_warn(&pdev->dev, "Card%d rejected load header:\n" 2004 + "Address:0x%x\nCount:0x%x\nStatus:0x%x\n", 2005 + index + 1, frame->addr, frame->count, status); 2006 + goto errrelfw; 2007 + } 2008 + outsw(base, frame->data, word_count); 2009 + 2010 + InterruptTheCard(base); 2011 + 2012 + udelay(50); /* 0x0f */ 2013 + 2014 + if (WaitTillCardIsFree(base)) 2015 + goto errrelfw; 2016 + 2017 + if ((status = inw(base + 0x4)) != 0) { 2018 + dev_err(&pdev->dev, "Card%d got out of sync.Card " 2019 + "Status:0x%x\n", index + 1, status); 2020 + goto errrelfw; 2021 + } 2022 + } 2023 + 2024 + retval = -EIO; 2025 + 2026 + if (WaitTillCardIsFree(base)) 2027 + goto errrelfw; 2028 + 2029 + outw(0xf2, base); 2030 + outw(0x800, base); 2031 + outw(0x0, base); 2032 + outw(0x0, base); 2033 + InterruptTheCard(base); 2034 + outw(0x0, base + 0x4); /* for ISI4608 cards */ 2035 + 2036 + /* XXX: should we test it by reading it back and comparing with original like 2037 + * in load firmware package? */ 2038 + for (frame = (struct stframe*)fw->data; 2039 + frame < (struct stframe*)(fw->data + fw->size); 2040 + frame++) { 2041 + if (WaitTillCardIsFree(base)) 2042 + goto errrelfw; 2043 + 2044 + outw(0xf1, base); /* start download sequence */ 2045 + outw(0x00, base); 2046 + outw(frame->addr, base); /* lsb of address */ 2047 + 2048 + word_count = (frame->count >> 1) + frame->count % 2; 2049 + outw(word_count + 1, base); 2050 + InterruptTheCard(base); 2051 + 2052 + udelay(50); /* 0xf */ 2053 + 2054 + if (WaitTillCardIsFree(base)) 2055 + goto errrelfw; 2056 + 2057 + if ((status = inw(base + 0x4)) != 0) { 2058 + dev_warn(&pdev->dev, "Card%d rejected verify header:\n" 2059 + "Address:0x%x\nCount:0x%x\nStatus: 0x%x\n", 2060 + index + 1, frame->addr, frame->count, status); 2061 + goto errrelfw; 2062 + } 2063 + 2064 + data = kmalloc(word_count * 2, GFP_KERNEL); 2065 + inw(base); 2066 + insw(base, data, word_count); 2067 + InterruptTheCard(base); 2068 + 2069 + for (a = 0; a < frame->count; a++) 2070 + if (data[a] != frame->data[a]) { 2071 + kfree(data); 2072 + dev_err(&pdev->dev, "Card%d, firmware upload " 2073 + "failed\n", index + 1); 2074 + goto errrelfw; 2075 + } 2076 + kfree(data); 2077 + 2078 + udelay(50); /* 0xf */ 2079 + 2080 + if (WaitTillCardIsFree(base)) 2081 + goto errrelfw; 2082 + 2083 + if ((status = inw(base + 0x4)) != 0) { 2084 + dev_err(&pdev->dev, "Card%d verify got out of sync. " 2085 + "Card Status:0x%x\n", index + 1, status); 2086 + goto errrelfw; 2087 + } 2088 + } 2089 + 2090 + board->status |= FIRMWARE_LOADED; 2091 + retval = 0; 2092 + 2093 + errrelfw: 2094 + release_firmware(fw); 2095 + end: 2096 + return retval; 2097 + } 2098 + 1701 2099 /* 1702 2100 * Insmod can set static symbols so keep these static 1703 2101 */ ··· 1913 1973 goto errunrr; 1914 1974 1915 1975 retval = reset_card(pdev, index, &signature); 1976 + if (retval < 0) 1977 + goto errunri; 1978 + 1979 + retval = load_firmware(pdev, index, signature); 1916 1980 if (retval < 0) 1917 1981 goto errunri; 1918 1982 ··· 1992 2048 goto errtty; 1993 2049 } 1994 2050 1995 - retval = misc_register(&isiloader_device); 1996 - if (retval < 0) 1997 - goto errpci; 1998 - 1999 2051 init_timer(&tx); 2000 2052 tx.expires = jiffies + 1; 2001 2053 tx.data = 0; ··· 2000 2060 add_timer(&tx); 2001 2061 2002 2062 return 0; 2003 - errpci: 2004 - pci_unregister_driver(&isicom_driver); 2005 2063 errtty: 2006 2064 isicom_unregister_tty_driver(); 2007 2065 error:
-35
include/linux/isicom.h
··· 4 4 /*#define ISICOM_DEBUG*/ 5 5 /*#define ISICOM_DEBUG_DTR_RTS*/ 6 6 7 - 8 - /* 9 - * Firmware Loader definitions ... 10 - */ 11 - 12 - #define __MultiTech ('M'<<8) 13 - #define MIOCTL_LOAD_FIRMWARE (__MultiTech | 0x01) 14 - #define MIOCTL_READ_FIRMWARE (__MultiTech | 0x02) 15 - #define MIOCTL_XFER_CTRL (__MultiTech | 0x03) 16 - #define MIOCTL_RESET_CARD (__MultiTech | 0x04) 17 - 18 - #define DATA_SIZE 16 19 - 20 - typedef struct { 21 - unsigned short exec_segment; 22 - unsigned short exec_addr; 23 - } exec_record; 24 - 25 - typedef struct { 26 - int board; /* Board to load */ 27 - unsigned short addr; 28 - unsigned short count; 29 - } bin_header; 30 - 31 - typedef struct { 32 - int board; /* Board to load */ 33 - unsigned short addr; 34 - unsigned short count; 35 - unsigned short segment; 36 - unsigned char bin_data[DATA_SIZE]; 37 - } bin_frame; 38 - 39 7 #ifdef __KERNEL__ 40 8 41 9 #define YES 1 42 10 #define NO 0 43 - 44 - #define ISILOAD_MISC_MINOR 155 /* /dev/isctl */ 45 - #define ISILOAD_NAME "ISILoad" 46 11 47 12 /* 48 13 * ISICOM Driver definitions ...