PageRenderTime 37ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/kernel_modules_drivers/gesytec-2.09/lpclinux.c

https://github.com/karlhiramoto/lon4linux
C | 1248 lines | 935 code | 126 blank | 187 comment | 118 complexity | d7007bcb90b3ad5eb92ebe4ad01776b8 MD5 | raw file
  1. /*
  2. * lpclinux.c
  3. *
  4. * Driver for "state of the art" LonWorks interfaces
  5. * Version 1.02b, Apr 2004
  6. * based on the generic LPC/LPP driver written by Ralf Feiland
  7. *
  8. * History:
  9. * Nov 1998 - Implementation of the generic driver
  10. * Mar 1999 - Windows CE driver based on the generic driver released
  11. * Mar 2000 - First beta release (0.90) of the linux driver
  12. * Jun 2000 - Beta release 0.91 bugfixed with IRQ sharing and module parameters
  13. * Oct 2000 - Beta release 0.92 with protocol analyzer interface (Watcher)
  14. * Aug 2002 - Release 1.00 running also on Linux 2.4
  15. * Jan 2003 - Release 1.01 bugfixed in driver unload,
  16. * optional ISA HW check at load time (CHECK_ISA_AT_LOAD_TIME)
  17. * Apr 2004 - Release 1.02 some debug output for
  18. * kernel panic in wake_up_interruptible(&dev->rd_wait);
  19. * Jun 2004 - Release 2.02 running on Linux 2.6 and 2.4
  20. * using PCI-PnP
  21. * Jun 2004 - do not use wake_up_interruptible_sync(), only wake_up_interruptible(),
  22. * it's very slow on Kernel 2.6.5
  23. * Nov 2005 - Release 2.08 used copy_to_user(), copy_from_user(), __get_user(),
  24. * __put_user() instead direct access to user memory
  25. * Dec 2005 - Release 2.09 evaluate return value from copy_to_user() and copy_from_user()
  26. *
  27. * This product may be distributed under the terms of the GNU Public License.
  28. *
  29. *
  30. * Compiling instructions:
  31. *
  32. * Only if you want to build a static driver,
  33. * insert a unique major number in /usr/include/linux/major.h:
  34. * Example: #define LPC_MAJOR 84
  35. *
  36. * Then compile the driver for Linux 2.2:
  37. * gcc -c -Wall -D__KERNEL__ -DMODULE -O2 lpclinux.c
  38. *
  39. * or for Linux 2.4:
  40. * gcc -c -Wall -D__KERNEL__ -DMODULE -O2 -I/usr/src/linux/include lpclinux.c
  41. *
  42. * Add some nodes in the /dev directory:
  43. * Minor number 0..31 are used for ISA cards
  44. * Minor number 32..63 are used for PCI cards
  45. *
  46. * Example:
  47. * mknod /dev/lon1 c 84 0 (lon1 is the 1st ISA card)
  48. * mknod /dev/lon2 c 84 1 (lon2 is the 2nd ISA card)
  49. * mknod /dev/lon3 c 84 32 (lon3 is the 1st PCI card)
  50. * mknod /dev/lon4 c 84 33 (lon4 is the 2nd PCI card)
  51. *
  52. * Don't forget to set the access rights:
  53. * chmod 666 /dev/lon*
  54. *
  55. * Load the driver:
  56. * insmod lpclinux.o [params]
  57. *
  58. * If you build a driver module (-DMODULE) instead of a static driver,
  59. * the major number is set at load time, so it is not necessary to
  60. * change the file major.h.
  61. * Example:
  62. * insmod lpclinux.o major=84
  63. *
  64. * The I/O addresses and IRQs of ISA cards can now be set at load time, so
  65. * it is not necessary to change the driver code.
  66. * ISA parameters are defined here as 16 bit values (4 hex digits)
  67. * Bits 11..0: base I/O address
  68. * Bits 15..12: IRQ, valid values are 3,5,7,9,A,B,C and F.
  69. *
  70. * The parameter isa is a string with 4 hex digits for each card.
  71. * All characters except 0..9, A..F and a..f are ignored and may be used
  72. * as seperators.
  73. * Also some other characters like comma and double quote are not allowed
  74. * by the insmod command.
  75. *
  76. * Example:
  77. * 1st card has address 0x340 and IRQ 5
  78. * 2nd card has address 0x344 and IRQ 7
  79. *
  80. * insmod lpclinux.o isa="53407344"
  81. * or
  82. * insmod lpclinux.o isa="5/340 7/344"
  83. * or
  84. * insmod lpclinux.o isa="irq=5 port=340h : irq=7 port=344h"
  85. *
  86. * Not allowed is
  87. * insmod lpclinux.o isa="interrupt = 5, baseaddress = 0x340"
  88. * ^ ^ ^^ ^^ ^ ^
  89. */
  90. #include "lpclinux.h"
  91. //#include "kdebug.c"
  92. #include "driverdata.c"
  93. //#include "dynbuf.c"
  94. static int downlink( DEV *dev )
  95. {
  96. u8 cmq, len, st;
  97. u8 *p;
  98. int idx;
  99. u32 cport, wport;
  100. dbg8("%s(): dev=%08X", __FUNCTION__, (uint)dev);
  101. cport = dev->cport;
  102. wport = dev->wport;
  103. idx = dev->outhead;
  104. p = dev->outbuf[idx];
  105. #if 0
  106. len = *p++;
  107. cmq = *p++;
  108. #else
  109. cmq = *p++;
  110. len = *p++;
  111. // len ++;
  112. #endif
  113. if (debug & DEBUG_DUMP2) DumpBuffer(">>", p-2, len+2);
  114. // printk(KERN_DEBUG ">len=%02X cmq=%02X\n", len, cmq);
  115. HS;
  116. NOUT(CMD_XFER);
  117. HS;
  118. NOUT(len+1);
  119. HS;
  120. NOUT(cmq);
  121. HS;
  122. // printk(KERN_DEBUG "len=%02X Loop: ", len);
  123. while(len--)
  124. {
  125. // printk ("%.2x ", *p);
  126. HS;
  127. NOUT(*p++);
  128. }
  129. // printk ("\n");
  130. HS;
  131. NOUT(EOM);
  132. idx++;
  133. if(idx >= NUM_OUTBUF) idx=0;
  134. dev->outhead = idx;
  135. return 0;
  136. }
  137. static int uplink( DEV *dev )
  138. {
  139. u8 cmq, len, st;
  140. u8 *p;
  141. int idx;
  142. u32 cport, rport;
  143. dbg8("%s(): dev=%08X", __FUNCTION__, (uint)dev);
  144. cport = dev->cport;
  145. rport = dev->rport;
  146. HS;
  147. if( !NIN ) return 0; // Pass token
  148. HS;
  149. len = NIN;
  150. HS;
  151. cmq = NIN;
  152. if(cmq == 0xC0) return 1; // niACK received
  153. idx = dev->intail; // uplink
  154. p = dev->inbuf[idx];
  155. #if 0
  156. *p++ = len;
  157. *p++ = cmq;
  158. len--;
  159. #else
  160. *p++ = cmq;
  161. len--;
  162. *p++ = len;
  163. #endif
  164. // printk(KERN_DEBUG "<len=%02X cmq=%02X\n", len, cmq);
  165. while( len-- )
  166. {
  167. HS;
  168. *p++ = NIN;
  169. }
  170. if (debug & DEBUG_DUMP2)
  171. {
  172. p = dev->inbuf[idx];
  173. len = p[1];
  174. DumpBuffer("<<", p, len+2);
  175. }
  176. idx++;
  177. if(idx >= NUM_INBUF) idx=0;
  178. if(idx != dev->inhead)
  179. {
  180. dev->intail = idx;
  181. dbg8(" %s(): before waitqueue_active()", __FUNCTION__);
  182. if (waitqueue_active(&dev->rd_wait))
  183. {
  184. dbg8(" %s(): before wake_up_interruptible()", __FUNCTION__);
  185. wake_up_interruptible( &dev->rd_wait );
  186. }
  187. else
  188. dbg8(" %s(): waitqueue_active()=0", __FUNCTION__);
  189. }
  190. return 0;
  191. }
  192. static int sm_lpc(register DEV *dev)
  193. {
  194. u8 *p;
  195. u8 st;
  196. int g;
  197. // int flags;
  198. u16 idx; // avoid critical section
  199. u32 cport, rport, wport;
  200. dbg4(" %s(): dev=%08X", __FUNCTION__, (uint)dev);
  201. cport = dev->cport;
  202. rport = dev->rport;
  203. wport = dev->wport;
  204. switch( dev->state )
  205. {
  206. case ST_RESYNC:
  207. if(LPCSTAT & 1) return 0;
  208. dev->ctl &= ~4;
  209. SETCTL; // clear reset flipflop
  210. SETCTL;
  211. SETCTL;
  212. dev->ctl |= 4;
  213. SETCTL;
  214. HS;
  215. NOUT(CMD_RESYNC); // send RESYNC
  216. HS;
  217. NOUT(EOM);
  218. HS;
  219. if(NIN != CMD_ACKSYNC) return -1; // get ACKSYNC
  220. dev->state = ST_RESET;
  221. return 0;
  222. case ST_RESET:
  223. HS;
  224. NOUT(CMD_NULL); // send NULL
  225. HS;
  226. NOUT(EOM);
  227. dev->state = ST_FLCAN;
  228. return 0;
  229. case ST_FLCAN:
  230. HS;
  231. if(NIN != CMD_XFER) return -1; // get niRESET
  232. HS;
  233. if(NIN != 1) return -1;
  234. HS;
  235. if(NIN != 0x50) return -1;
  236. // dev->intail = dev->inhead;
  237. // dev->outhead = dev->outtail;
  238. idx = dev->intail;
  239. p = dev->inbuf[idx];
  240. *p++ = 0x50;
  241. *p++ = 0x00;
  242. idx++;
  243. if(idx >= NUM_INBUF) idx=0;
  244. if(idx != dev->inhead)
  245. {
  246. dev->intail = idx;
  247. dbg8(" %s(): before waitqueue_active()", __FUNCTION__);
  248. if (waitqueue_active(&dev->rd_wait))
  249. {
  250. dbg8(" %s(): before wake_up_interruptible()", __FUNCTION__);
  251. wake_up_interruptible( &dev->rd_wait );
  252. }
  253. else
  254. dbg8(" %s(): waitqueue_active()=0", __FUNCTION__);
  255. }
  256. HS;
  257. NOUT(CMD_XFER); // send FLUSH_CANCEL
  258. HS;
  259. NOUT(1);
  260. HS;
  261. NOUT(0x60);
  262. HS;
  263. NOUT(EOM);
  264. dev->state = ST_UPLINK;
  265. return 0;
  266. case ST_IDLE:
  267. if(dev->outhead == dev->outtail) {
  268. HS;
  269. NOUT(CMD_NULL); // send NULL
  270. HS;
  271. NOUT(EOM);
  272. dev->state = ST_UPLINK;
  273. return 0;
  274. }
  275. p = dev->outbuf[dev->outhead];
  276. if( !((p[0]-0x10) & 0xE0) )
  277. { // 1x or 2x
  278. HS;
  279. NOUT(CMD_XFER); // buffer request
  280. HS;
  281. NOUT(0x01);
  282. HS;
  283. NOUT(p[0]);
  284. HS;
  285. NOUT(EOM);
  286. HS;
  287. dev->state = ST_NIACK;
  288. return 0;
  289. }
  290. if( downlink( dev ) ) return -1;
  291. dev->state = ST_UPLINK;
  292. return 0;
  293. case ST_UPLINK:
  294. if( uplink( dev ) < 0 ) return -1;
  295. dev->state = ST_IDLE;
  296. if(dev->outhead != dev->outtail) {
  297. // CLI;
  298. dev->active++;
  299. // STI;
  300. }
  301. return 0;
  302. case ST_NIACK:
  303. g = uplink( dev );
  304. if( g < 0 ) return -1;
  305. if( g == 1 ) {
  306. downlink( dev );
  307. dev->state = ST_UPLINK;
  308. return 0;
  309. }
  310. HS;
  311. NOUT(CMD_NULL); // send NULL
  312. HS;
  313. NOUT(EOM);
  314. dev->state = ST_NIACK;
  315. return 0;
  316. }
  317. return 0;
  318. }
  319. #ifndef NO_PCI
  320. static void DpcForIsr(unsigned long dev_addr)
  321. {
  322. DEV *dev = (DEV *) dev_addr;
  323. dbg4(" %s(): dev=%08X active=%X", __FUNCTION__, (uint)dev, dev->active);
  324. // do
  325. {
  326. int result;
  327. u32 cport;
  328. result = sm_lpc( dev );
  329. if (result < 0)
  330. {
  331. dev->active = 1; // will be 0
  332. dev->state = 0;
  333. cport = dev->cport;
  334. dbg4(" %s(): active=%X RST_CMND:", __FUNCTION__, dev->active);
  335. dev->ctl |= 0x01; // RST_CMND
  336. SETCTL;
  337. SETCTL;
  338. dev->ctl &= 0xFE;
  339. SETCTL;
  340. }
  341. --dev->active;
  342. }
  343. // while (--dev->active > 0);
  344. dev->drvtimer.expires = jiffies + HZ/5;
  345. add_timer( &dev->drvtimer );
  346. dbg4(" %s(): dev=%08X active=%X return", __FUNCTION__, (uint)dev, dev->active);
  347. }
  348. #endif
  349. #if 0
  350. // tasklet does not work with ISA-Card !!!
  351. static void sm_stub( DEV *dev )
  352. {
  353. dbg4(" %s(): dev=%08X active=%X", __FUNCTION__, (uint)dev, dev->active);
  354. ++dev->active;
  355. tasklet_schedule(&dev->Dpc);
  356. }
  357. #else
  358. static BOOLEAN sm_stub( DEV *dev )
  359. {
  360. int result;
  361. // int flags;
  362. u32 cport;
  363. dbg4(" %s(): dev=%08X active=%X", __FUNCTION__, (uint)dev, dev->active);
  364. if (++dev->active > 1)
  365. {
  366. dbg4(" %s(): active=%X", __FUNCTION__, dev->active);
  367. return FALSE;
  368. }
  369. do {
  370. result = sm_lpc( dev );
  371. if (result < 0)
  372. {
  373. dev->active = 1; // will be 0
  374. dev->state = 0;
  375. cport = dev->cport;
  376. dev->ctl |= 0x01;
  377. SETCTL;
  378. SETCTL;
  379. dev->ctl &= 0xFE;
  380. SETCTL;
  381. }
  382. } while (--dev->active > 0);
  383. dev->drvtimer.expires = jiffies + HZ/5;
  384. add_timer( &dev->drvtimer );
  385. return TRUE;
  386. }
  387. #endif
  388. static irqreturn_t lpc_isa_interrupt( int irq, void *ptr, struct pt_regs *regs )
  389. {
  390. DEV *dev;
  391. dev = (DEV *)ptr;
  392. if( inb(dev->cport) & 8 ) return IRQ_NONE; // Its not for me
  393. dbg2("+ %s(): dev=%08X", __FUNCTION__, (uint)dev);
  394. del_timer( &dev->drvtimer );
  395. outb(0, dev->rport); // Clear interrupt flipflop (ISA)
  396. sm_stub( dev );
  397. dbg2("- %s(): dev=%08X return", __FUNCTION__, (uint)dev);
  398. return IRQ_HANDLED;
  399. }
  400. #ifndef NO_PCI
  401. static irqreturn_t lpc_pci_interrupt( int irq, void *ptr, struct pt_regs *regs )
  402. {
  403. DEV *dev = (DEV *)ptr;
  404. u32 cport;
  405. u16 IntCsr = inw(dev->PlxIntCsrPort);
  406. // dev->PciIntCount++;
  407. // info("? %s(): dev=%08X IntCsr=%04X", __FUNCTION__, (uint)dev, IntCsr);
  408. if (IntCsr == 0xFFFF) return IRQ_NONE; // Can't read PLX
  409. if (inb(dev->cport) & 8) return IRQ_NONE; // Its not for me
  410. dbg2("+ %s(): dev=%08X", __FUNCTION__, (uint)dev);
  411. del_timer( &dev->drvtimer );
  412. cport = dev->cport;
  413. dev->ctl &= 0xEF; // Clear interrupt flipflop (PCI)
  414. SETCTL;
  415. SETCTL;
  416. SETCTL;
  417. dev->ctl |= 0x10; // CLR_IFF_CMND
  418. SETCTL;
  419. sm_stub(dev);
  420. dbg2("- %s(): dev=%08X return", __FUNCTION__, (uint)dev);
  421. return IRQ_HANDLED;
  422. }
  423. #endif
  424. static void lpc_timer( unsigned long ptr )
  425. {
  426. DEV *dev = (DEV *)ptr;
  427. dbg1("+ %s(): dev=%08X", __FUNCTION__, (uint)dev);
  428. sm_stub(dev);
  429. dbg1("- %s(): dev=%08X return", __FUNCTION__, (uint)dev);
  430. }
  431. static ssize_t lpc_write( struct file *file, const char *buf,
  432. size_t count, loff_t *off )
  433. {
  434. u8 *p;
  435. int idx;
  436. int len;
  437. // int flags;
  438. register DEV *dev = (DEV *)(file->private_data);
  439. dbg1("%s(): dev=%08X", __FUNCTION__, (uint)dev);
  440. // DbgFlush();
  441. if(count < 0) return -EINVAL;
  442. if(count > 256) return -EINVAL;
  443. idx = dev->outtail + 1;
  444. if(idx >= NUM_OUTBUF) idx = 0;
  445. // CLI;
  446. if(idx == dev->outhead)
  447. {
  448. // STI;
  449. dbg1("%s(): dev=%08X return -EWOULDBLOCK", __FUNCTION__, (uint)dev);
  450. return -EWOULDBLOCK;
  451. }
  452. // STI;
  453. p = dev->outbuf[ dev->outtail ];
  454. if (copy_from_user(p, buf, count))
  455. return -EFAULT;
  456. if (debug & DEBUG_DUMP1) DumpBuffer("> ", p, count);
  457. #if 0
  458. // app layer -> link layer
  459. len = p[1] + 1;
  460. p[1] = p[0];
  461. p[0] = (u8)len;
  462. len++;
  463. #else
  464. len = p[1] + 2;
  465. #endif
  466. dev->outtail = idx;
  467. if( dev->state == ST_IDLE )
  468. {
  469. del_timer( &dev->drvtimer );
  470. sm_stub( dev );
  471. }
  472. dbg1("%s(): dev=%08X return %d", __FUNCTION__, (uint)dev, len);
  473. return len;
  474. }
  475. static ssize_t lpc_read( struct file *file, char *buf,
  476. size_t count, loff_t *off )
  477. {
  478. // int flags;
  479. int idx;
  480. int len;
  481. u8 *p;
  482. register DEV *dev = (DEV *)(file->private_data);
  483. if(count < 0) return -EINVAL;
  484. dbg1("%s(): dev=%08X", __FUNCTION__, (uint)dev);
  485. // DbgFlush();
  486. idx = dev->inhead;
  487. #if 0
  488. CLI;
  489. if( idx == dev->intail )
  490. {
  491. if(file->f_flags & O_NONBLOCK)
  492. {
  493. STI;
  494. return -EWOULDBLOCK;
  495. }
  496. interruptible_sleep_on( &dev->rd_wait );
  497. /*
  498. The next line produces compiling errors, so I use a workaround
  499. if( current->signal & ~current->blocked ) return -ERESTARTSYS;
  500. */
  501. if( idx == dev->intail ) return -ERESTARTSYS;
  502. }
  503. STI;
  504. #else
  505. // if (qempty(&dev->ReadBufferQueue))
  506. if (idx == dev->intail)
  507. {
  508. dbg1("%s(): qempty", __FUNCTION__);
  509. // up (&dev->sem);
  510. if (file->f_flags & O_NONBLOCK)
  511. {
  512. dbg1("%s()=-EAGAIN !!!", __FUNCTION__);
  513. return -EAGAIN; // -EWOULDBLOCK;
  514. }
  515. // if (wait_event_interruptible(dev->rd_wait, qhasdata(&dev->ReadBufferQueue)))
  516. if (wait_event_interruptible(dev->rd_wait, (idx != dev->intail) ))
  517. {
  518. dbg1("%s(): dev=%08X return -ERESTARTSYS", __FUNCTION__, (uint)dev);
  519. return -ERESTARTSYS; /* signal: tell the fs layer to handle it */
  520. }
  521. dbg8("%s(): nach wait_event_interruptible(rd_wait)", __FUNCTION__);
  522. // if (down_interruptible(&dev->sem))
  523. // return -ERESTARTSYS;
  524. }
  525. #endif
  526. p = dev->inbuf[idx];
  527. #if 0
  528. // link layer -> app layer
  529. len = p[0];
  530. p[0] = p[1];
  531. p[1] = (u8)(len - 1);
  532. if( count > len + 1 ) count = len + 1;
  533. #else
  534. len = p[1]+2;
  535. if (count > len) count = len;
  536. #endif
  537. if (debug & DEBUG_DUMP1) DumpBuffer("< ", p, count);
  538. if (copy_to_user(buf, p, count))
  539. return -EFAULT;
  540. idx++;
  541. if(idx >= NUM_INBUF) idx = 0;
  542. dev->inhead = idx;
  543. dbg1("%s(): dev=%08X return %d", __FUNCTION__, (uint)dev, count);
  544. return count;
  545. }
  546. static unsigned lpc_poll( struct file *file, struct poll_table_struct *wait)
  547. {
  548. DEV *dev = file->private_data;
  549. unsigned mask = 0;
  550. dbg1("%s(): dev=%08X", __FUNCTION__, (uint)dev);
  551. // DbgFlush();
  552. poll_wait( file, &dev->rd_wait, wait);
  553. if(dev->inhead != dev->intail) mask |= POLLIN | POLLRDNORM;
  554. return mask;
  555. }
  556. static int initialize_isacard( DEV *dev, int index )
  557. {
  558. u32 cport, rport;
  559. int irq;
  560. dbg1("%s(): dev=%08X", __FUNCTION__, (uint)dev);
  561. /*
  562. if( !lpcs[index] ) {
  563. err( "invalid minor number %d\n", index );
  564. return -ENODEV;
  565. }
  566. iobase = lpcs[index] & 0x0FFF;
  567. irq = lpcs[index] >> 12;
  568. cport = iobase+1;
  569. rport = iobase+2;
  570. */
  571. cport = dev->cport;
  572. rport = dev->rport;
  573. irq = dev->irq;
  574. #ifndef CHECK_ISA_AT_LOAD_TIME
  575. {
  576. int hwfail = 0;
  577. if( ((u8)irq > 15) || !irq_table[irq] )
  578. {
  579. err("IRQ%d not supported\n", irq );
  580. return -ENODEV;
  581. }
  582. if( check_region(iobase, 4) )
  583. {
  584. err( "unable to register port 0x%X\n", iobase);
  585. return -ENODEV;
  586. }
  587. outb(0x5F, cport);
  588. outb(0, rport);
  589. outb(0, rport);
  590. outb(0, rport);
  591. if( (inb(cport) & 0xF0) != 0x50 ) hwfail = 1;
  592. outb(0x0F, cport);
  593. outb(0, rport);
  594. outb(0, rport);
  595. outb(0, rport);
  596. if( inb(cport) & 0xF0 ) hwfail = 1;
  597. if( hwfail )
  598. {
  599. err("interface card not responding at port 0x%X\n", iobase);
  600. return -ENODEV;
  601. }
  602. request_region( iobase, 4, DRIVER_DEV_NAME );
  603. }
  604. #endif
  605. /*
  606. dev->cport = iobase+1;
  607. dev->rport = iobase+2;
  608. dev->wport = iobase+3;
  609. dev->wtcport = iobase+0;
  610. dev->irq = irq;
  611. dev->PlxIntCsrPort = 0;
  612. */
  613. dev->ctl = 0x0F;
  614. SETCTL;
  615. SETCTL;
  616. dev->ctl = 0x0D;
  617. SETCTL;
  618. SETCTL;
  619. dev->ctl |= irq_table[dev->irq];
  620. SETCTL;
  621. SETCTL;
  622. dev->ctl &= 0xF6;
  623. SETCTL;
  624. if( request_irq(irq, lpc_isa_interrupt, SA_SHIRQ, DRIVER_DEV_NAME, dev) )
  625. {
  626. err("unable to register IRQ%d\n", irq);
  627. #ifndef CHECK_ISA_AT_LOAD_TIME
  628. release_region(iobase, 4);
  629. #endif
  630. return -ENODEV;
  631. }
  632. return 0;
  633. }
  634. #ifndef NO_PCI
  635. static int initialize_pcicard( DEV *dev, int index )
  636. {
  637. dbg1("%s(): dev=%08X", __FUNCTION__, (uint)dev);
  638. {
  639. #if 0
  640. u32 PlxIntCsrPort, cport, rport, wtcport, rtr;
  641. int irq;
  642. char bus, function;
  643. if( !pcibios_present() )
  644. {
  645. err( "PCI bios not present\n" );
  646. return -ENODEV;
  647. }
  648. if( pcibios_find_device( VENDOR_ID, DEVICE_ID, index, &bus, &function ) )
  649. {
  650. err( "PCI device not found\n" );
  651. return -ENODEV;
  652. }
  653. pcibios_read_config_dword( bus, function, 0x14, (int *)&rtr );
  654. pcibios_read_config_dword( bus, function, 0x18, (int *)&cport );
  655. pcibios_read_config_dword( bus, function, 0x1C, (int *)&rport );
  656. pcibios_read_config_dword( bus, function, 0x24, (int *)&wtcport );
  657. pcibios_read_config_dword( bus, function, 0x3C, &irq );
  658. PlxIntCsrPort = (rtr & 0xFFF0) + P9050_INTCSR;
  659. cport &= 0xFFF0;
  660. rport &= 0xFFF0;
  661. irq &= 0x0F;
  662. outw( 0, PlxIntCsrPort );
  663. if( check_region(cport, 4) ) {
  664. err( "unable to register port 0x%X\n", cport );
  665. return -ENODEV;
  666. }
  667. if( check_region(rport, 4) ) {
  668. err( "unable to register port 0x%X\n", rport );
  669. return -ENODEV;
  670. }
  671. request_region( cport, 4, DRIVER_DEV_NAME );
  672. request_region( rport, 4, DRIVER_DEV_NAME );
  673. dev->cport = cport;
  674. dev->rport = rport;
  675. dev->wport = rport;
  676. dev->wtcport = wtcport;
  677. dev->irq = irq;
  678. dev->PlxIntCsrPort = PlxIntCsrPort;
  679. #else
  680. u32 cport;
  681. u16 IntCsr;
  682. cport = dev->cport;
  683. #endif
  684. dev->ctl = 0x0D;
  685. SETCTL;
  686. SETCTL;
  687. dev->ctl = 0x16;
  688. SETCTL;
  689. SETCTL;
  690. dev->ctl = 0x02;
  691. SETCTL;
  692. SETCTL;
  693. dev->ctl = 0x16;
  694. SETCTL;
  695. IntCsr = inw(dev->PlxIntCsrPort);
  696. dbg1("? %s(): PlxIntCsrPort=%04X IntCsr=%04X", __FUNCTION__, dev->PlxIntCsrPort, IntCsr);
  697. IntCsr |= PLX_9050_INTR_ENABLE | PLX_9050_LINT1_ENABLE; // | PLX_9050_LINT2_ENABLE;
  698. outw(IntCsr, dev->PlxIntCsrPort);
  699. dbg1("? %s(): PlxIntCsrPort=%04X IntCsr=%04X", __FUNCTION__, dev->PlxIntCsrPort, IntCsr);
  700. if( request_irq(dev->irq, lpc_pci_interrupt, SA_SHIRQ, DRIVER_DEV_NAME, dev) )
  701. {
  702. err("unable to register IRQ%d\n", dev->irq);
  703. #if 0
  704. release_region(rport, 4);
  705. release_region(cport, 4);
  706. #endif
  707. return -ENODEV;
  708. }
  709. return 0;
  710. }
  711. }
  712. #endif // NO_PCI
  713. static int lpc_open(struct inode *inode, struct file *file)
  714. {
  715. int minor;
  716. // u32 cport;
  717. int idx;
  718. register DEV *dev;
  719. dbg1("%s(): MINOR=%d", __FUNCTION__, MINOR (inode->i_rdev));
  720. /*
  721. DbgFlush();
  722. struct timeval tv;
  723. do {
  724. do_gettimeofday(&tv);
  725. } while ( (tv.tv_sec % 10) != 0);
  726. */
  727. minor = iminor(inode);
  728. if( minor > MAX_DEVICES )
  729. {
  730. err("%s - invalid minor number %d", __FUNCTION__, minor);
  731. return -ENODEV;
  732. }
  733. dev = minor_table[minor];
  734. if( !dev )
  735. {
  736. err ("%s - error, can't find device for minor %d", __FUNCTION__, minor);
  737. return -ENODEV;
  738. }
  739. /* increment our usage count for the driver */
  740. if (++dev->open_count == 1)
  741. {
  742. dev->active = 1;
  743. if( minor < MAX_LPCS )
  744. {
  745. if( initialize_isacard(dev, minor) )
  746. {
  747. /* decrement our usage count for the device */
  748. --dev->open_count;
  749. return -ENODEV;
  750. }
  751. }
  752. else
  753. {
  754. #ifndef NO_PCI
  755. if( initialize_pcicard(dev, minor - MAX_LPCS) )
  756. #endif
  757. {
  758. /* decrement our usage count for the device */
  759. --dev->open_count;
  760. return -ENODEV;
  761. }
  762. }
  763. // dev->PciIntCount = dev->PciIntCountPlus = dev->PciIntCountMinus = 0;
  764. // dev->TimerCountPlus = dev->TimerCountMinus = 0;
  765. #if LINUX_VERSION_CODE < 0x020400
  766. dev->rd_wait = NULL;
  767. // dev->wr_wait = NULL;
  768. #else
  769. // #ifdef DECLARE_WAITQUEUE
  770. init_waitqueue_head(&dev->rd_wait);
  771. // dbg8("%s(): init_waitqueue_head()", __FUNCTION__);
  772. // init_waitqueue_head(&dev->wr_wait);
  773. // #endif
  774. #endif
  775. dev->inhead = dev->intail = 0;
  776. dev->outhead = dev->outtail = 0;
  777. dev->state = ST_RESYNC;
  778. dev->active = 0;
  779. dev->wtc_exist = 0;
  780. init_timer( &dev->drvtimer );
  781. dev->drvtimer.function = lpc_timer;
  782. dev->drvtimer.data = (unsigned long)dev;
  783. // cport = dev->cport;
  784. #if LINUX_VERSION_CODE < 0x020500
  785. MOD_INC_USE_COUNT;
  786. #endif
  787. dbg1("%s(): before sm_stub()", __FUNCTION__);
  788. sm_stub( dev ); // Start state machine
  789. #if 01
  790. #if 0
  791. dbg8("%s(): before interruptible_sleep_on()", __FUNCTION__);
  792. interruptible_sleep_on( &dev->rd_wait ); // and read 1st reset msg
  793. dbg8("%s(): after interruptible_sleep_on()", __FUNCTION__);
  794. idx = dev->inhead;
  795. #else
  796. idx = dev->inhead;
  797. // if (qempty(&dev->ReadBufferQueue))
  798. if (idx == dev->intail)
  799. {
  800. dbg1("%s(): qempty", __FUNCTION__);
  801. // up (&dev->sem);
  802. // if (wait_event_interruptible(dev->rd_wait, qhasdata(&dev->ReadBufferQueue)))
  803. if (wait_event_interruptible(dev->rd_wait, (idx != dev->intail) ))
  804. {
  805. /* decrement our usage count for the device */
  806. --dev->open_count;
  807. return -ERESTARTSYS; /* signal: tell the fs layer to handle it */
  808. }
  809. dbg8("%s(): nach wait_event_interruptible(rd_wait)", __FUNCTION__);
  810. // if (down_interruptible(&dev->sem))
  811. // return -ERESTARTSYS;
  812. }
  813. #endif
  814. idx++;
  815. if(idx >= NUM_INBUF) idx = 0;
  816. dev->inhead = idx;
  817. #endif
  818. }
  819. /* save our object in the file's private structure */
  820. file->private_data = dev;
  821. dbg1("%s(): return 0", __FUNCTION__);
  822. return 0;
  823. }
  824. static int lpc_release(struct inode *inode, struct file *file)
  825. {
  826. register DEV *dev = (DEV *)(file->private_data);
  827. if (dev == NULL)
  828. {
  829. dbg1("%s() dev=NULL", __FUNCTION__);
  830. return -ENODEV;
  831. }
  832. dbg1("%s(): minor=%d open_count=%d", __FUNCTION__, dev->minor, dev->open_count);
  833. /*
  834. dbg("PciIntCount=%5d PciIntCountPlus=%5d PciIntCountMinus=%5d"
  835. "\nTimerCountPlus=%5d TimerCountMinus=%5d",
  836. dev->PciIntCount, dev->PciIntCountPlus, dev->PciIntCountMinus,
  837. dev->TimerCountPlus, dev->TimerCountMinus);
  838. DbgFlush();
  839. */
  840. if (dev->open_count <= 0)
  841. {
  842. dbg1("%s() device not opened", __FUNCTION__);
  843. return -ENODEV;
  844. }
  845. /* decrement our usage count for the device */
  846. if (--dev->open_count <= 0)
  847. {
  848. u32 cport = dev->cport;
  849. dev->active = 1;
  850. dbg8("%s(): before del_timer()", __FUNCTION__);
  851. del_timer( &dev->drvtimer );
  852. free_irq(dev->irq, dev);
  853. dbg8("%s(): after free_irq()", __FUNCTION__);
  854. dev->ctl = 0x0D;
  855. SETCTL;
  856. if (dev->PlxIntCsrPort)
  857. {
  858. u16 IntCsr = inw(dev->PlxIntCsrPort);
  859. dbg1("? %s(): PlxIntCsrPort=%04X IntCsr=%04X", __FUNCTION__, dev->PlxIntCsrPort, IntCsr);
  860. IntCsr &= ~PLX_9050_INTR_ENABLE;
  861. outw(IntCsr, dev->PlxIntCsrPort);
  862. dbg1("? %s(): PlxIntCsrPort=%04X IntCsr=%04X", __FUNCTION__, dev->PlxIntCsrPort, IntCsr);
  863. // release_region(dev->cport, 4);
  864. // release_region(dev->rport, 4);
  865. }
  866. else
  867. {
  868. outw( 0, dev->rport );
  869. #ifndef CHECK_ISA_AT_LOAD_TIME
  870. release_region(cport-1, 4);
  871. #endif
  872. }
  873. // devs[minor] = NULL;
  874. // kfree( dev );
  875. dev->open_count = 0;
  876. }
  877. file->private_data = 0;
  878. #if LINUX_VERSION_CODE < 0x020500
  879. MOD_DEC_USE_COUNT;
  880. #endif
  881. dbg1("%s(): return 0", __FUNCTION__);
  882. // DbgFlush();
  883. return 0;
  884. }
  885. int lpc_watcher( DEV* dev, u8* buf )
  886. {
  887. u32 cport, wtcport;
  888. u8 *s, *d;
  889. s16 count, i;
  890. u8 xcvr, cmd, tmp;
  891. int t;
  892. dbg1("%s(): dev=%08X", __FUNCTION__, (uint)dev);
  893. cport = dev->cport;
  894. wtcport = dev->wtcport;
  895. s = d = buf;
  896. #if 01
  897. __get_user(count, s++); // Get the length
  898. __get_user(tmp, s++);
  899. count = (count << 8) + tmp;
  900. __get_user(cmd, s++);
  901. cmd &= 0x7F;
  902. #else
  903. count = *s++; // Get the length
  904. count = (count << 8) + *s++;
  905. cmd = *s++ & 0x7F;
  906. #endif
  907. if( cmd )
  908. { // Normal case: request watcher firmware
  909. if(!dev->wtc_exist) return -ENODEV;
  910. t = jiffies + HZ/2;
  911. WTCHS;
  912. WOUT((u8)(count >> 8)); // Send the length
  913. WTCHS;
  914. WOUT((u8)(count & 0xFF));
  915. WTCHS;
  916. WOUT(cmd);
  917. count--;
  918. while( count > 0 ) {
  919. WTCHS;
  920. #if 01
  921. __get_user(tmp, s++);
  922. WOUT(tmp); // Send the data bytes
  923. #else
  924. WOUT(*s++); // Send the data bytes
  925. #endif
  926. count--;
  927. }
  928. WTCHS;
  929. WOUT(0); // EOM
  930. WTCHS;
  931. count = WIN; // Receive the length
  932. #if 01
  933. __put_user(count & 0xFF, d++);
  934. WTCHS;
  935. count = (count << 8) + WIN;
  936. __put_user(count & 0xFF, d++);
  937. #else
  938. *d++ = count & 0xFF;
  939. WTCHS;
  940. count = (count << 8) + WIN;
  941. *d++ = count & 0xFF;
  942. #endif
  943. i = count;
  944. while( i > 0 ) {
  945. WTCHS;
  946. #if 01
  947. tmp = WIN;
  948. __put_user(tmp, d++);
  949. #else
  950. *d++ = WIN;
  951. #endif
  952. i--;
  953. }
  954. } else { // Special case: firmware download
  955. dev->ctl |= 0x02; // Reset LWA
  956. SETCTL;
  957. WIN; // Switch to Bootloader
  958. dev->ctl &= ~0x02; // Start LWA
  959. SETCTL;
  960. #if 01
  961. __get_user(xcvr, s++);
  962. #else
  963. xcvr = *s++;
  964. #endif
  965. count -=2;
  966. schedule();
  967. t = jiffies + HZ;
  968. while( count > 0 ) {
  969. WTCHS;
  970. #if 01
  971. __get_user(tmp, s++);
  972. WOUT(tmp); // Send the data bytes
  973. #else
  974. WOUT(*s++); // Send the data bytes
  975. #endif
  976. count--;
  977. }
  978. WTCHS;
  979. WOUT(0); // EOM
  980. WTCHS; // Wait until finished
  981. dev->ctl |= 0x02;
  982. SETCTL; // Reset LWA
  983. WOUT(xcvr); // Switch to Firmware
  984. dev->ctl &= ~0x02;
  985. SETCTL; // Start LWA
  986. t = HZ * 2; // Give the LWA some time to answer
  987. do {
  988. t--;
  989. if( !t ) return -ENODEV;
  990. schedule();
  991. }
  992. while(LPCSTAT & 2);
  993. #if 01
  994. __put_user(0, d++);
  995. __put_user(0, d++);
  996. #else
  997. *d++ = 0; // Acknowledge
  998. *d++ = 0;
  999. #endif
  1000. dev->wtc_exist = 1;
  1001. }
  1002. return d - buf;
  1003. }
  1004. static int lpc_ioctl(struct inode *inode, struct file *file,
  1005. unsigned int cmd, unsigned long arg)
  1006. {
  1007. int retval = -EINVAL;
  1008. register DEV *dev = (DEV *)(file->private_data);
  1009. char tmpBuf[80];
  1010. dbg1("%s(): dev=%08X", __FUNCTION__, (uint)dev);
  1011. switch( cmd )
  1012. {
  1013. case IOCTL_VERSION:
  1014. retval = sprintf(tmpBuf, DRIVER_DESC " " DRIVER_VERSION ", Linux %d.%d.%d",
  1015. (LINUX_VERSION_CODE >> 16) & 0xFF,
  1016. (LINUX_VERSION_CODE >> 8) & 0xFF,
  1017. LINUX_VERSION_CODE & 0xFF ) + 1;
  1018. if (copy_to_user ((char *)arg, tmpBuf, retval))
  1019. retval = -EFAULT;
  1020. break;
  1021. case IOCTL_WATCHER:
  1022. return lpc_watcher( dev, (u8 *)arg );
  1023. }
  1024. return retval;
  1025. }
  1026. int lpc_init( void )
  1027. {
  1028. int i;
  1029. u32 iobase, cport, rport;
  1030. int irq;
  1031. int rc = -ENODEV;
  1032. dbg1("%s():", __FUNCTION__);
  1033. for( i=0; i<MAX_LPCS; i++ )
  1034. {
  1035. if( !lpcs[i] ) continue;
  1036. iobase = lpcs[i] & 0x0FFF;
  1037. irq = lpcs[i] >> 12;
  1038. cport = iobase+1;
  1039. rport = iobase+2;
  1040. dbg1("lpc[%2d]: iobase=%04X irq=%X", i, iobase, irq);
  1041. #ifdef CHECK_ISA_AT_LOAD_TIME
  1042. if( ((u8)irq > 15) || !irq_table[irq] ) {
  1043. err( "IRQ%d not supported\n", irq );
  1044. lpcs[i] = 0;
  1045. continue;
  1046. }
  1047. if (!request_region( iobase, 4, DRIVER_DEV_NAME ))
  1048. // if( check_region(iobase, 4) )
  1049. {
  1050. err("unable to register port 0x%X", iobase);
  1051. lpcs[i] = 0;
  1052. continue;
  1053. }
  1054. {
  1055. int hwfail = 0;
  1056. outb(0x5F, cport);
  1057. outb(0, rport);
  1058. outb(0, rport);
  1059. outb(0, rport);
  1060. if( (inb(cport) & 0xF0) != 0x50 ) hwfail = 1;
  1061. outb(0x0F, cport);
  1062. outb(0, rport);
  1063. outb(0, rport);
  1064. outb(0, rport);
  1065. if( inb(cport) & 0xF0 ) hwfail = 1;
  1066. if( hwfail )
  1067. {
  1068. err( "interface card not responding at port 0x%04X", iobase );
  1069. lpcs[i] = 0;
  1070. release_region( iobase, 4);
  1071. continue;
  1072. }
  1073. // request_region( iobase, 4, DRIVER_DEV_NAME );
  1074. }
  1075. #endif
  1076. {
  1077. DEV *dev = NULL;
  1078. uint minor;
  1079. /* select a "subminor" number (part of a minor number) */
  1080. down (&minor_table_mutex);
  1081. for (minor = 0; minor < MAX_LPCS; ++minor)
  1082. {
  1083. if (minor_table[minor] == NULL)
  1084. break;
  1085. }
  1086. if (minor >= MAX_LPCS)
  1087. {
  1088. info ("Too many devices plugged in, can not handle this device.");
  1089. rc = -EINVAL;
  1090. goto err_minor_table;
  1091. }
  1092. dev = kmalloc (sizeof(DEV), GFP_KERNEL);
  1093. if (!dev)
  1094. {
  1095. up (&minor_table_mutex);
  1096. #ifdef CHECK_ISA_AT_LOAD_TIME
  1097. release_region( iobase, 4);
  1098. #endif
  1099. return -ENOMEM;
  1100. }
  1101. memset (dev, 0x00, sizeof (*dev));
  1102. dev->cport = iobase+1;
  1103. dev->rport = iobase+2;
  1104. dev->wport = iobase+3;
  1105. dev->wtcport = iobase+0;
  1106. dev->irq = irq;
  1107. dev->PlxIntCsrPort = 0;
  1108. dev->minor = minor;
  1109. minor_table[minor] = dev;
  1110. up (&minor_table_mutex);
  1111. rc = 0; // found on or more devices
  1112. }
  1113. }
  1114. return rc;
  1115. err_minor_table:
  1116. up (&minor_table_mutex);
  1117. #ifdef CHECK_ISA_AT_LOAD_TIME
  1118. release_region( iobase, 4);
  1119. #endif
  1120. return rc;
  1121. }
  1122. #include "driverentry.c"