isicom.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:52k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * This program is free software; you can redistribute it and/or
  3.  * modify it under the terms of the GNU General Public License
  4.  * as published by the Free Software Foundation; either version
  5.  * 2 of the License, or (at your option) any later version.
  6.  *
  7.  * Original driver code supplied by Multi-Tech
  8.  *
  9.  * Changes
  10.  * 1/9/98 alan@redhat.com Merge to 2.0.x kernel tree
  11.  * Obtain and use official major/minors
  12.  * Loader switched to a misc device
  13.  * (fixed range check bug as a side effect)
  14.  * Printk clean up
  15.  * 9/12/98 alan@redhat.com Rough port to 2.1.x
  16.  *
  17.  * 10/6/99 sameer Merged the ISA and PCI drivers to
  18.  * a new unified driver.
  19.  * 09/06/01 acme@conectiva.com.br use capable, not suser, do
  20.  * restore_flags on failure in
  21.  * isicom_send_break, verify put_user
  22.  * result
  23.  * ***********************************************************
  24.  *
  25.  * To use this driver you also need the support package. You 
  26.  * can find this in RPM format on
  27.  * ftp://ftp.linux.org.uk/pub/linux/alan
  28.  * 
  29.  * You can find the original tools for this direct from Multitech
  30.  * ftp://ftp.multitech.com/ISI-Cards/
  31.  *
  32.  * Having installed the cards the module options (/etc/modules.conf)
  33.  *
  34.  * options isicom   io=card1,card2,card3,card4 irq=card1,card2,card3,card4
  35.  *
  36.  * Omit those entries for boards you don't have installed.
  37.  *
  38.  */
  39. #include <linux/module.h>
  40. #include <linux/version.h>
  41. #include <linux/kernel.h>
  42. #include <linux/tty.h>
  43. #include <linux/termios.h>
  44. #include <linux/fs.h>
  45. #include <linux/sched.h>
  46. #include <linux/serial.h>
  47. #include <linux/mm.h>
  48. #include <linux/miscdevice.h>
  49. #include <linux/interrupt.h>
  50. #include <linux/timer.h>
  51. #include <linux/ioport.h>
  52. #include <asm/segment.h>
  53. #include <asm/uaccess.h>
  54. #include <asm/io.h>
  55. #include <asm/system.h>
  56. #include <linux/pci.h>
  57. #include <linux/isicom.h>
  58. static struct pci_device_id isicom_pci_tbl[] = {
  59. { VENDOR_ID, 0x2028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
  60. { VENDOR_ID, 0x2051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
  61. { VENDOR_ID, 0x2052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
  62. { VENDOR_ID, 0x2053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
  63. { VENDOR_ID, 0x2054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
  64. { VENDOR_ID, 0x2055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
  65. { VENDOR_ID, 0x2056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
  66. { VENDOR_ID, 0x2057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
  67. { VENDOR_ID, 0x2058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
  68. { 0 }
  69. };
  70. MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
  71. static int isicom_refcount;
  72. static int prev_card = 3; /* start servicing isi_card[0] */
  73. static struct isi_board * irq_to_board[16];
  74. static struct tty_driver isicom_normal, isicom_callout;
  75. static struct tty_struct * isicom_table[PORT_COUNT];
  76. static struct termios * isicom_termios[PORT_COUNT];
  77. static struct termios * isicom_termios_locked[PORT_COUNT];
  78. static struct isi_board isi_card[BOARD_COUNT];
  79. static struct isi_port  isi_ports[PORT_COUNT];
  80. DECLARE_TASK_QUEUE(tq_isicom);
  81. static struct timer_list tx;
  82. static char re_schedule = 1;
  83. #ifdef ISICOM_DEBUG
  84. static unsigned long tx_count = 0;
  85. #endif
  86. static int ISILoad_ioctl(struct inode *inode, struct file *filp, unsigned  int cmd, unsigned long arg);
  87. static void isicom_tx(unsigned long _data);
  88. static void isicom_start(struct tty_struct * tty);
  89. static unsigned char * tmp_buf = 0;
  90. static DECLARE_MUTEX(tmp_buf_sem);
  91. /*   baud index mappings from linux defns to isi */
  92. static signed char linuxb_to_isib[] = {
  93. -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17,     
  94. 18, 19
  95. };
  96. /* 
  97.  *  Firmware loader driver specific routines
  98.  *
  99.  */
  100. static struct file_operations ISILoad_fops = {
  101. owner: THIS_MODULE,
  102. ioctl: ISILoad_ioctl,
  103. };
  104. struct miscdevice isiloader_device = {
  105. ISILOAD_MISC_MINOR, "isictl", &ISILoad_fops
  106. };
  107.  
  108. extern inline int WaitTillCardIsFree(unsigned short base)
  109. {
  110. unsigned long count=0;
  111. while( (!(inw(base+0xe) & 0x1)) && (count++ < 6000000));
  112. if (inw(base+0xe)&0x1)  
  113. return 0;
  114. else
  115. return 1;
  116. }
  117. static int ISILoad_ioctl(struct inode *inode, struct file *filp,
  118.          unsigned int cmd, unsigned long arg)
  119. {
  120. unsigned int card, i, j, signature, status, portcount = 0;
  121. unsigned short word_count, base;
  122. bin_frame frame;
  123. /* exec_record exec_rec; */
  124. if(get_user(card, (int *)arg))
  125. return -EFAULT;
  126. if(card < 0 || card >= BOARD_COUNT)
  127. return -ENXIO;
  128. base=isi_card[card].base;
  129. if(base==0)
  130. return -ENXIO; /* disabled or not used */
  131. switch(cmd) {
  132. case MIOCTL_RESET_CARD:
  133. if (!capable(CAP_SYS_ADMIN))
  134. return -EPERM;
  135. printk(KERN_DEBUG "ISILoad:Resetting Card%d at 0x%x ",card+1,base);
  136. inw(base+0x8);
  137. for(i=jiffies+HZ/100;time_before(jiffies, i););
  138. outw(0,base+0x8); /* Reset */
  139. for(j=1;j<=3;j++) {
  140. for(i=jiffies+HZ;time_before(jiffies, i););
  141. printk(".");
  142. }
  143. signature=(inw(base+0x4)) & 0xff;
  144. if (isi_card[card].isa) {
  145. if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) {
  146. #ifdef ISICOM_DEBUG
  147. printk("nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
  148. #endif
  149. printk("nISILoad:ISA Card%d reset failure (Possible bad I/O Port Address 0x%x).n",card+1,base);
  150. return -EIO;
  151. }
  152. }
  153. else {
  154. portcount = inw(base+0x2);
  155. if (!(inw(base+0xe) & 0x1) || ((portcount!=0) && (portcount!=4) && (portcount!=8))) {
  156. #ifdef ISICOM_DEBUG
  157. printk("nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
  158. #endif
  159. printk("nISILoad:PCI Card%d reset failure (Possible bad I/O Port Address 0x%x).n",card+1,base);
  160. return -EIO;
  161. }
  162. }
  163. switch(signature) {
  164. case 0xa5:
  165. case 0xbb:
  166. case 0xdd:
  167. if (isi_card[card].isa) 
  168. isi_card[card].port_count = 8;
  169. else {
  170. if (portcount == 4)
  171. isi_card[card].port_count = 4;
  172. else
  173. isi_card[card].port_count = 8;
  174. }
  175.       isi_card[card].shift_count = 12;
  176.       break;
  177.         
  178. case 0xcc: isi_card[card].port_count = 16;
  179. isi_card[card].shift_count = 11;
  180. break;  
  181. default: printk("ISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).n",card+1,base);
  182. #ifdef ISICOM_DEBUG
  183.  printk("Sig=0x%xn",signature);
  184. #endif  
  185.  return -EIO;
  186. }
  187. printk("-Donen");
  188. return put_user(signature,(unsigned int*)arg);
  189. case MIOCTL_LOAD_FIRMWARE:
  190. if (!capable(CAP_SYS_ADMIN))
  191. return -EPERM;
  192. if(copy_from_user(&frame, (void *) arg, sizeof(bin_frame)))
  193. return -EFAULT;
  194. if (WaitTillCardIsFree(base))
  195. return -EIO;
  196. outw(0xf0,base); /* start upload sequence */ 
  197. outw(0x00,base);
  198. outw((frame.addr), base);/*      lsb of adderess    */
  199. word_count=(frame.count >> 1) + frame.count % 2;
  200. outw(word_count, base);
  201. InterruptTheCard(base);
  202. for(i=0;i<=0x2f;i++); /* a wee bit of delay */
  203. if (WaitTillCardIsFree(base)) 
  204. return -EIO;
  205. if ((status=inw(base+0x4))!=0) {
  206. printk(KERN_WARNING "ISILoad:Card%d rejected load header:nAddress:0x%x nCount:0x%x nStatus:0x%x n", 
  207. card+1, frame.addr, frame.count, status);
  208. return -EIO;
  209. }
  210. outsw(base, (void *) frame.bin_data, word_count);
  211. InterruptTheCard(base);
  212. for(i=0;i<=0x0f;i++); /* another wee bit of delay */ 
  213. if (WaitTillCardIsFree(base)) 
  214. return -EIO;
  215. if ((status=inw(base+0x4))!=0) {
  216. printk(KERN_ERR "ISILoad:Card%d got out of sync.Card Status:0x%xn",card+1, status);
  217. return -EIO;
  218. }
  219. return 0;
  220. case MIOCTL_READ_FIRMWARE:
  221. if (!capable(CAP_SYS_ADMIN))
  222. return -EPERM;
  223. if(copy_from_user(&frame, (void *) arg, sizeof(bin_header)))
  224. return -EFAULT;
  225. if (WaitTillCardIsFree(base))
  226. return -EIO;
  227. outw(0xf1,base); /* start download sequence */ 
  228. outw(0x00,base);
  229. outw((frame.addr), base);/*      lsb of adderess    */
  230. word_count=(frame.count >> 1) + frame.count % 2;
  231. outw(word_count+1, base);
  232. InterruptTheCard(base);
  233. for(i=0;i<=0xf;i++); /* a wee bit of delay */
  234. if (WaitTillCardIsFree(base)) 
  235. return -EIO;
  236. if ((status=inw(base+0x4))!=0) {
  237. printk(KERN_WARNING "ISILoad:Card%d rejected verify header:nAddress:0x%x nCount:0x%x nStatus:0x%x n", 
  238. card+1, frame.addr, frame.count, status);
  239. return -EIO;
  240. }
  241. inw(base);
  242. insw(base, frame.bin_data, word_count);
  243. InterruptTheCard(base);
  244. for(i=0;i<=0x0f;i++); /* another wee bit of delay */ 
  245. if (WaitTillCardIsFree(base)) 
  246. return -EIO;
  247. if ((status=inw(base+0x4))!=0) {
  248. printk(KERN_ERR "ISILoad:Card%d verify got out of sync.Card Status:0x%xn",card+1, status);
  249. return -EIO;
  250. }
  251. if(copy_to_user((void *) arg, &frame, sizeof(bin_frame)))
  252. return -EFAULT;
  253. return 0;
  254. case MIOCTL_XFER_CTRL:
  255. if (!capable(CAP_SYS_ADMIN))
  256. return -EPERM;
  257. if (WaitTillCardIsFree(base)) 
  258. return -EIO;
  259. outw(0xf2, base);
  260. outw(0x800, base);
  261. outw(0x0, base);
  262. outw(0x0, base);
  263. InterruptTheCard(base);
  264. outw(0x0, base+0x4);    /* for ISI4608 cards */
  265. isi_card[card].status |= FIRMWARE_LOADED;
  266. return 0;
  267. default:
  268. #ifdef ISICOM_DEBUG
  269. printk(KERN_DEBUG "ISILoad: Received Ioctl cmd 0x%x.n", cmd); 
  270. #endif
  271. return -ENOIOCTLCMD;
  272. }
  273. }
  274.         
  275. /*
  276.  * ISICOM Driver specific routines ...
  277.  *
  278.  */
  279.  
  280. static inline int isicom_paranoia_check(struct isi_port const * port, kdev_t dev, 
  281. const char * routine)
  282. {
  283. #ifdef ISICOM_DEBUG 
  284. static const char * badmagic = 
  285. KERN_WARNING "ISICOM: Warning: bad isicom magic for dev %s in %s.n";
  286. static const char * badport = 
  287. KERN_WARNING "ISICOM: Warning: NULL isicom port for dev %s in %s.n";
  288. if (!port) {
  289. printk(badport, kdevname(dev), routine);
  290. return 1;
  291. }
  292. if (port->magic != ISICOM_MAGIC) {
  293. printk(badmagic, kdevname(dev), routine);
  294. return 1;
  295. }
  296. #endif
  297. return 0;
  298. }
  299. extern inline void schedule_bh(struct isi_port * port)
  300. {
  301. queue_task(&port->bh_tqueue, &tq_isicom);
  302. mark_bh(ISICOM_BH);
  303. /* Transmitter */
  304. static void isicom_tx(unsigned long _data)
  305. {
  306. short count = (BOARD_COUNT-1), card, base;
  307. short txcount, wait, wrd, residue, word_count, cnt;
  308. struct isi_port * port;
  309. struct tty_struct * tty;
  310. unsigned long flags;
  311. #ifdef ISICOM_DEBUG
  312. ++tx_count;
  313. #endif
  314. /* find next active board */
  315. card = (prev_card + 1) & 0x0003;
  316. while(count-- > 0) {
  317. if (isi_card[card].status & BOARD_ACTIVE) 
  318. break;
  319. card = (card + 1) & 0x0003;
  320. }
  321. if (!(isi_card[card].status & BOARD_ACTIVE))
  322. goto sched_again;
  323. prev_card = card;
  324. count = isi_card[card].port_count;
  325. port = isi_card[card].ports;
  326. base = isi_card[card].base;
  327. for (;count > 0;count--, port++) {
  328. /* port not active or tx disabled to force flow control */
  329. if (!(port->status & ISI_TXOK))
  330. continue;
  331. tty = port->tty;
  332. save_flags(flags); cli();
  333. txcount = MIN(TX_SIZE, port->xmit_cnt);
  334. if ((txcount <= 0) || tty->stopped || tty->hw_stopped) {
  335. restore_flags(flags);
  336. continue;
  337. }
  338. wait = 200;
  339. while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
  340. if (wait <= 0) {
  341. restore_flags(flags);
  342. #ifdef ISICOM_DEBUG
  343. printk(KERN_DEBUG "ISICOM: isicom_tx:Card(0x%x) found busy.n",
  344. card);
  345. #endif
  346. continue;
  347. }
  348. if (!(inw(base + 0x02) & (1 << port->channel))) {
  349. restore_flags(flags);
  350. #ifdef ISICOM_DEBUG
  351. printk(KERN_DEBUG "ISICOM: isicom_tx: cannot tx to 0x%x:%d.n",
  352. base, port->channel + 1);
  353. #endif
  354. continue;
  355. }
  356. #ifdef ISICOM_DEBUG
  357. printk(KERN_DEBUG "ISICOM: txing %d bytes, port%d.n", 
  358. txcount, port->channel+1); 
  359. #endif
  360. outw((port->channel << isi_card[card].shift_count) | txcount
  361. , base);
  362. residue = NO;
  363. wrd = 0;
  364. while (1) {
  365. cnt = MIN(txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
  366. if (residue == YES) {
  367. residue = NO;
  368. if (cnt > 0) {
  369. wrd |= (port->xmit_buf[port->xmit_tail] << 8);
  370. port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
  371. port->xmit_cnt--;
  372. txcount--;
  373. cnt--;
  374. outw(wrd, base);
  375. }
  376. else {
  377. outw(wrd, base);
  378. break;
  379. }
  380. }
  381. if (cnt <= 0) break;
  382. word_count = cnt >> 1;
  383. outsw(base, port->xmit_buf+port->xmit_tail, word_count);
  384. port->xmit_tail = (port->xmit_tail + (word_count << 1)) &
  385. (SERIAL_XMIT_SIZE - 1);
  386. txcount -= (word_count << 1);
  387. port->xmit_cnt -= (word_count << 1);
  388. if (cnt & 0x0001) {
  389. residue = YES;
  390. wrd = port->xmit_buf[port->xmit_tail];
  391. port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
  392. port->xmit_cnt--;
  393. txcount--;
  394. }
  395. }
  396. InterruptTheCard(base);
  397. if (port->xmit_cnt <= 0)
  398. port->status &= ~ISI_TXOK;
  399. if (port->xmit_cnt <= WAKEUP_CHARS)
  400. schedule_bh(port);
  401. restore_flags(flags);
  402. }
  403. /* schedule another tx for hopefully in about 10ms */
  404. sched_again:
  405. if (!re_schedule)
  406. return;
  407. init_timer(&tx);
  408. tx.expires = jiffies + HZ/100;
  409. tx.data = 0;
  410. tx.function = isicom_tx;
  411. add_timer(&tx);
  412. return;
  413. }
  414.  
  415. /*  Interrupt handlers  */
  416. static void do_isicom_bh(void)
  417. {
  418. run_task_queue(&tq_isicom);
  419. }
  420.  
  421. static void isicom_bottomhalf(void * data)
  422. {
  423. struct isi_port * port = (struct isi_port *) data;
  424. struct tty_struct * tty = port->tty;
  425. if (!tty)
  426. return;
  427. if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
  428.     tty->ldisc.write_wakeup)
  429. (tty->ldisc.write_wakeup)(tty);
  430. wake_up_interruptible(&tty->write_wait);
  431.  
  432. /* main interrupt handler routine */ 
  433. static void isicom_interrupt(int irq, void * dev_id, struct pt_regs * regs)
  434. {
  435. struct isi_board * card;
  436. struct isi_port * port;
  437. struct tty_struct * tty;
  438. unsigned short base, header, word_count, count;
  439. unsigned char channel;
  440. short byte_count;
  441. /*
  442.  *      find the source of interrupt
  443.  */
  444.  
  445. for(count = 0; count < BOARD_COUNT; count++) { 
  446. card = &isi_card[count];
  447. if (card->base != 0) {
  448. if (((card->isa == YES) && (card->irq == irq)) || 
  449. ((card->isa == NO) && (card->irq == irq) && (inw(card->base+0x0e) & 0x02)))
  450. break;
  451. }
  452. card = NULL;
  453. }
  454. if (!card || !(card->status & FIRMWARE_LOADED)) {
  455. /* printk(KERN_DEBUG "ISICOM: interrupt: not handling irq%d!.n", irq);*/
  456. return;
  457. }
  458. base = card->base;
  459. if (card->isa == NO) {
  460. /*
  461.  *      disable any interrupts from the PCI card and lower the
  462.  *      interrupt line
  463.  */
  464. outw(0x8000, base+0x04);
  465. ClearInterrupt(base);
  466. }
  467. inw(base); /* get the dummy word out */
  468. header = inw(base);
  469. channel = (header & 0x7800) >> card->shift_count;
  470. byte_count = header & 0xff;
  471. #ifdef ISICOM_DEBUG
  472. printk(KERN_DEBUG "ISICOM:Intr:(0x%x:%d).n", base, channel+1);
  473. #endif
  474. if ((channel+1) > card->port_count) {
  475. printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%x): %d(channel) > port_count.n",
  476. base, channel+1);
  477. if (card->isa)
  478. ClearInterrupt(base);
  479. else
  480. outw(0x0000, base+0x04); /* enable interrupts */
  481. return;
  482. }
  483. port = card->ports + channel;
  484. if (!(port->flags & ASYNC_INITIALIZED)) {
  485. if (card->isa)
  486. ClearInterrupt(base);
  487. else
  488. outw(0x0000, base+0x04); /* enable interrupts */
  489. return;
  490. }
  491. tty = port->tty;
  492. if (header & 0x8000) { /* Status Packet */
  493. header = inw(base);
  494. switch(header & 0xff) {
  495. case 0: /* Change in EIA signals */
  496. if (port->flags & ASYNC_CHECK_CD) {
  497. if (port->status & ISI_DCD) {
  498. if (!(header & ISI_DCD)) {
  499. /* Carrier has been lost  */
  500. #ifdef ISICOM_DEBUG
  501. printk(KERN_DEBUG "ISICOM: interrupt: DCD->low.n");
  502. #endif
  503. port->status &= ~ISI_DCD;
  504. if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
  505. (port->flags & ASYNC_CALLOUT_NOHUP))) {
  506. MOD_INC_USE_COUNT;
  507. if (schedule_task(&port->hangup_tq) == 0)
  508. MOD_DEC_USE_COUNT;
  509. }
  510. }
  511. }
  512. else {
  513. if (header & ISI_DCD) {
  514. /* Carrier has been detected */
  515. #ifdef ISICOM_DEBUG
  516. printk(KERN_DEBUG "ISICOM: interrupt: DCD->high.n");
  517. #endif
  518. port->status |= ISI_DCD;
  519. wake_up_interruptible(&port->open_wait);
  520. }
  521. }
  522. }
  523. else {
  524. if (header & ISI_DCD) 
  525. port->status |= ISI_DCD;
  526. else
  527. port->status &= ~ISI_DCD;
  528. }
  529. if (port->flags & ASYNC_CTS_FLOW) {
  530. if (port->tty->hw_stopped) {
  531. if (header & ISI_CTS) {
  532. port->tty->hw_stopped = 0;
  533. /* start tx ing */
  534. port->status |= (ISI_TXOK | ISI_CTS);
  535. schedule_bh(port);
  536. }
  537. }
  538. else {
  539. if (!(header & ISI_CTS)) {
  540. port->tty->hw_stopped = 1;
  541. /* stop tx ing */
  542. port->status &= ~(ISI_TXOK | ISI_CTS);
  543. }
  544. }
  545. }
  546. else {
  547. if (header & ISI_CTS) 
  548. port->status |= ISI_CTS;
  549. else
  550. port->status &= ~ISI_CTS;
  551. }
  552. if (header & ISI_DSR) 
  553. port->status |= ISI_DSR;
  554. else
  555. port->status &= ~ISI_DSR;
  556. if (header & ISI_RI) 
  557. port->status |= ISI_RI;
  558. else
  559. port->status &= ~ISI_RI;
  560. break;
  561. case 1: /* Received Break !!!  */
  562. if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  563. break;
  564. *tty->flip.flag_buf_ptr++ = TTY_BREAK;
  565. /* dunno if this is right */
  566. *tty->flip.char_buf_ptr++ = 0;
  567. tty->flip.count++;
  568. if (port->flags & ASYNC_SAK)
  569. do_SAK(tty);
  570. queue_task(&tty->flip.tqueue, &tq_timer);
  571. break;
  572. case 2: /* Statistics  */
  573. printk(KERN_DEBUG "ISICOM: isicom_interrupt: stats!!!.n");
  574. break;
  575. default:
  576. printk(KERN_WARNING "ISICOM: Intr: Unknown code in status packet.n");
  577. break;
  578. }  
  579. }
  580. else { /* Data   Packet */
  581. count = MIN(byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
  582. #ifdef ISICOM_DEBUG
  583. printk(KERN_DEBUG "ISICOM: Intr: Can rx %d of %d bytes.n", 
  584. count, byte_count);
  585. #endif
  586. word_count = count >> 1;
  587. insw(base, tty->flip.char_buf_ptr, word_count);
  588. tty->flip.char_buf_ptr += (word_count << 1);
  589. byte_count -= (word_count << 1);
  590. if (count & 0x0001) {
  591. *tty->flip.char_buf_ptr++ = (char)(inw(base) & 0xff);
  592. byte_count -= 2;
  593. }
  594. memset(tty->flip.flag_buf_ptr, 0, count);
  595. tty->flip.flag_buf_ptr += count;
  596. tty->flip.count += count;
  597. if (byte_count > 0) {
  598. printk(KERN_DEBUG "ISICOM: Intr(0x%x:%d): Flip buffer overflow! dropping bytes...n",
  599. base, channel+1);
  600. while(byte_count > 0) { /* drain out unread xtra data */
  601. inw(base);
  602. byte_count -= 2;
  603. }
  604. }
  605. queue_task(&tty->flip.tqueue, &tq_timer);
  606. }
  607. if (card->isa == YES)
  608. ClearInterrupt(base);
  609. else
  610. outw(0x0000, base+0x04); /* enable interrupts */
  611. return;
  612.  /* called with interrupts disabled */ 
  613. static void isicom_config_port(struct isi_port * port)
  614. {
  615. struct isi_board * card = port->card;
  616. struct tty_struct * tty;
  617. unsigned long baud;
  618. unsigned short channel_setup, wait, base = card->base;
  619. unsigned short channel = port->channel, shift_count = card->shift_count;
  620. unsigned char flow_ctrl;
  621. if (!(tty = port->tty) || !tty->termios)
  622. return;
  623. baud = C_BAUD(tty);
  624. if (baud & CBAUDEX) {
  625. baud &= ~CBAUDEX;
  626. /*  if CBAUDEX bit is on and the baud is set to either 50 or 75
  627.  *  then the card is programmed for 57.6Kbps or 115Kbps
  628.  *  respectively.
  629.  */   
  630.  
  631. if (baud < 1 || baud > 2)
  632. port->tty->termios->c_cflag &= ~CBAUDEX;
  633. else
  634. baud += 15;
  635. }
  636. if (baud == 15) {
  637. /*  the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set 
  638.  *  by the set_serial_info ioctl ... this is done by
  639.  *  the 'setserial' utility.
  640.  */  
  641. if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
  642. baud++;     /*  57.6 Kbps */
  643. if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
  644. baud +=2;   /*  115  Kbps */  
  645. }
  646. if (linuxb_to_isib[baud] == -1) {
  647. /* hang up */
  648.   drop_dtr(port);
  649.   return;
  650. }
  651. else  
  652. raise_dtr(port);
  653. wait = 100;
  654. while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));
  655. if (!wait) {
  656. printk(KERN_WARNING "ISICOM: Card found busy in isicom_config_port at channel setup.n");
  657. return;
  658. }  
  659. outw(0x8000 | (channel << shift_count) |0x03, base);
  660. outw(linuxb_to_isib[baud] << 8 | 0x03, base);
  661. channel_setup = 0;
  662. switch(C_CSIZE(tty)) {
  663. case CS5:
  664. channel_setup |= ISICOM_CS5;
  665. break;
  666. case CS6:
  667. channel_setup |= ISICOM_CS6;
  668. break;
  669. case CS7:
  670. channel_setup |= ISICOM_CS7;
  671. break;
  672. case CS8:
  673. channel_setup |= ISICOM_CS8;
  674. break;
  675. }
  676. if (C_CSTOPB(tty))
  677. channel_setup |= ISICOM_2SB;
  678. if (C_PARENB(tty))
  679. channel_setup |= ISICOM_EVPAR;
  680. if (C_PARODD(tty))
  681. channel_setup |= ISICOM_ODPAR;
  682. outw(channel_setup, base);
  683. InterruptTheCard(base);
  684. if (C_CLOCAL(tty))
  685. port->flags &= ~ASYNC_CHECK_CD;
  686. else
  687. port->flags |= ASYNC_CHECK_CD;
  688. /* flow control settings ...*/
  689. flow_ctrl = 0;
  690. port->flags &= ~ASYNC_CTS_FLOW;
  691. if (C_CRTSCTS(tty)) {
  692. port->flags |= ASYNC_CTS_FLOW;
  693. flow_ctrl |= ISICOM_CTSRTS;
  694. }
  695. if (I_IXON(tty))
  696. flow_ctrl |= ISICOM_RESPOND_XONXOFF;
  697. if (I_IXOFF(tty))
  698. flow_ctrl |= ISICOM_INITIATE_XONXOFF;
  699. wait = 100;
  700. while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));
  701. if (!wait) {
  702. printk(KERN_WARNING "ISICOM: Card found busy in isicom_config_port at flow setup.n");
  703. return;
  704. }  
  705. outw(0x8000 | (channel << shift_count) |0x04, base);
  706. outw(flow_ctrl << 8 | 0x05, base);
  707. outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
  708. InterruptTheCard(base);
  709. /* rx enabled -> enable port for rx on the card */
  710. if (C_CREAD(tty)) {
  711. card->port_status |= (1 << channel);
  712. outw(card->port_status, base + 0x02);
  713. }
  714. }
  715.  
  716. /* open et all */ 
  717. extern inline void isicom_setup_board(struct isi_board * bp)
  718. {
  719. int channel;
  720. struct isi_port * port;
  721. unsigned long flags;
  722. if (bp->status & BOARD_ACTIVE) 
  723. return;
  724. port = bp->ports;
  725. #ifdef ISICOM_DEBUG
  726. printk(KERN_DEBUG "ISICOM: setup_board: drop_dtr_rts start, port_count %d...n", bp->port_count);
  727. #endif
  728. for(channel = 0; channel < bp->port_count; channel++, port++) {
  729. save_flags(flags); cli();
  730. drop_dtr_rts(port);
  731. restore_flags(flags);
  732. }
  733. #ifdef ISICOM_DEBUG
  734. printk(KERN_DEBUG "ISICOM: setup_board: drop_dtr_rts stop...n");
  735. #endif
  736. bp->status |= BOARD_ACTIVE;
  737. MOD_INC_USE_COUNT;
  738. return;
  739. }
  740.  
  741. static int isicom_setup_port(struct isi_port * port)
  742. {
  743. struct isi_board * card = port->card;
  744. unsigned long flags;
  745. if (port->flags & ASYNC_INITIALIZED)
  746. return 0;
  747. if (!port->xmit_buf) {
  748. unsigned long page;
  749. if (!(page = get_free_page(GFP_KERNEL)))
  750. return -ENOMEM;
  751. if (port->xmit_buf) {
  752. free_page(page);
  753. return -ERESTARTSYS;
  754. }
  755. port->xmit_buf = (unsigned char *) page;
  756. }
  757. save_flags(flags); cli();
  758. if (port->tty)
  759. clear_bit(TTY_IO_ERROR, &port->tty->flags);
  760. if (port->count == 1)
  761. card->count++;
  762. port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
  763. /* discard any residual data */
  764. kill_queue(port, ISICOM_KILLTX | ISICOM_KILLRX);
  765. isicom_config_port(port);
  766. port->flags |= ASYNC_INITIALIZED;
  767. restore_flags(flags);
  768. return 0;
  769.  
  770. static int block_til_ready(struct tty_struct * tty, struct file * filp, struct isi_port * port) 
  771. {
  772. int do_clocal = 0, retval;
  773. DECLARE_WAITQUEUE(wait, current);
  774. /* block if port is in the process of being closed */
  775. if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
  776. #ifdef ISICOM_DEBUG
  777. printk(KERN_DEBUG "ISICOM: block_til_ready: close in progress.n");
  778. #endif
  779. interruptible_sleep_on(&port->close_wait);
  780. if (port->flags & ASYNC_HUP_NOTIFY)
  781. return -EAGAIN;
  782. else
  783. return -ERESTARTSYS;
  784. }
  785. /* trying to open a callout device... check for constraints */
  786. if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
  787. #ifdef ISICOM_DEBUG
  788. printk(KERN_DEBUG "ISICOM: bl_ti_rdy: callout open.n");
  789. #endif
  790. if (port->flags & ASYNC_NORMAL_ACTIVE)
  791. return -EBUSY;
  792. if ((port->flags & ASYNC_CALLOUT_ACTIVE) &&
  793.     (port->flags & ASYNC_SESSION_LOCKOUT) &&
  794.     (port->session != current->session))
  795. return -EBUSY;
  796. if ((port->flags & ASYNC_CALLOUT_ACTIVE) &&
  797.     (port->flags & ASYNC_PGRP_LOCKOUT) &&
  798.     (port->pgrp != current->pgrp))
  799. return -EBUSY;
  800. port->flags |= ASYNC_CALLOUT_ACTIVE;
  801. cli();
  802. raise_dtr_rts(port);
  803. sti();
  804. return 0;
  805. }
  806. /* if non-blocking mode is set ... */
  807. if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
  808. #ifdef ISICOM_DEBUG
  809. printk(KERN_DEBUG "ISICOM: block_til_ready: non-block mode.n");
  810. #endif
  811. if (port->flags & ASYNC_CALLOUT_ACTIVE)
  812. return -EBUSY;
  813. port->flags |= ASYNC_NORMAL_ACTIVE;
  814. return 0;
  815. }
  816. if (port->flags & ASYNC_CALLOUT_ACTIVE) {
  817. if (port->normal_termios.c_cflag & CLOCAL)
  818. do_clocal = 1; 
  819. } else {
  820. if (C_CLOCAL(tty))
  821. do_clocal = 1;
  822. }
  823. #ifdef ISICOM_DEBUG
  824. if (do_clocal)
  825. printk(KERN_DEBUG "ISICOM: block_til_ready: CLOCAL set.n");
  826. #endif 
  827. /* block waiting for DCD to be asserted, and while 
  828. callout dev is busy */
  829. retval = 0;
  830. add_wait_queue(&port->open_wait, &wait);
  831. cli();
  832. if (!tty_hung_up_p(filp))
  833. port->count--;
  834. sti();
  835. port->blocked_open++;
  836. #ifdef ISICOM_DEBUG
  837. printk(KERN_DEBUG "ISICOM: block_til_ready: waiting for DCD...n");
  838. #endif
  839. while (1) {
  840. cli();
  841. if (!(port->flags & ASYNC_CALLOUT_ACTIVE)) 
  842. raise_dtr_rts(port);
  843. sti();
  844. set_current_state(TASK_INTERRUPTIBLE);
  845. if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { 
  846. if (port->flags & ASYNC_HUP_NOTIFY)
  847. retval = -EAGAIN;
  848. else
  849. retval = -ERESTARTSYS;
  850. #ifdef ISICOM_DEBUG
  851. printk(KERN_DEBUG "ISICOM: block_til_ready: tty_hung_up_p || not init.n"); 
  852. #endif
  853. break;
  854. }
  855. if (!(port->flags & ASYNC_CALLOUT_ACTIVE) &&
  856.     !(port->flags & ASYNC_CLOSING) &&
  857.     (do_clocal || (port->status & ISI_DCD))) {
  858. #ifdef ISICOM_DEBUG     
  859.   printk(KERN_DEBUG "ISICOM: block_til_ready: do_clocal || DCD.n");   
  860. #endif  
  861. break;
  862. }
  863. if (signal_pending(current)) {
  864. #ifdef ISICOM_DEBUG
  865. printk(KERN_DEBUG "ISICOM: block_til_ready: sig blocked.n");
  866. #endif
  867. retval = -ERESTARTSYS;
  868. break;
  869. }
  870. schedule();
  871. }
  872. set_current_state(TASK_RUNNING);
  873. remove_wait_queue(&port->open_wait, &wait);
  874. if (!tty_hung_up_p(filp))
  875. port->count++;
  876. port->blocked_open--;
  877. if (retval)
  878. return retval;
  879. port->flags |= ASYNC_NORMAL_ACTIVE;
  880. return 0;
  881. }
  882.  
  883. static int isicom_open(struct tty_struct * tty, struct file * filp)
  884. {
  885. struct isi_port * port;
  886. struct isi_board * card;
  887. unsigned int line, board;
  888. unsigned long flags;
  889. int error;
  890. #ifdef ISICOM_DEBUG
  891. printk(KERN_DEBUG "ISICOM: open start!!!.n");
  892. #endif
  893. line = MINOR(tty->device) - tty->driver.minor_start;
  894. #ifdef ISICOM_DEBUG
  895. printk(KERN_DEBUG "line = %d.n", line);
  896. #endif
  897. if ((line < 0) || (line > (PORT_COUNT-1)))
  898. return -ENODEV;
  899. board = BOARD(line);
  900. #ifdef ISICOM_DEBUG
  901. printk(KERN_DEBUG "board = %d.n", board);
  902. #endif
  903. card = &isi_card[board];
  904. if (!(card->status & FIRMWARE_LOADED)) {
  905. #ifdef ISICOM_DEBUG
  906. printk(KERN_DEBUG"ISICOM: Firmware not loaded to card%d.n", board);
  907. #endif
  908. return -ENODEV;
  909. }
  910. /*  open on a port greater than the port count for the card !!! */
  911. if (line > ((board * 16) + card->port_count - 1)) {
  912. printk(KERN_ERR "ISICOM: Open on a port which exceeds the port_count of the card!n");
  913. return -ENODEV;
  914. }
  915. port = &isi_ports[line];
  916. if (isicom_paranoia_check(port, tty->device, "isicom_open"))
  917. return -ENODEV;
  918. #ifdef ISICOM_DEBUG
  919. printk(KERN_DEBUG "ISICOM: isicom_setup_board ...n");
  920. #endif
  921. isicom_setup_board(card);
  922. port->count++;
  923. tty->driver_data = port;
  924. port->tty = tty;
  925. #ifdef ISICOM_DEBUG
  926. printk(KERN_DEBUG "ISICOM: isicom_setup_port ...n");
  927. #endif
  928. if ((error = isicom_setup_port(port))!=0)
  929. return error;
  930. #ifdef ISICOM_DEBUG
  931. printk(KERN_DEBUG "ISICOM: block_til_ready ...n");
  932. #endif
  933. if ((error = block_til_ready(tty, filp, port))!=0)
  934. return error;
  935. if ((port->count == 1) && (port->flags & ASYNC_SPLIT_TERMIOS)) {
  936. if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
  937. *tty->termios = port->normal_termios;
  938. else 
  939. *tty->termios = port->callout_termios;
  940. save_flags(flags); cli();
  941. isicom_config_port(port);
  942. restore_flags(flags);
  943. }
  944. port->session = current->session;
  945. port->pgrp = current->pgrp;
  946. #ifdef ISICOM_DEBUG
  947. printk(KERN_DEBUG "ISICOM: open end!!!.n");
  948. #endif
  949. return 0;      
  950. }
  951.  
  952. /* close et all */
  953. extern inline void isicom_shutdown_board(struct isi_board * bp)
  954. {
  955. int channel;
  956. struct isi_port * port;
  957. if (!(bp->status & BOARD_ACTIVE))
  958. return;
  959. bp->status &= ~BOARD_ACTIVE;
  960. port = bp->ports;
  961. for(channel = 0; channel < bp->port_count; channel++, port++) {
  962. drop_dtr_rts(port);
  963. }
  964. MOD_DEC_USE_COUNT;
  965. }
  966. static void isicom_shutdown_port(struct isi_port * port)
  967. {
  968. struct isi_board * card = port->card;
  969. struct tty_struct * tty;
  970. if (!(port->flags & ASYNC_INITIALIZED))
  971. return;
  972. if (port->xmit_buf) {
  973. free_page((unsigned long) port->xmit_buf);
  974. port->xmit_buf = NULL;
  975. }
  976. if (!(tty = port->tty) || C_HUPCL(tty)) 
  977. /* drop dtr on this port */
  978. drop_dtr(port);
  979. /* any other port uninits  */ 
  980. if (tty)
  981. set_bit(TTY_IO_ERROR, &tty->flags);
  982. port->flags &= ~ASYNC_INITIALIZED;
  983. if (--card->count < 0) {
  984. printk(KERN_DEBUG "ISICOM: isicom_shutdown_port: bad board(0x%x) count %d.n",
  985. card->base, card->count);
  986. card->count = 0;
  987. }
  988. /* last port was closed , shutdown that boad too */
  989. if (!card->count)
  990. isicom_shutdown_board(card);
  991. }
  992. static void isicom_close(struct tty_struct * tty, struct file * filp)
  993. {
  994. struct isi_port * port = (struct isi_port *) tty->driver_data;
  995. struct isi_board * card = port->card;
  996. unsigned long flags;
  997. if (!port)
  998. return;
  999. if (isicom_paranoia_check(port, tty->device, "isicom_close"))
  1000. return;
  1001. #ifdef ISICOM_DEBUG
  1002. printk(KERN_DEBUG "ISICOM: Close start!!!.n");
  1003. #endif
  1004. save_flags(flags); cli();
  1005. if (tty_hung_up_p(filp)) {
  1006. restore_flags(flags);
  1007. return;
  1008. }
  1009. if ((tty->count == 1) && (port->count != 1)) {
  1010. printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count"
  1011. "tty->count = 1 port count = %d.n",
  1012. card->base, port->count);
  1013. port->count = 1;
  1014. }
  1015. if (--port->count < 0) {
  1016. printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count for"
  1017. "channel%d = %d", card->base, port->channel, 
  1018. port->count);
  1019. port->count = 0;
  1020. }
  1021. if (port->count) {
  1022. restore_flags(flags);
  1023. return;
  1024. port->flags |= ASYNC_CLOSING;
  1025. /* 
  1026.  * save termios struct since callout and dialin termios may be 
  1027.  * different.
  1028.  */
  1029. if (port->flags & ASYNC_NORMAL_ACTIVE)
  1030. port->normal_termios = *tty->termios;
  1031. if (port->flags & ASYNC_CALLOUT_ACTIVE)
  1032. port->callout_termios = *tty->termios;
  1033. tty->closing = 1;
  1034. if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
  1035. tty_wait_until_sent(tty, port->closing_wait);
  1036. /* indicate to the card that no more data can be received 
  1037.    on this port */
  1038. if (port->flags & ASYNC_INITIALIZED) {   
  1039. card->port_status &= ~(1 << port->channel);
  1040. outw(card->port_status, card->base + 0x02);
  1041. }
  1042. isicom_shutdown_port(port);
  1043. if (tty->driver.flush_buffer)
  1044. tty->driver.flush_buffer(tty);
  1045. if (tty->ldisc.flush_buffer)
  1046. tty->ldisc.flush_buffer(tty);
  1047. tty->closing = 0;
  1048. port->tty = 0;
  1049. if (port->blocked_open) {
  1050. if (port->close_delay) {
  1051. set_current_state(TASK_INTERRUPTIBLE);
  1052. #ifdef ISICOM_DEBUG
  1053. printk(KERN_DEBUG "ISICOM: scheduling until time out.n");
  1054. #endif
  1055. schedule_timeout(port->close_delay);
  1056. }
  1057. wake_up_interruptible(&port->open_wait);
  1058. }
  1059. port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE | 
  1060. ASYNC_CLOSING);
  1061. wake_up_interruptible(&port->close_wait);
  1062. restore_flags(flags);
  1063. #ifdef ISICOM_DEBUG
  1064. printk(KERN_DEBUG "ISICOM: Close end!!!.n");
  1065. #endif
  1066. }
  1067. /* write et all */
  1068. static int isicom_write(struct tty_struct * tty, int from_user,
  1069. const unsigned char * buf, int count)
  1070. {
  1071. struct isi_port * port = (struct isi_port *) tty->driver_data;
  1072. unsigned long flags;
  1073. int cnt, total = 0;
  1074. #ifdef ISICOM_DEBUG
  1075. printk(KERN_DEBUG "ISICOM: isicom_write for port%d: %d bytes.n",
  1076. port->channel+1, count);
  1077. #endif   
  1078. if (isicom_paranoia_check(port, tty->device, "isicom_write"))
  1079. return 0;
  1080. if (!tty || !port->xmit_buf || !tmp_buf)
  1081. return 0;
  1082. if (from_user)
  1083. down(&tmp_buf_sem); /* acquire xclusive access to tmp_buf */
  1084. save_flags(flags);
  1085. while(1) {
  1086. cli();
  1087. cnt = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
  1088. SERIAL_XMIT_SIZE - port->xmit_head));
  1089. if (cnt <= 0) 
  1090. break;
  1091. if (from_user) {
  1092. /* the following may block for paging... hence 
  1093.    enabling interrupts but tx routine may have 
  1094.    created more space in xmit_buf when the ctrl 
  1095.    gets back here  */
  1096. sti(); 
  1097. copy_from_user(tmp_buf, buf, cnt);
  1098. cli();
  1099. cnt = MIN(cnt, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
  1100. SERIAL_XMIT_SIZE - port->xmit_head));
  1101. memcpy(port->xmit_buf + port->xmit_head, tmp_buf, cnt);
  1102. }
  1103. else
  1104. memcpy(port->xmit_buf + port->xmit_head, buf, cnt);
  1105. port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE - 1);
  1106. port->xmit_cnt += cnt;
  1107. restore_flags(flags);
  1108. buf += cnt;
  1109. count -= cnt;
  1110. total += cnt;
  1111. }
  1112. if (from_user)
  1113. up(&tmp_buf_sem);
  1114. if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
  1115. port->status |= ISI_TXOK;
  1116. restore_flags(flags);
  1117. #ifdef ISICOM_DEBUG
  1118. printk(KERN_DEBUG "ISICOM: isicom_write %d bytes written.n", total);
  1119. #endif
  1120. return total;
  1121. }
  1122. /* put_char et all */
  1123. static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
  1124. {
  1125. struct isi_port * port = (struct isi_port *) tty->driver_data;
  1126. unsigned long flags;
  1127. if (isicom_paranoia_check(port, tty->device, "isicom_put_char"))
  1128. return;
  1129. if (!tty || !port->xmit_buf)
  1130. return;
  1131. #ifdef ISICOM_DEBUG
  1132. printk(KERN_DEBUG "ISICOM: put_char, port %d, char %c.n", port->channel+1, ch);
  1133. #endif
  1134. save_flags(flags); cli();
  1135. if (port->xmit_cnt >= (SERIAL_XMIT_SIZE - 1)) {
  1136. restore_flags(flags);
  1137. return;
  1138. }
  1139. port->xmit_buf[port->xmit_head++] = ch;
  1140. port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
  1141. port->xmit_cnt++;
  1142. restore_flags(flags);
  1143. }
  1144. /* flush_chars et all */
  1145. static void isicom_flush_chars(struct tty_struct * tty)
  1146. {
  1147. struct isi_port * port = (struct isi_port *) tty->driver_data;
  1148. if (isicom_paranoia_check(port, tty->device, "isicom_flush_chars"))
  1149. return;
  1150. if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
  1151.     !port->xmit_buf)
  1152. return;
  1153. /* this tells the transmitter to consider this port for
  1154.    data output to the card ... that's the best we can do. */
  1155. port->status |= ISI_TXOK;
  1156. }
  1157. /* write_room et all */
  1158. static int isicom_write_room(struct tty_struct * tty)
  1159. {
  1160. struct isi_port * port = (struct isi_port *) tty->driver_data;
  1161. int free;
  1162. if (isicom_paranoia_check(port, tty->device, "isicom_write_room"))
  1163. return 0;
  1164. free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
  1165. if (free < 0)
  1166. free = 0;
  1167. return free;
  1168. }
  1169. /* chars_in_buffer et all */
  1170. static int isicom_chars_in_buffer(struct tty_struct * tty)
  1171. {
  1172. struct isi_port * port = (struct isi_port *) tty->driver_data;
  1173. if (isicom_paranoia_check(port, tty->device, "isicom_chars_in_buffer"))
  1174. return 0;
  1175. return port->xmit_cnt;
  1176. }
  1177. /* ioctl et all */
  1178. extern inline void isicom_send_break(struct isi_port * port, unsigned long length)
  1179. {
  1180. struct isi_board * card = port->card;
  1181. short wait = 10;
  1182. unsigned short base = card->base;
  1183. unsigned long flags;
  1184. save_flags(flags); cli();
  1185. while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));
  1186. if (!wait) {
  1187. printk(KERN_DEBUG "ISICOM: Card found busy in isicom_send_break.n");
  1188. goto out;
  1189. }
  1190. outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
  1191. outw((length & 0xff) << 8 | 0x00, base);
  1192. outw((length & 0xff00), base);
  1193. InterruptTheCard(base);
  1194. out: restore_flags(flags);
  1195. }
  1196. static int isicom_get_modem_info(struct isi_port * port, unsigned int * value)
  1197. {
  1198. /* just send the port status */
  1199. unsigned int info;
  1200. unsigned short status = port->status;
  1201. info =  ((status & ISI_RTS) ? TIOCM_RTS : 0) |
  1202. ((status & ISI_DTR) ? TIOCM_DTR : 0) |
  1203. ((status & ISI_DCD) ? TIOCM_CAR : 0) |
  1204. ((status & ISI_DSR) ? TIOCM_DSR : 0) |
  1205. ((status & ISI_CTS) ? TIOCM_CTS : 0) |
  1206. ((status & ISI_RI ) ? TIOCM_RI  : 0);
  1207. return put_user(info, (unsigned int *) value);
  1208. }
  1209. static int isicom_set_modem_info(struct isi_port * port, unsigned int cmd,
  1210. unsigned int * value)
  1211. {
  1212. unsigned int arg;
  1213. unsigned long flags;
  1214. if(get_user(arg, value))
  1215. return -EFAULT;
  1216. save_flags(flags); cli();
  1217. switch(cmd) {
  1218. case TIOCMBIS:
  1219. if (arg & TIOCM_RTS) 
  1220. raise_rts(port);
  1221. if (arg & TIOCM_DTR) 
  1222. raise_dtr(port);
  1223. break;
  1224. case TIOCMBIC:
  1225. if (arg & TIOCM_RTS)
  1226. drop_rts(port);
  1227. if (arg & TIOCM_DTR)
  1228. drop_dtr(port);
  1229. break;
  1230. case TIOCMSET:
  1231. if (arg & TIOCM_RTS)
  1232. raise_rts(port);
  1233. else
  1234. drop_rts(port);
  1235. if (arg & TIOCM_DTR)
  1236. raise_dtr(port);
  1237. else
  1238. drop_dtr(port);
  1239. break;
  1240. default:
  1241. restore_flags(flags);
  1242. return -EINVAL;  
  1243. }
  1244. restore_flags(flags);
  1245. return 0;
  1246. }
  1247. static int isicom_set_serial_info(struct isi_port * port,
  1248. struct serial_struct * info)
  1249. {
  1250. struct serial_struct newinfo;
  1251. unsigned long flags;
  1252. int reconfig_port;
  1253. if(copy_from_user(&newinfo, info, sizeof(newinfo)))
  1254. return -EFAULT;
  1255. reconfig_port = ((port->flags & ASYNC_SPD_MASK) != 
  1256.  (newinfo.flags & ASYNC_SPD_MASK));
  1257. if (!capable(CAP_SYS_ADMIN)) {
  1258. if ((newinfo.close_delay != port->close_delay) ||
  1259.     (newinfo.closing_wait != port->closing_wait) ||
  1260.     ((newinfo.flags & ~ASYNC_USR_MASK) != 
  1261.      (port->flags & ~ASYNC_USR_MASK)))
  1262. return -EPERM;
  1263. port->flags = ((port->flags & ~ ASYNC_USR_MASK) |
  1264. (newinfo.flags & ASYNC_USR_MASK));
  1265. }
  1266. else {
  1267. port->close_delay = newinfo.close_delay;
  1268. port->closing_wait = newinfo.closing_wait; 
  1269. port->flags = ((port->flags & ~ASYNC_FLAGS) | 
  1270. (newinfo.flags & ASYNC_FLAGS));
  1271. }
  1272. if (reconfig_port) {
  1273. save_flags(flags); cli();
  1274. isicom_config_port(port);
  1275. restore_flags(flags);
  1276. }
  1277. return 0;  
  1278. }
  1279. static int isicom_get_serial_info(struct isi_port * port, 
  1280. struct serial_struct * info)
  1281. {
  1282. struct serial_struct out_info;
  1283. memset(&out_info, 0, sizeof(out_info));
  1284. /* out_info.type = ? */
  1285. out_info.line = port - isi_ports;
  1286. out_info.port = port->card->base;
  1287. out_info.irq = port->card->irq;
  1288. out_info.flags = port->flags;
  1289. /* out_info.baud_base = ? */
  1290. out_info.close_delay = port->close_delay;
  1291. out_info.closing_wait = port->closing_wait;
  1292. if(copy_to_user(info, &out_info, sizeof(out_info)))
  1293. return -EFAULT;
  1294. return 0;
  1295. }
  1296. static int isicom_ioctl(struct tty_struct * tty, struct file * filp,
  1297. unsigned int cmd, unsigned long arg) 
  1298. {
  1299. struct isi_port * port = (struct isi_port *) tty->driver_data;
  1300. int retval;
  1301. if (isicom_paranoia_check(port, tty->device, "isicom_ioctl"))
  1302. return -ENODEV;
  1303. switch(cmd) {
  1304. case TCSBRK:
  1305. retval = tty_check_change(tty);
  1306. if (retval)
  1307. return retval;
  1308. tty_wait_until_sent(tty, 0);
  1309. if (!arg)
  1310. isicom_send_break(port, HZ/4);
  1311. return 0;
  1312. case TCSBRKP:
  1313. retval = tty_check_change(tty);
  1314. if (retval)
  1315. return retval;
  1316. tty_wait_until_sent(tty, 0);
  1317. isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
  1318. return 0;
  1319. case TIOCGSOFTCAR:
  1320. return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
  1321. case TIOCSSOFTCAR:
  1322. if(get_user(arg, (unsigned long *) arg))
  1323. return -EFAULT;
  1324. tty->termios->c_cflag =
  1325. ((tty->termios->c_cflag & ~CLOCAL) |
  1326. (arg ? CLOCAL : 0));
  1327. return 0;
  1328. case TIOCMGET:
  1329. return isicom_get_modem_info(port, (unsigned int*) arg);
  1330. case TIOCMBIS:
  1331. case TIOCMBIC:
  1332. case TIOCMSET: 
  1333. return isicom_set_modem_info(port, cmd, 
  1334. (unsigned int *) arg);
  1335. case TIOCGSERIAL:
  1336. return isicom_get_serial_info(port, 
  1337. (struct serial_struct *) arg);
  1338. case TIOCSSERIAL:
  1339. return isicom_set_serial_info(port,
  1340. (struct serial_struct *) arg);
  1341. default:
  1342. return -ENOIOCTLCMD;
  1343. }
  1344. return 0;
  1345. }
  1346. /* set_termios et all */
  1347. static void isicom_set_termios(struct tty_struct * tty, struct termios * old_termios)
  1348. {
  1349. struct isi_port * port = (struct isi_port *) tty->driver_data;
  1350. unsigned long flags;
  1351. if (isicom_paranoia_check(port, tty->device, "isicom_set_termios"))
  1352. return;
  1353. if (tty->termios->c_cflag == old_termios->c_cflag &&
  1354.     tty->termios->c_iflag == old_termios->c_iflag)
  1355. return;
  1356. save_flags(flags); cli();
  1357. isicom_config_port(port);
  1358. restore_flags(flags);
  1359. if ((old_termios->c_cflag & CRTSCTS) &&
  1360.     !(tty->termios->c_cflag & CRTSCTS)) {
  1361. tty->hw_stopped = 0;
  1362. isicom_start(tty);   
  1363. }    
  1364. }
  1365. /* throttle et all */
  1366. static void isicom_throttle(struct tty_struct * tty)
  1367. {
  1368. struct isi_port * port = (struct isi_port *) tty->driver_data;
  1369. struct isi_board * card = port->card;
  1370. unsigned long flags;
  1371. if (isicom_paranoia_check(port, tty->device, "isicom_throttle"))
  1372. return;
  1373. /* tell the card that this port cannot handle any more data for now */
  1374. save_flags(flags); cli();
  1375. card->port_status &= ~(1 << port->channel);
  1376. outw(card->port_status, card->base + 0x02);
  1377. restore_flags(flags);
  1378. }
  1379. /* unthrottle et all */
  1380. static void isicom_unthrottle(struct tty_struct * tty)
  1381. {
  1382. struct isi_port * port = (struct isi_port *) tty->driver_data;
  1383. struct isi_board * card = port->card;
  1384. unsigned long flags;
  1385. if (isicom_paranoia_check(port, tty->device, "isicom_unthrottle"))
  1386. return;
  1387. /* tell the card that this port is ready to accept more data */
  1388. save_flags(flags); cli();
  1389. card->port_status |= (1 << port->channel);
  1390. outw(card->port_status, card->base + 0x02);
  1391. restore_flags(flags);
  1392. }
  1393. /* stop et all */
  1394. static void isicom_stop(struct tty_struct * tty)
  1395. {
  1396. struct isi_port * port = (struct isi_port *) tty->driver_data;
  1397. if (isicom_paranoia_check(port, tty->device, "isicom_stop"))
  1398. return;
  1399. /* this tells the transmitter not to consider this port for
  1400.    data output to the card. */
  1401. port->status &= ~ISI_TXOK;
  1402. }
  1403. /* start et all */
  1404. static void isicom_start(struct tty_struct * tty)
  1405. {
  1406. struct isi_port * port = (struct isi_port *) tty->driver_data;
  1407. if (isicom_paranoia_check(port, tty->device, "isicom_start"))
  1408. return;
  1409. /* this tells the transmitter to consider this port for
  1410.    data output to the card. */
  1411. port->status |= ISI_TXOK;
  1412. }
  1413. /* hangup et all */
  1414. static void do_isicom_hangup(void * data)
  1415. {
  1416. struct isi_port * port = (struct isi_port *) data;
  1417. struct tty_struct * tty;
  1418. tty = port->tty;
  1419. if (tty)
  1420. tty_hangup(tty); /* FIXME: module removal race here - AKPM */
  1421. MOD_DEC_USE_COUNT;
  1422. }
  1423. static void isicom_hangup(struct tty_struct * tty)
  1424. {
  1425. struct isi_port * port = (struct isi_port *) tty->driver_data;
  1426. if (isicom_paranoia_check(port, tty->device, "isicom_hangup"))
  1427. return;
  1428. isicom_shutdown_port(port);
  1429. port->count = 0;
  1430. port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);
  1431. port->tty = 0;
  1432. wake_up_interruptible(&port->open_wait);
  1433. }
  1434. /* flush_buffer et all */
  1435. static void isicom_flush_buffer(struct tty_struct * tty)
  1436. {
  1437. struct isi_port * port = (struct isi_port *) tty->driver_data;
  1438. unsigned long flags;
  1439. if (isicom_paranoia_check(port, tty->device, "isicom_flush_buffer"))
  1440. return;
  1441. save_flags(flags); cli();
  1442. port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
  1443. restore_flags(flags);
  1444. wake_up_interruptible(&tty->write_wait);
  1445. if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
  1446.     tty->ldisc.write_wakeup)
  1447. (tty->ldisc.write_wakeup)(tty);
  1448. }
  1449. static int register_ioregion(void)
  1450. {
  1451. int count, done=0;
  1452. for (count=0; count < BOARD_COUNT; count++ ) {
  1453. if (isi_card[count].base) {
  1454. if (check_region(isi_card[count].base,16)) {
  1455. printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x is busy. Card%d will be disabled.n",
  1456. isi_card[count].base,isi_card[count].base+15,count+1);
  1457. isi_card[count].base=0;
  1458. }
  1459. else {
  1460. request_region(isi_card[count].base,16,ISICOM_NAME);
  1461. #ifdef ISICOM_DEBUG
  1462. printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x requested for Card%d.n",isi_card[count].base,isi_card[count].base+15,count+1);
  1463. #endif
  1464. done++;
  1465. }
  1466. }
  1467. }
  1468. return done;
  1469. }
  1470. static void unregister_ioregion(void)
  1471. {
  1472. int count;
  1473. for (count=0; count < BOARD_COUNT; count++ ) 
  1474. if (isi_card[count].base) {
  1475. release_region(isi_card[count].base,16);
  1476. #ifdef ISICOM_DEBUG
  1477. printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x released for Card%d.n",isi_card[count].base,isi_card[count].base+15,count+1);
  1478. #endif
  1479. }
  1480. }
  1481. static int register_drivers(void)
  1482. {
  1483. int error;
  1484. /* tty driver structure initialization */
  1485. memset(&isicom_normal, 0, sizeof(struct tty_driver));
  1486. isicom_normal.magic = TTY_DRIVER_MAGIC;
  1487. isicom_normal.name  = "ttyM";
  1488. isicom_normal.major = ISICOM_NMAJOR;
  1489. isicom_normal.minor_start = 0;
  1490. isicom_normal.num = PORT_COUNT;
  1491. isicom_normal.type = TTY_DRIVER_TYPE_SERIAL;
  1492. isicom_normal.subtype = SERIAL_TYPE_NORMAL;
  1493. isicom_normal.init_termios = tty_std_termios;
  1494. isicom_normal.init_termios.c_cflag = 
  1495. B9600 | CS8 | CREAD | HUPCL |CLOCAL;
  1496. isicom_normal.flags = TTY_DRIVER_REAL_RAW;
  1497. isicom_normal.refcount = &isicom_refcount;
  1498. isicom_normal.table = isicom_table;
  1499. isicom_normal.termios = isicom_termios;
  1500. isicom_normal.termios_locked = isicom_termios_locked;
  1501. isicom_normal.open = isicom_open;
  1502. isicom_normal.close = isicom_close;
  1503. isicom_normal.write = isicom_write;
  1504. isicom_normal.put_char = isicom_put_char;
  1505. isicom_normal.flush_chars = isicom_flush_chars;
  1506. isicom_normal.write_room = isicom_write_room;
  1507. isicom_normal.chars_in_buffer = isicom_chars_in_buffer;
  1508. isicom_normal.ioctl = isicom_ioctl;
  1509. isicom_normal.set_termios = isicom_set_termios;
  1510. isicom_normal.throttle = isicom_throttle;
  1511. isicom_normal.unthrottle = isicom_unthrottle;
  1512. isicom_normal.stop = isicom_stop;
  1513. isicom_normal.start = isicom_start;
  1514. isicom_normal.hangup = isicom_hangup;
  1515. isicom_normal.flush_buffer = isicom_flush_buffer;
  1516. /* callout device */
  1517. isicom_callout = isicom_normal;
  1518. isicom_callout.name = "cum"; 
  1519. isicom_callout.major = ISICOM_CMAJOR;
  1520. isicom_callout.subtype = SERIAL_TYPE_CALLOUT;
  1521. if ((error=tty_register_driver(&isicom_normal))!=0) {
  1522. printk(KERN_DEBUG "ISICOM: Couldn't register the dialin driver, error=%dn",
  1523. error);
  1524. return error;
  1525. }
  1526. if ((error=tty_register_driver(&isicom_callout))!=0) {
  1527. tty_unregister_driver(&isicom_normal);
  1528. printk(KERN_DEBUG "ISICOM: Couldn't register the callout driver, error=%dn",
  1529. error);
  1530. return error;
  1531. }
  1532. return 0;
  1533. }
  1534. static void unregister_drivers(void)
  1535. {
  1536. int error;
  1537. if ((error=tty_unregister_driver(&isicom_callout))!=0)
  1538. printk(KERN_DEBUG "ISICOM: couldn't unregister callout driver error=%d.n",error);
  1539. if (tty_unregister_driver(&isicom_normal))
  1540. printk(KERN_DEBUG "ISICOM: couldn't unregister normal driver error=%d.n",error);
  1541. }
  1542. static int register_isr(void)
  1543. {
  1544. int count, done=0, card;
  1545. int flag;
  1546. unsigned char request;
  1547. for (count=0; count < BOARD_COUNT; count++ ) {
  1548. if (isi_card[count].base) {
  1549. /*
  1550.  * verify if the required irq has already been requested for
  1551.  * another ISI Card, if so we already have it, else request it
  1552.  */
  1553. request = YES;
  1554. for(card = 0; card < count; card++)
  1555. if ((isi_card[card].base) && (isi_card[card].irq == isi_card[count].irq)) {
  1556. request = NO;
  1557. if ((isi_card[count].isa == NO) && (isi_card[card].isa == NO))
  1558. break;
  1559. /*
  1560.  * ISA cards cannot share interrupts with other
  1561.  * PCI or ISA devices hence disable this card.
  1562.  */
  1563. release_region(isi_card[count].base,16);
  1564. isi_card[count].base = 0;
  1565. break;
  1566. }
  1567. flag=0;
  1568. if(isi_card[count].isa == NO)
  1569. flag |= SA_SHIRQ;
  1570. if (request == YES) { 
  1571. if (request_irq(isi_card[count].irq, isicom_interrupt, SA_INTERRUPT|flag, ISICOM_NAME, NULL)) {
  1572. printk(KERN_WARNING "ISICOM: Could not install handler at Irq %d. Card%d will be disabled.n",
  1573. isi_card[count].irq, count+1);
  1574. release_region(isi_card[count].base,16);
  1575. isi_card[count].base=0;
  1576. }
  1577. else {
  1578. printk(KERN_INFO "ISICOM: Card%d at 0x%x using irq %d.n", 
  1579. count+1, isi_card[count].base, isi_card[count].irq); 
  1580. irq_to_board[isi_card[count].irq]=&isi_card[count];
  1581. done++;
  1582. }
  1583. }
  1584. }
  1585. }
  1586. return done;
  1587. }
  1588. static void unregister_isr(void)
  1589. {
  1590. int count, card;
  1591. unsigned char freeirq;
  1592. for (count=0; count < BOARD_COUNT; count++ ) {
  1593. if (isi_card[count].base) {
  1594. freeirq = YES;
  1595. for(card = 0; card < count; card++)
  1596. if ((isi_card[card].base) && (isi_card[card].irq == isi_card[count].irq)) {
  1597. freeirq = NO;
  1598. break;
  1599. }
  1600. if (freeirq == YES) {
  1601. free_irq(isi_card[count].irq, NULL);
  1602. #ifdef ISICOM_DEBUG
  1603. printk(KERN_DEBUG "ISICOM: Irq %d released for Card%d.n",isi_card[count].irq, count+1);
  1604. #endif
  1605. }
  1606. }
  1607. }
  1608. }
  1609. static int isicom_init(void)
  1610. {
  1611. int card, channel, base;
  1612. struct isi_port * port;
  1613. unsigned long page;
  1614. if (!tmp_buf) { 
  1615. page = get_free_page(GFP_KERNEL);
  1616.        if (!page) {
  1617. #ifdef ISICOM_DEBUG       
  1618.        printk(KERN_DEBUG "ISICOM: Couldn't allocate page for tmp_buf.n");
  1619. #else
  1620. printk(KERN_ERR "ISICOM: Not enough memory...n");
  1621. #endif       
  1622.        return 0;
  1623.        }
  1624.        tmp_buf = (unsigned char *) page;
  1625. }
  1626. if (!register_ioregion()) 
  1627. {
  1628. printk(KERN_ERR "ISICOM: All required I/O space found busy.n");
  1629. free_page((unsigned long)tmp_buf);
  1630. return 0;
  1631. }
  1632. if (register_drivers()) 
  1633. {
  1634. unregister_ioregion();
  1635. free_page((unsigned long)tmp_buf);
  1636. return 0;
  1637. }
  1638. if (!register_isr()) 
  1639. {
  1640. unregister_drivers();
  1641. /*  ioports already uregistered in register_isr */
  1642. free_page((unsigned long)tmp_buf);
  1643. return 0;
  1644. }
  1645. /* initialize bottom half  */
  1646. init_bh(ISICOM_BH, do_isicom_bh);
  1647. memset(isi_ports, 0, sizeof(isi_ports));
  1648. for (card = 0; card < BOARD_COUNT; card++) {
  1649. port = &isi_ports[card * 16];
  1650. isi_card[card].ports = port;
  1651. base = isi_card[card].base;
  1652. for (channel = 0; channel < 16; channel++, port++) {
  1653. port->magic = ISICOM_MAGIC;
  1654. port->card = &isi_card[card];
  1655. port->channel = channel;
  1656. port->normal_termios = isicom_normal.init_termios;
  1657. port->callout_termios = isicom_callout.init_termios;
  1658.   port->close_delay = 50 * HZ/100;
  1659.   port->closing_wait = 3000 * HZ/100;
  1660. port->hangup_tq.routine = do_isicom_hangup;
  1661.   port->hangup_tq.data = port;
  1662.   port->bh_tqueue.routine = isicom_bottomhalf;
  1663.   port->bh_tqueue.data = port;
  1664.   port->status = 0;
  1665. init_waitqueue_head(&port->open_wait);  
  1666. init_waitqueue_head(&port->close_wait);
  1667. /*  . . .  */
  1668.   }
  1669. return 1;
  1670. }
  1671. /*
  1672.  * Insmod can set static symbols so keep these static
  1673.  */
  1674.  
  1675. static int io[4];
  1676. static int irq[4];
  1677. MODULE_AUTHOR("MultiTech");
  1678. MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
  1679. MODULE_LICENSE("GPL");
  1680. MODULE_PARM(io, "1-4i");
  1681. MODULE_PARM_DESC(io, "I/O ports for the cards");
  1682. MODULE_PARM(irq, "1-4i");
  1683. MODULE_PARM_DESC(irq, "Interrupts for the cards");
  1684. int init_module(void)
  1685. {
  1686. struct pci_dev *dev = NULL;
  1687. int retval, card, idx, count;
  1688. unsigned char pciirq;
  1689. unsigned int ioaddr;
  1690.                 
  1691. card = 0;
  1692. for(idx=0; idx < BOARD_COUNT; idx++) {
  1693. if (io[idx]) {
  1694. isi_card[idx].base=io[idx];
  1695. isi_card[idx].irq=irq[idx];
  1696. isi_card[idx].isa=YES;
  1697. card++;
  1698. }
  1699. else {
  1700. isi_card[idx].base = 0;
  1701. isi_card[idx].irq = 0;
  1702. }
  1703. }
  1704. for (idx=0 ;idx < card; idx++) {
  1705. if (!((isi_card[idx].irq==2)||(isi_card[idx].irq==3)||
  1706.     (isi_card[idx].irq==4)||(isi_card[idx].irq==5)||
  1707.     (isi_card[idx].irq==7)||(isi_card[idx].irq==10)||
  1708.     (isi_card[idx].irq==11)||(isi_card[idx].irq==12)||
  1709.     (isi_card[idx].irq==15))) {
  1710. if (isi_card[idx].base) {
  1711. printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...n",
  1712. isi_card[idx].irq, idx+1);
  1713. isi_card[idx].base=0;
  1714. card--;
  1715. }
  1716. }
  1717. }
  1718. if (pci_present() && (card < BOARD_COUNT)) {
  1719. for (idx=0; idx < DEVID_COUNT; idx++) {
  1720. dev = NULL;
  1721. for (;;){
  1722. if (!(dev = pci_find_device(VENDOR_ID, isicom_pci_tbl[idx].device, dev)))
  1723. break;
  1724. if (card >= BOARD_COUNT)
  1725. break;
  1726. if (pci_enable_device(dev))
  1727. break;
  1728. /* found a PCI ISI card! */
  1729. ioaddr = pci_resource_start (dev, 3); /* i.e at offset 0x1c in the
  1730.        * PCI configuration register
  1731.        * space.
  1732.        */
  1733. pciirq = dev->irq;
  1734. printk(KERN_INFO "ISI PCI Card(Device ID 0x%x)n", isicom_pci_tbl[idx].device);
  1735. /*
  1736.  * allot the first empty slot in the array
  1737.  */
  1738. for (count=0; count < BOARD_COUNT; count++) {
  1739. if (isi_card[count].base == 0) {
  1740. isi_card[count].base = ioaddr;
  1741. isi_card[count].irq = pciirq;
  1742. isi_card[count].isa = NO;
  1743. card++;
  1744. break;
  1745. }
  1746. }
  1747. }
  1748. if (card >= BOARD_COUNT) break;
  1749. }
  1750. }
  1751. if (!(isi_card[0].base || isi_card[1].base || isi_card[2].base || isi_card[3].base)) {
  1752. printk(KERN_ERR "ISICOM: No valid card configuration. Driver cannot be initialized...n"); 
  1753. return -EIO;
  1754. }
  1755. retval=misc_register(&isiloader_device);
  1756. if (retval<0) {
  1757. printk(KERN_ERR "ISICOM: Unable to register firmware loader driver.n");
  1758. return -EIO;
  1759. }
  1760. if (!isicom_init()) {
  1761. if (misc_deregister(&isiloader_device)) 
  1762. printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader drivern");
  1763. return -EIO;
  1764. }
  1765. init_timer(&tx);
  1766. tx.expires = jiffies + 1;
  1767. tx.data = 0;
  1768. tx.function = isicom_tx;
  1769. re_schedule = 1;
  1770. add_timer(&tx);
  1771. return 0;
  1772. }
  1773. void cleanup_module(void)
  1774. {
  1775. re_schedule = 0;
  1776. set_current_state(TASK_INTERRUPTIBLE);
  1777. schedule_timeout(HZ);
  1778. remove_bh(ISICOM_BH);
  1779. #ifdef ISICOM_DEBUG
  1780. printk("ISICOM: isicom_tx tx_count = %ld.n", tx_count);
  1781. #endif
  1782. #ifdef ISICOM_DEBUG
  1783. printk("ISICOM: uregistering isr ...n");
  1784. #endif
  1785. unregister_isr();
  1786. #ifdef ISICOM_DEBUG
  1787. printk("ISICOM: unregistering drivers ...n");
  1788. #endif
  1789. unregister_drivers();
  1790. #ifdef ISICOM_DEBUG
  1791. printk("ISICOM: unregistering ioregion ...n");
  1792. #endif
  1793. unregister_ioregion();
  1794. #ifdef ISICOM_DEBUG
  1795. printk("ISICOM: freeing tmp_buf ...n");
  1796. #endif
  1797. free_page((unsigned long)tmp_buf);
  1798. #ifdef ISICOM_DEBUG
  1799. printk("ISICOM: unregistering firmware loader ...n");
  1800. #endif
  1801. if (misc_deregister(&isiloader_device))
  1802. printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader drivern");
  1803. }