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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Rocketport device driver for Linux
  3.  *
  4.  * Written by Theodore Ts'o, 1995, 1996, 1997.
  5.  * 
  6.  * Copyright (C) 1995, 1996, 1997 by Comtrol, Inc.
  7.  * 
  8.  * This program is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU General Public License as
  10.  * published by the Free Software Foundation; either version 2 of the
  11.  * License, or (at your option) any later version.
  12.  * 
  13.  * This program is distributed in the hope that it will be useful, but
  14.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * General Public License for more details.
  17.  * 
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22. /*
  23.  * Minor number schema:
  24.  *
  25.  * +-------------------------------+
  26.  * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
  27.  * +---+-------+-------+-----------+
  28.  * | C | Board |  AIOP | Port #    |
  29.  * +---+-------+-------+-----------+
  30.  *
  31.  * C=0 implements normal POSIX tty.
  32.  * C=1 is reserved for the callout device.
  33.  * 
  34.  * Normally, the user won't have to worry about the AIOP; as far as
  35.  * the user is concerned, the lower 5 bits of the minor number address
  36.  * the ports on a particular board (from 0 up to 32).
  37.  */
  38. /* Kernel includes */
  39. #include <linux/config.h>
  40. #include <linux/version.h>
  41. #ifdef CONFIG_PCI
  42. #define ENABLE_PCI
  43. #endif
  44. #include <linux/module.h>
  45. #include <linux/errno.h>
  46. #include <linux/major.h>
  47. #include <linux/kernel.h>
  48. #include <linux/signal.h>
  49. #include <linux/slab.h>
  50. #include <linux/mm.h>
  51. #include <linux/sched.h>
  52. #include <linux/timer.h>
  53. #include <linux/interrupt.h>
  54. #include <linux/tty.h>
  55. #include <linux/tty_flip.h>
  56. #include <linux/string.h>
  57. #include <linux/fcntl.h>
  58. #include <linux/ptrace.h>
  59. #include <linux/ioport.h>
  60. #ifdef ENABLE_PCI
  61. #include <linux/pci.h>
  62. #if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
  63. #include <linux/bios32.h>
  64. #endif
  65. #endif
  66. #if (LINUX_VERSION_CODE >= 131343) /* 2.1.15 -- XX get correct version */
  67. #include <linux/init.h>
  68. #endif
  69. #include "rocket_int.h"
  70. #ifdef LOCAL_ROCKET_H
  71. #include "rocket.h"
  72. #include "version.h"
  73. #else
  74. #include <linux/rocket.h>
  75. #define ROCKET_VERSION "1.14c"
  76. #define ROCKET_DATE "24-Aug-98"
  77. #endif /* LOCAL_ROCKET_H */
  78. #define ROCKET_PARANOIA_CHECK
  79. #define ROCKET_SOFT_FLOW
  80. #undef ROCKET_DEBUG_OPEN
  81. #undef ROCKET_DEBUG_INTR
  82. #undef ROCKET_DEBUG_WRITE
  83. #undef ROCKET_DEBUG_FLOW
  84. #undef ROCKET_DEBUG_THROTTLE
  85. #undef ROCKET_DEBUG_WAIT_UNTIL_SENT
  86. #undef ROCKET_DEBUG_RECEIVE
  87. #undef ROCKET_DEBUG_HANGUP
  88. /*   CAUTION!!!!!  The TIME_STAT Function relies on the Pentium 64 bit
  89.  *    register.  For various reasons related to 1.2.13, the test for this
  90.  *    register is omitted from this driver.  If you are going to enable
  91.  *    this option, make sure you are running a Pentium CPU and that a
  92.  *    cat of /proc/cpuinfo shows ability TS Counters as Yes.  Warning part
  93.  *    done, don't cry to me if you enable this options and things won't
  94.  *    work.  If it gives you any problems, then disable the option.  The code
  95.  *    in this function is pretty straight forward, if it breaks on your
  96.  *    CPU, there is probably something funny about your CPU.
  97.  */
  98. #undef TIME_STAT /* For performing timing statistics on driver. */
  99. /* Produces printks, one every TIME_COUNTER loops, eats */
  100. /* some of your CPU time.  Good for testing or */
  101. /* other checking, otherwise, leave it undefed */
  102. /* Doug Ledford */
  103. #define TIME_STAT_CPU 100      /* This needs to be set to your processor speed */
  104.                                /* For example, 100Mhz CPU, set this to 100 */
  105. #define TIME_COUNTER 180000    /* This is how many iterations to run before */
  106.       /* performing the printk statements.   */
  107.       /* 6000 = 1 minute, 360000 = 1 hour, etc. */
  108.       /* Since time_stat is long long, this */
  109.       /* Can be really high if you want :)  */
  110. #undef TIME_STAT_VERBOSE   /* Undef this if you want a terse log message. */
  111. #define _INLINE_ inline
  112. static struct r_port *rp_table[MAX_RP_PORTS];
  113. static struct tty_struct *rocket_table[MAX_RP_PORTS];
  114. static unsigned int xmit_flags[NUM_BOARDS];
  115. static struct termios *rocket_termios[MAX_RP_PORTS];
  116. static struct termios *rocket_termios_locked[MAX_RP_PORTS];
  117. static void rp_wait_until_sent(struct tty_struct *tty, int timeout);
  118. static void rp_flush_buffer(struct tty_struct *tty);
  119. static struct tty_driver rocket_driver, callout_driver;
  120. static int rocket_refcount;
  121. static int rp_num_ports_open;
  122. static struct timer_list rocket_timer;
  123. unsigned long board1;
  124. unsigned long board2;
  125. unsigned long board3;
  126. unsigned long board4;
  127. unsigned long controller;
  128. unsigned long support_low_speed;
  129. int rp_baud_base = 460800;
  130. static unsigned long rcktpt_io_addr[NUM_BOARDS];
  131. static int max_board;
  132. #ifdef TIME_STAT
  133. static unsigned long long time_stat;
  134. static unsigned long time_stat_short;
  135. static unsigned long time_stat_long;
  136. static unsigned long time_counter;
  137. #endif
  138. #if ((LINUX_VERSION_CODE > 0x020111) && defined(MODULE))
  139. MODULE_AUTHOR("Theodore Ts'o");
  140. MODULE_DESCRIPTION("Comtrol Rocketport driver");
  141. MODULE_LICENSE("GPL");
  142. MODULE_PARM(board1,     "i");
  143. MODULE_PARM_DESC(board1, "I/O port for (ISA) board #1");
  144. MODULE_PARM(board2,     "i");
  145. MODULE_PARM_DESC(board2, "I/O port for (ISA) board #2");
  146. MODULE_PARM(board3,     "i");
  147. MODULE_PARM_DESC(board3, "I/O port for (ISA) board #3");
  148. MODULE_PARM(board4,     "i");
  149. MODULE_PARM_DESC(board4, "I/O port for (ISA) board #4");
  150. MODULE_PARM(controller, "i");
  151. MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller");
  152. MODULE_PARM(support_low_speed, "i");
  153. MODULE_PARM_DESC(support_low_speed, "0 means support 50 baud, 1 means support 460400 baud");
  154. #endif
  155. #if (LINUX_VERSION_CODE < 131336)
  156. int copy_from_user(void *to, const void *from_user, unsigned long len)
  157. {
  158. int error;
  159. error = verify_area(VERIFY_READ, from_user, len);
  160. if (error)
  161. return len;
  162. memcpy_fromfs(to, from_user, len);
  163. return 0;
  164. }
  165. int copy_to_user(void *to_user, const void *from, unsigned long len)
  166. {
  167. int error;
  168. error = verify_area(VERIFY_WRITE, to_user, len);
  169. if (error)
  170. return len;
  171. memcpy_tofs(to_user, from, len);
  172. return 0;
  173. }
  174. static inline int signal_pending(struct task_struct *p)
  175. {
  176. return (p->signal & ~p->blocked) != 0;
  177. }
  178. #else
  179. #include <asm/uaccess.h>
  180. #endif
  181. /*
  182.  * tmp_buf is used as a temporary buffer by rp_write.  We need to
  183.  * lock it in case the memcpy_fromfs blocks while swapping in a page,
  184.  * and some other program tries to do a serial write at the same time.
  185.  * Since the lock will only come under contention when the system is
  186.  * swapping and available memory is low, it makes sense to share one
  187.  * buffer across all the serial ports, since it significantly saves
  188.  * memory if large numbers of serial ports are open.
  189.  */
  190. static unsigned char *tmp_buf = 0;
  191. static DECLARE_MUTEX(tmp_buf_sem);
  192. static void rp_start(struct tty_struct *tty);
  193. static inline int rocket_paranoia_check(struct r_port *info,
  194. kdev_t device, const char *routine)
  195. {
  196. #ifdef ROCKET_PARANOIA_CHECK
  197. static const char *badmagic =
  198. "Warning: bad magic number for rocketport struct (%d, %d) in %sn";
  199. if (!info)
  200. return 1;
  201. if (info->magic != RPORT_MAGIC) {
  202. printk(badmagic, MAJOR(device), MINOR(device), routine);
  203. return 1;
  204. }
  205. #endif
  206. return 0;
  207. }
  208. /*
  209.  * Here begins the interrupt/polling routine for the Rocketport!
  210.  */
  211. static _INLINE_ void rp_do_receive(struct r_port *info, struct tty_struct *tty,
  212.    CHANNEL_t *cp, unsigned int ChanStatus)
  213. {
  214. unsigned int CharNStat;
  215. int ToRecv, wRecv, space, count;
  216. unsigned char *cbuf;
  217. char *fbuf;
  218. ToRecv= sGetRxCnt(cp);
  219. space = 2*TTY_FLIPBUF_SIZE;
  220. cbuf = tty->flip.char_buf;
  221. fbuf = tty->flip.flag_buf;
  222. count = 0;
  223. #ifdef ROCKET_DEBUG_INTR
  224. printk("rp_do_receive(%d, %d)...", ToRecv, space);
  225. #endif
  226. if (ToRecv == 0 || (space <= 0))
  227. return;
  228. /*
  229.  * determine how many we can actually read in.  If we can't
  230.  * read any in then we have a software overrun condition.
  231.  */
  232. if (ToRecv > space)
  233. ToRecv = space;
  234. /*
  235.  * if status indicates there are errored characters in the
  236.  * FIFO, then enter status mode (a word in FIFO holds
  237.  * character and status).
  238.  */
  239. if (ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
  240. if (!(ChanStatus & STATMODE)) {
  241. #ifdef ROCKET_DEBUG_RECEIVE
  242. printk("Entering STATMODE...");
  243. #endif
  244. ChanStatus |= STATMODE;
  245. sEnRxStatusMode(cp);
  246. }
  247. }
  248. /* 
  249.  * if we previously entered status mode, then read down the
  250.  * FIFO one word at a time, pulling apart the character and
  251.  * the status.  Update error counters depending on status
  252.  */
  253. if (ChanStatus & STATMODE) {
  254. #ifdef ROCKET_DEBUG_RECEIVE
  255. printk("Ignore %x, read %x...", info->ignore_status_mask,
  256.        info->read_status_mask);
  257. #endif
  258. while (ToRecv) {
  259. CharNStat= sInW(sGetTxRxDataIO(cp));
  260. #ifdef ROCKET_DEBUG_RECEIVE
  261. printk("%x...", CharNStat);
  262. #endif
  263. if (CharNStat & STMBREAKH)
  264. CharNStat &= ~(STMFRAMEH | STMPARITYH);
  265. if (CharNStat & info->ignore_status_mask) {
  266. ToRecv--;
  267. continue;
  268. }
  269. CharNStat &= info->read_status_mask;
  270. if (CharNStat & STMBREAKH) {
  271. *fbuf++ = TTY_BREAK;
  272. #if 0
  273. if (info->flags & ROCKET_SAK)
  274. do_SAK(tty);
  275. #endif
  276. } else if (CharNStat & STMPARITYH)
  277. *fbuf++ = TTY_PARITY;
  278. else if (CharNStat & STMFRAMEH)
  279. *fbuf++ = TTY_FRAME;
  280. else if (CharNStat & STMRCVROVRH)
  281. *fbuf++ =TTY_OVERRUN;
  282. else
  283. *fbuf++ = 0;
  284. *cbuf++ = CharNStat & 0xff;
  285. count++;
  286. ToRecv--;
  287. }
  288. /*
  289.  * after we've emptied the FIFO in status mode, turn
  290.  * status mode back off
  291.  */
  292. if (sGetRxCnt(cp) == 0) {
  293. #ifdef ROCKET_DEBUG_RECEIVE
  294. printk("Status mode off.n");
  295. #endif
  296. sDisRxStatusMode(cp);
  297. }
  298. } else {
  299. /*
  300.  * we aren't in status mode, so read down the FIFO two
  301.  * characters at time by doing repeated word IO
  302.  * transfer.
  303.  */
  304. wRecv= ToRecv >> 1;
  305. if (wRecv)
  306. sInStrW(sGetTxRxDataIO(cp), cbuf,
  307. wRecv);
  308. if (ToRecv & 1)
  309. cbuf[ToRecv-1] = sInB(sGetTxRxDataIO(cp));
  310. memset(fbuf, 0, ToRecv);
  311. cbuf += ToRecv;
  312. fbuf += ToRecv;
  313. count += ToRecv;
  314. }
  315. tty->ldisc.receive_buf(tty, tty->flip.char_buf,
  316.        tty->flip.flag_buf, count);
  317. }
  318. /*
  319.  * This routine is called when a transmit interrupt is found.  It's
  320.  * responsible for pushing data found in the transmit buffer out to
  321.  * the serial card.
  322.  */
  323. static _INLINE_ void rp_do_transmit(struct r_port *info)
  324. {
  325. int c;
  326. CHANNEL_t *cp = &info->channel;
  327. struct tty_struct *tty;
  328. #ifdef ROCKET_DEBUG_INTR
  329. printk("rp_do_transmit ");
  330. #endif
  331. if (!info)
  332. return;
  333. if (!info->tty) {
  334. printk("rp: WARNING rp_do_transmit called with info->tty==NULLn");
  335. xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
  336. return;
  337. }
  338. tty = info->tty;
  339. info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
  340. while (1) {
  341. if (tty->stopped || tty->hw_stopped)
  342. break;
  343. c = MIN(info->xmit_fifo_room,
  344. MIN(info->xmit_cnt,
  345.     XMIT_BUF_SIZE - info->xmit_tail));
  346. if (c <= 0 || info->xmit_fifo_room <= 0)
  347. break;
  348. sOutStrW(sGetTxRxDataIO(cp),
  349.  info->xmit_buf + info->xmit_tail, c/2);
  350. if (c & 1)
  351. sOutB(sGetTxRxDataIO(cp),
  352.       info->xmit_buf[info->xmit_tail + c -
  353.      1]);
  354. info->xmit_tail += c;
  355. info->xmit_tail &= XMIT_BUF_SIZE-1;
  356. info->xmit_cnt -= c;
  357. info->xmit_fifo_room -= c;
  358. #ifdef ROCKET_DEBUG_INTR
  359. printk("tx %d chars...", c);
  360. #endif
  361. }
  362. if (info->xmit_cnt == 0)
  363. xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
  364. if (info->xmit_cnt < WAKEUP_CHARS) {
  365. if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
  366.     tty->ldisc.write_wakeup)
  367. (tty->ldisc.write_wakeup)(tty);
  368. wake_up_interruptible(&tty->write_wait);
  369. }
  370. #ifdef ROCKET_DEBUG_INTR
  371. printk("(%d,%d,%d,%d)...", info->xmit_cnt, info->xmit_head,
  372.        info->xmit_tail, info->xmit_fifo_room);
  373. #endif
  374. }
  375. /*
  376.  * This function is called for each port which has signalled an
  377.  * interrupt.  It checks what interrupts are pending and services
  378.  * them. 
  379.  */
  380. static _INLINE_ void rp_handle_port(struct r_port *info)
  381. {
  382. CHANNEL_t *cp;
  383. struct tty_struct *tty;
  384. unsigned int IntMask, ChanStatus;
  385. if (!info)
  386. return;
  387. if ( (info->flags & ROCKET_INITIALIZED) == 0 ) {
  388. printk("rp: WARNING: rp_handle_port called with info->flags & NOT_INITn");
  389. return;
  390. }
  391. if (!info->tty) {
  392. printk("rp: WARNING: rp_handle_port called with info->tty==NULLn");
  393. return;
  394. }
  395. cp = &info->channel;
  396. tty = info->tty;
  397. IntMask = sGetChanIntID(cp) & info->intmask;
  398. #ifdef ROCKET_DEBUG_INTR
  399. printk("rp_interrupt %02x...", IntMask);
  400. #endif
  401. ChanStatus= sGetChanStatus(cp);
  402. if (IntMask & RXF_TRIG) { /* Rx FIFO trigger level */
  403. rp_do_receive(info, tty, cp, ChanStatus);
  404. }
  405. #if 0
  406. if (IntMask & SRC_INT) { /* Special receive condition */
  407. }
  408. #endif
  409. if (IntMask & DELTA_CD) { /* CD change  */
  410. #if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_INTR) || 
  411.      defined(ROCKET_DEBUG_HANGUP))
  412. printk("ttyR%d CD now %s...", info->line,
  413.        (ChanStatus & CD_ACT) ? "on" : "off");
  414. #endif
  415. if (!(ChanStatus & CD_ACT) &&
  416.     info->cd_status &&
  417.     !((info->flags & ROCKET_CALLOUT_ACTIVE) &&
  418.       (info->flags & ROCKET_CALLOUT_NOHUP))) {
  419. #ifdef ROCKET_DEBUG_HANGUP
  420. printk("CD drop, calling hangup.n");
  421. #endif
  422. tty_hangup(tty);
  423. }
  424. info->cd_status = (ChanStatus & CD_ACT) ? 1 : 0;
  425. wake_up_interruptible(&info->open_wait);
  426. }
  427. #ifdef ROCKET_DEBUG_INTR
  428. if (IntMask & DELTA_CTS) { /* CTS change */
  429. printk("CTS change...n");
  430. }
  431. if (IntMask & DELTA_DSR) { /* DSR change */
  432. printk("DSR change...n");
  433. }
  434. #endif
  435. }
  436. /*
  437.  * The top level polling routine.
  438.  */
  439. static void rp_do_poll(unsigned long dummy)
  440. {
  441. CONTROLLER_t *ctlp;
  442. int ctrl, aiop, ch, line;
  443. unsigned int xmitmask;
  444. unsigned char CtlMask, AiopMask;
  445. #ifdef TIME_STAT
  446. unsigned long loop_time;
  447. unsigned long long time_stat_tmp=0, time_stat_tmp2=0;
  448. rdtscll(time_stat_tmp);
  449. #endif /* TIME_STAT */
  450. for (ctrl=0; ctrl < max_board; ctrl++) {
  451. if (rcktpt_io_addr[ctrl] <= 0)
  452. continue;
  453. ctlp= sCtlNumToCtlPtr(ctrl);
  454. #ifdef ENABLE_PCI
  455. if(ctlp->BusType == isPCI)
  456. CtlMask= sPCIGetControllerIntStatus(ctlp);
  457. else
  458. #endif
  459. CtlMask= sGetControllerIntStatus(ctlp);
  460. for (aiop=0; CtlMask; CtlMask >>= 1, aiop++) {
  461. if (CtlMask & 1) {
  462. AiopMask= sGetAiopIntStatus(ctlp, aiop);
  463. for (ch=0; AiopMask; AiopMask >>= 1, ch++) {
  464. if (AiopMask & 1) {
  465. line = (ctrl << 5) | 
  466. (aiop << 3) | ch;
  467. rp_handle_port(rp_table[line]);
  468. }
  469. }
  470. }
  471. }
  472. xmitmask = xmit_flags[ctrl];
  473. for (line = ctrl << 5; xmitmask; xmitmask >>= 1, line++) {
  474. if (xmitmask & 1)
  475. rp_do_transmit(rp_table[line]);
  476. }
  477. }
  478. /*
  479.  * Reset the timer so we get called at the next clock tick.
  480.  */
  481. if (rp_num_ports_open) {
  482. mod_timer(&rocket_timer, jiffies + 1);
  483. }
  484. #ifdef TIME_STAT
  485. rdtscll(time_stat_tmp2);
  486. time_stat_tmp2 -= time_stat_tmp;
  487. time_stat += time_stat_tmp2;
  488. if (time_counter == 0) 
  489. time_stat_short = time_stat_long = time_stat_tmp2;
  490. else {
  491. if ( time_stat_tmp2 < time_stat_short )
  492. time_stat_short = time_stat_tmp2;
  493. else if ( time_stat_tmp2 > time_stat_long )
  494. time_stat_long = time_stat_tmp2;
  495. }
  496. if ( ++time_counter == TIME_COUNTER ) {
  497. loop_time = (unsigned long) ( ((unsigned long)(time_stat >> 32) * ( (unsigned long)(0xffffffff)/(TIME_STAT_CPU * TIME_COUNTER) ) ) + ((unsigned long)time_stat/(TIME_STAT_CPU*TIME_COUNTER)));
  498. #ifdef TIME_STAT_VERBOSE
  499. printk("rp_do_poll: Interrupt Timingsn");
  500. printk("     %5ld iterations; %ld us min,n",
  501.        (long)TIME_COUNTER, (time_stat_short/TIME_STAT_CPU));
  502. printk("     %5ld us max, %ld us average per iteration.n",
  503.        (time_stat_long/TIME_STAT_CPU), loop_time);
  504. printk("We want to use < 5,000 us for an iteration.n");
  505. #else /* TIME_STAT_VERBOSE */
  506. printk("rp: %ld loops: %ld min, %ld max, %ld us/loop.n",
  507.        (long)TIME_COUNTER, (time_stat_short/TIME_STAT_CPU),
  508.        (time_stat_long/TIME_STAT_CPU), loop_time);
  509. #endif /* TIME_STAT_VERBOSE */
  510. time_counter = time_stat = 0;
  511. time_stat_short = time_stat_long = 0;
  512. }
  513. #endif /* TIME_STAT */
  514. }
  515. /*
  516.  * Here ends the interrupt/polling routine.
  517.  */
  518. /*
  519.  * This function initializes the r_port structure, as well as enabling
  520.  * the port on the RocketPort board.
  521.  */
  522. static void init_r_port(int board, int aiop, int chan)
  523. {
  524. struct r_port *info;
  525. int line;
  526. CONTROLLER_T *ctlp;
  527. CHANNEL_t *cp;
  528. line = (board << 5) | (aiop << 3) | chan;
  529. ctlp= sCtlNumToCtlPtr(board);
  530. info = kmalloc(sizeof(struct r_port), GFP_KERNEL);
  531. if (!info) {
  532. printk("Couldn't allocate info struct for line #%dn", line);
  533. return;
  534. }
  535. memset(info, 0, sizeof(struct r_port));
  536. info->magic = RPORT_MAGIC;
  537. info->line = line;
  538. info->ctlp = ctlp;
  539. info->board = board;
  540. info->aiop = aiop;
  541. info->chan = chan;
  542. info->closing_wait = 3000;
  543. info->close_delay = 50;
  544. info->callout_termios =callout_driver.init_termios;
  545. info->normal_termios = rocket_driver.init_termios;
  546. init_waitqueue_head(&info->open_wait);
  547. init_waitqueue_head(&info->close_wait);
  548. info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD |
  549. DELTA_CTS | DELTA_DSR;
  550. if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
  551. printk("Rocketport sInitChan(%d, %d, %d) failed!n",
  552.        board, aiop, chan);
  553. kfree(info);
  554. return;
  555. }
  556. cp = &info->channel;
  557. rp_table[line] = info;
  558. }
  559. #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
  560. static int baud_table[] = {
  561. 0, 50, 75, 110, 134, 150, 200, 300,
  562. 600, 1200, 1800, 2400, 4800, 9600, 19200,
  563. 38400, 57600, 115200, 230400, 460800, 0 };
  564. #endif
  565. /*
  566.  * This routine configures a rocketport port so according to its
  567.  * termio settings.
  568.  */
  569. static void configure_r_port(struct r_port *info)
  570. {
  571. unsigned cflag;
  572. unsigned long  flags;
  573. int bits, baud;
  574. #if (LINUX_VERSION_CODE < 131393) /* Linux 2.1.65 */
  575. int i;
  576. #endif
  577. CHANNEL_t *cp;
  578. if (!info->tty || !info->tty->termios)
  579. return;
  580. cp = &info->channel;
  581. cflag = info->tty->termios->c_cflag;
  582. /* Byte size and parity */
  583. if ((cflag & CSIZE) == CS8) {
  584. sSetData8(cp);
  585. bits = 10;
  586. } else {
  587. sSetData7(cp);
  588. bits = 9;
  589. }
  590.         if (cflag & CSTOPB) {
  591. sSetStop2(cp);
  592. bits++;
  593. } else {
  594. sSetStop1(cp);
  595. }
  596. if (cflag & PARENB) {
  597. sEnParity(cp);
  598. bits++;
  599. if (cflag & PARODD) {
  600. sSetOddParity(cp);
  601. } else {
  602. sSetEvenParity(cp);
  603. }
  604. } else {
  605. sDisParity(cp);
  606. }
  607. /* baud rate */
  608. #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
  609. i = cflag & CBAUD;
  610. if (i & CBAUDEX) {
  611. i &= ~CBAUDEX;
  612. if (i < 1 || i > 4) 
  613. info->tty->termios->c_cflag &= ~CBAUDEX;
  614. else
  615. i += 15;
  616. }
  617. if (i == 15) {
  618. if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
  619. i += 1;
  620. if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
  621. i += 2;
  622. if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
  623. i += 3;
  624. if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
  625. i += 4;
  626. }
  627. baud = baud_table[i] ? baud_table[i] : 9600;
  628. #else
  629. baud = tty_get_baud_rate(info->tty);
  630. if (!baud)
  631. baud = 9600;
  632. #endif
  633. info->cps = baud / bits;
  634. sSetBaud(cp, (rp_baud_base/baud) - 1);
  635. if (cflag & CRTSCTS) {
  636. info->intmask |= DELTA_CTS;
  637. sEnCTSFlowCtl(cp);
  638. } else {
  639. info->intmask &= ~DELTA_CTS;
  640. sDisCTSFlowCtl(cp);
  641. }
  642. sSetRTS(&info->channel);
  643. if (cflag & CLOCAL)
  644. info->intmask &= ~DELTA_CD;
  645. else {
  646. save_flags(flags); cli();
  647. if (sGetChanStatus(cp) & CD_ACT)
  648. info->cd_status = 1;
  649. else
  650. info->cd_status = 0;
  651. info->intmask |= DELTA_CD;
  652. restore_flags(flags);
  653. }
  654. /*
  655.  * Handle software flow control in the board
  656.  */
  657. #ifdef ROCKET_SOFT_FLOW
  658. if (I_IXON(info->tty)) {
  659. sEnTxSoftFlowCtl(cp);
  660. if (I_IXANY(info->tty)) {
  661. sEnIXANY(cp);
  662. } else {
  663. sDisIXANY(cp);
  664. }
  665. sSetTxXONChar(cp, START_CHAR(info->tty));
  666. sSetTxXOFFChar(cp, STOP_CHAR(info->tty));
  667. } else {
  668. sDisTxSoftFlowCtl(cp);
  669. sDisIXANY(cp);
  670. sClrTxXOFF(cp);
  671. }
  672. #endif
  673. /*
  674.  * Set up ignore/read mask words
  675.  */
  676. info->read_status_mask = STMRCVROVRH | 0xFF;
  677. if (I_INPCK(info->tty))
  678. info->read_status_mask |= STMFRAMEH | STMPARITYH;
  679. if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
  680. info->read_status_mask |= STMBREAKH;
  681. /*
  682.  * Characters to ignore
  683.  */
  684. info->ignore_status_mask = 0;
  685. if (I_IGNPAR(info->tty))
  686. info->ignore_status_mask |= STMFRAMEH | STMPARITYH;
  687. if (I_IGNBRK(info->tty)) {
  688. info->ignore_status_mask |= STMBREAKH;
  689. /*
  690.  * If we're ignoring parity and break indicators,
  691.  * ignore overruns too.  (For real raw support).
  692.  */
  693. if (I_IGNPAR(info->tty))
  694. info->ignore_status_mask |= STMRCVROVRH;
  695. }
  696. }
  697. static int block_til_ready(struct tty_struct *tty, struct file * filp,
  698.    struct r_port *info)
  699. {
  700. DECLARE_WAITQUEUE(wait, current);
  701. int retval;
  702. int do_clocal = 0, extra_count = 0;
  703. unsigned long flags;
  704. /*
  705.  * If the device is in the middle of being closed, then block
  706.  * until it's done, and then try again.
  707.  */
  708. if (tty_hung_up_p(filp))
  709. return ((info->flags & ROCKET_HUP_NOTIFY) ? 
  710. -EAGAIN : -ERESTARTSYS);
  711. if (info->flags & ROCKET_CLOSING) {
  712. interruptible_sleep_on(&info->close_wait);
  713. return ((info->flags & ROCKET_HUP_NOTIFY) ? 
  714. -EAGAIN : -ERESTARTSYS);
  715. }
  716. /*
  717.  * If this is a callout device, then just make sure the normal
  718.  * device isn't being used.
  719.  */
  720. if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
  721. if (info->flags & ROCKET_NORMAL_ACTIVE)
  722. return -EBUSY;
  723. if ((info->flags & ROCKET_CALLOUT_ACTIVE) &&
  724.     (info->flags & ROCKET_SESSION_LOCKOUT) &&
  725.     (info->session != current->session))
  726.     return -EBUSY;
  727. if ((info->flags & ROCKET_CALLOUT_ACTIVE) &&
  728.     (info->flags & ROCKET_PGRP_LOCKOUT) &&
  729.     (info->pgrp != current->pgrp))
  730.     return -EBUSY;
  731. info->flags |= ROCKET_CALLOUT_ACTIVE;
  732. return 0;
  733. }
  734. /*
  735.  * If non-blocking mode is set, or the port is not enabled,
  736.  * then make the check up front and then exit.
  737.  */
  738. if ((filp->f_flags & O_NONBLOCK) ||
  739.     (tty->flags & (1 << TTY_IO_ERROR))) {
  740. if (info->flags & ROCKET_CALLOUT_ACTIVE)
  741. return -EBUSY;
  742. info->flags |= ROCKET_NORMAL_ACTIVE;
  743. return 0;
  744. }
  745. if (info->flags & ROCKET_CALLOUT_ACTIVE) {
  746. if (info->normal_termios.c_cflag & CLOCAL)
  747. do_clocal = 1;
  748. } else {
  749. if (tty->termios->c_cflag & CLOCAL)
  750. do_clocal = 1;
  751. }
  752. /*
  753.  * Block waiting for the carrier detect and the line to become
  754.  * free (i.e., not in use by the callout).  While we are in
  755.  * this loop, info->count is dropped by one, so that
  756.  * rp_close() knows when to free things.  We restore it upon
  757.  * exit, either normal or abnormal.
  758.  */
  759. retval = 0;
  760. add_wait_queue(&info->open_wait, &wait);
  761. #ifdef ROCKET_DEBUG_OPEN
  762. printk("block_til_ready before block: ttyR%d, count = %dn",
  763.        info->line, info->count);
  764. #endif
  765. save_flags(flags); cli();
  766. if (!tty_hung_up_p(filp)) {
  767. extra_count = 1;
  768. info->count--;
  769. }
  770. restore_flags(flags);
  771. info->blocked_open++;
  772. while (1) {
  773. if (!(info->flags & ROCKET_CALLOUT_ACTIVE) &&
  774.     (tty->termios->c_cflag & CBAUD)) {
  775. sSetDTR(&info->channel);
  776. sSetRTS(&info->channel);
  777. }
  778. set_current_state(TASK_INTERRUPTIBLE);
  779. if (tty_hung_up_p(filp) ||
  780.     !(info->flags & ROCKET_INITIALIZED)) {
  781. if (info->flags & ROCKET_HUP_NOTIFY)
  782. retval = -EAGAIN;
  783. else
  784. retval = -ERESTARTSYS;
  785. break;
  786. }
  787. if (!(info->flags & ROCKET_CALLOUT_ACTIVE) &&
  788.     !(info->flags & ROCKET_CLOSING) &&
  789.     (do_clocal || (sGetChanStatusLo(&info->channel) &
  790.    CD_ACT)))
  791. break;
  792. if (signal_pending(current)) {
  793. retval = -ERESTARTSYS;
  794. break;
  795. }
  796. #ifdef ROCKET_DEBUG_OPEN
  797. printk("block_til_ready blocking: ttyR%d, count = %d, flags=0x%0xn",
  798.        info->line, info->count, info->flags);
  799. #endif
  800. schedule();
  801. }
  802. current->state = TASK_RUNNING;
  803. remove_wait_queue(&info->open_wait, &wait);
  804. cli();
  805. if (extra_count)
  806. info->count++;
  807. restore_flags(flags);
  808. info->blocked_open--;
  809. #ifdef ROCKET_DEBUG_OPEN
  810. printk("block_til_ready after blocking: ttyR%d, count = %dn",
  811.        info->line, info->count);
  812. #endif
  813. if (retval)
  814. return retval;
  815. info->flags |= ROCKET_NORMAL_ACTIVE;
  816. return 0;
  817. }
  818. /*
  819.  * This routine is called whenever a rocketport board is opened.
  820.  */
  821. static int rp_open(struct tty_struct *tty, struct file * filp)
  822. {
  823. struct r_port *info;
  824. int line, retval;
  825. CHANNEL_t *cp;
  826. unsigned long page;
  827. line = MINOR(tty->device) - tty->driver.minor_start;
  828. if ((line < 0) || (line >= MAX_RP_PORTS))
  829. return -ENODEV;
  830. if (!tmp_buf) {
  831. page = get_free_page(GFP_KERNEL);
  832. if (!page)
  833. return -ENOMEM;
  834. if (tmp_buf)
  835. free_page(page);
  836. else
  837. tmp_buf = (unsigned char *) page;
  838. }
  839. page = get_free_page(GFP_KERNEL);
  840. if (!page)
  841. return -ENOMEM;
  842. tty->driver_data = info = rp_table[line];
  843. if (info->flags & ROCKET_CLOSING) {
  844. interruptible_sleep_on(&info->close_wait);
  845. free_page(page);
  846. return ((info->flags & ROCKET_HUP_NOTIFY) ?
  847. -EAGAIN : -ERESTARTSYS);
  848. }
  849. /*
  850.  * We must not sleep from here until the port is marked fully
  851.  * in use.
  852.  */
  853. if (rp_table[line] == NULL) {
  854. tty->flags = (1 << TTY_IO_ERROR);
  855. free_page(page);
  856. return 0;
  857. }
  858. if (!info) {
  859. printk("rp_open: rp_table[%d] is NULL!n", line);
  860. free_page(page);
  861. return -EIO;
  862. }
  863. if (info->xmit_buf)
  864. free_page(page);
  865. else
  866. info->xmit_buf = (unsigned char *) page;
  867. info->tty = tty;
  868. if (info->flags & ROCKET_CLOSING) {
  869. interruptible_sleep_on(&info->close_wait);
  870. return ((info->flags & ROCKET_HUP_NOTIFY) ? 
  871. -EAGAIN : -ERESTARTSYS);
  872. }
  873. if (info->count++ == 0) {
  874. #ifdef MODULE
  875. MOD_INC_USE_COUNT;
  876. #endif
  877. rp_num_ports_open++;
  878. #ifdef ROCKET_DEBUG_OPEN
  879. printk("rocket mod++ = %d...", rp_num_ports_open);
  880. #endif
  881. }
  882. #ifdef ROCKET_DEBUG_OPEN
  883. printk("rp_open ttyR%d, count=%dn", info->line, info->count);
  884. #endif
  885. /*
  886.  * Info->count is now 1; so it's safe to sleep now.
  887.  */
  888. info->session = current->session;
  889. info->pgrp = current->pgrp;
  890. cp = &info->channel;
  891. sSetRxTrigger(cp, TRIG_1);
  892. if (sGetChanStatus(cp) & CD_ACT)
  893. info->cd_status = 1;
  894. else
  895. info->cd_status = 0;
  896. sDisRxStatusMode(cp);
  897. sFlushRxFIFO(cp);
  898. sFlushTxFIFO(cp);
  899. sEnInterrupts(cp, (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
  900. sSetRxTrigger(cp, TRIG_1);
  901. sGetChanStatus(cp);
  902. sDisRxStatusMode(cp);
  903. sClrTxXOFF(cp);
  904. sDisCTSFlowCtl(cp);
  905. sDisTxSoftFlowCtl(cp);
  906. sEnRxFIFO(cp);
  907. sEnTransmit(cp);
  908. info->flags |= ROCKET_INITIALIZED;
  909. #if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
  910. /*
  911.  * Set up the tty->alt_speed kludge
  912.  */
  913. if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
  914. info->tty->alt_speed = 57600;
  915. if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
  916. info->tty->alt_speed = 115200;
  917. if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
  918. info->tty->alt_speed = 230400;
  919. if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
  920. info->tty->alt_speed = 460800;
  921. #endif
  922. configure_r_port(info);
  923. if (tty->termios->c_cflag & CBAUD) {
  924. sSetDTR(cp);
  925. sSetRTS(cp);
  926. }
  927. mod_timer(&rocket_timer, jiffies + 1);
  928. retval = block_til_ready(tty, filp, info);
  929. if (retval) {
  930. #ifdef ROCKET_DEBUG_OPEN
  931. printk("rp_open returning after block_til_ready with %dn",
  932.        retval);
  933. #endif
  934. return retval;
  935. }
  936. if ((info->count == 1) && (info->flags & ROCKET_SPLIT_TERMIOS)) {
  937. if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
  938. *tty->termios = info->normal_termios;
  939. else 
  940. *tty->termios = info->callout_termios;
  941. configure_r_port(info);
  942. }
  943. return 0;
  944. }
  945. static void rp_close(struct tty_struct *tty, struct file * filp)
  946. {
  947. struct r_port * info = (struct r_port *)tty->driver_data;
  948. unsigned long flags;
  949. int timeout;
  950. CHANNEL_t *cp;
  951. if (rocket_paranoia_check(info, tty->device, "rp_close"))
  952. return;
  953. #ifdef ROCKET_DEBUG_OPEN
  954. printk("rp_close ttyR%d, count = %dn", info->line, info->count);
  955. #endif
  956. save_flags(flags); cli();
  957. if (tty_hung_up_p(filp)) {
  958. restore_flags(flags);
  959. return;
  960. }
  961. if ((tty->count == 1) && (info->count != 1)) {
  962. /*
  963.  * Uh, oh.  tty->count is 1, which means that the tty
  964.  * structure will be freed.  Info->count should always
  965.  * be one in these conditions.  If it's greater than
  966.  * one, we've got real problems, since it means the
  967.  * serial port won't be shutdown.
  968.  */
  969. printk("rp_close: bad serial port count; tty->count is 1, "
  970.        "info->count is %dn", info->count);
  971. info->count = 1;
  972. }
  973. if (--info->count < 0) {
  974. printk("rp_close: bad serial port count for ttyR%d: %dn",
  975.        info->line, info->count);
  976. info->count = 0;
  977. }
  978. if (info->count) {
  979. restore_flags(flags);
  980. return;
  981. }
  982. info->flags |= ROCKET_CLOSING;
  983. /*
  984.  * Save the termios structure, since this port may have
  985.  * separate termios for callout and dialin.
  986.  */
  987. if (info->flags & ROCKET_NORMAL_ACTIVE)
  988. info->normal_termios = *tty->termios;
  989. if (info->flags & ROCKET_CALLOUT_ACTIVE)
  990. info->callout_termios = *tty->termios;
  991. cp = &info->channel;
  992. /*
  993.  * Notify the line discpline to only process XON/XOFF characters
  994.  */
  995. tty->closing = 1;
  996. /*
  997.  * If transmission was throttled by the application request,
  998.  * just flush the xmit buffer.
  999.  */
  1000. #if (LINUX_VERSION_CODE >= 131343)
  1001. if (tty->flow_stopped)
  1002. rp_flush_buffer(tty);
  1003. #endif
  1004. /*
  1005.  * Wait for the transmit buffer to clear
  1006.  */
  1007. if (info->closing_wait != ROCKET_CLOSING_WAIT_NONE)
  1008. tty_wait_until_sent(tty, info->closing_wait);
  1009. /*
  1010.  * Before we drop DTR, make sure the UART transmitter
  1011.  * has completely drained; this is especially
  1012.  * important if there is a transmit FIFO!
  1013.  */
  1014. timeout = (sGetTxCnt(cp)+1) * HZ / info->cps;
  1015. if (timeout == 0)
  1016. timeout = 1;
  1017. rp_wait_until_sent(tty, timeout);
  1018. xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
  1019. sDisTransmit(cp);
  1020. sDisInterrupts(cp, (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
  1021. sDisCTSFlowCtl(cp);
  1022. sDisTxSoftFlowCtl(cp);
  1023. sClrTxXOFF(cp);
  1024. sFlushRxFIFO(cp);
  1025. sFlushTxFIFO(cp);
  1026. sClrRTS(cp);
  1027. if (C_HUPCL(tty)) {
  1028. sClrDTR(cp);
  1029. }
  1030. if (tty->driver.flush_buffer)
  1031. tty->driver.flush_buffer(tty);
  1032. if (tty->ldisc.flush_buffer)
  1033. tty->ldisc.flush_buffer(tty);
  1034. xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
  1035. if (info->blocked_open) {
  1036. if (info->close_delay) {
  1037. current->state = TASK_INTERRUPTIBLE;
  1038. schedule_timeout(info->close_delay);
  1039. }
  1040. wake_up_interruptible(&info->open_wait);
  1041. } else {
  1042. if (info->xmit_buf) {
  1043. free_page((unsigned long) info->xmit_buf);
  1044. info->xmit_buf = 0;
  1045. }
  1046. }
  1047. info->flags &= ~(ROCKET_INITIALIZED | ROCKET_CLOSING |
  1048.  ROCKET_CALLOUT_ACTIVE | ROCKET_NORMAL_ACTIVE);
  1049. tty->closing = 0;
  1050. wake_up_interruptible(&info->close_wait);
  1051. #ifdef MODULE
  1052. MOD_DEC_USE_COUNT;
  1053. #endif
  1054. rp_num_ports_open--;
  1055. #ifdef ROCKET_DEBUG_OPEN
  1056. printk("rocket mod-- = %d...", rp_num_ports_open);
  1057. #endif
  1058. restore_flags(flags);
  1059. #ifdef ROCKET_DEBUG_OPEN
  1060. printk("rp_close ttyR%d complete shutdownn", info->line);
  1061. #endif
  1062. }
  1063. static void rp_set_termios(struct tty_struct *tty, struct termios *old_termios)
  1064. {
  1065. struct r_port * info = (struct r_port *)tty->driver_data;
  1066. CHANNEL_t *cp;
  1067. unsigned cflag;
  1068. if (rocket_paranoia_check(info, tty->device, "rp_set_termios"))
  1069. return;
  1070. cflag = tty->termios->c_cflag;
  1071. if (cflag == old_termios->c_cflag)
  1072. return;
  1073. /*
  1074.  * This driver doesn't support CS5 or CS6
  1075.  */
  1076. if (((cflag & CSIZE) == CS5) ||
  1077.     ((cflag & CSIZE) == CS6))
  1078. tty->termios->c_cflag = ((cflag & ~CSIZE) |
  1079.  (old_termios->c_cflag & CSIZE));
  1080. configure_r_port(info);
  1081. cp = &info->channel;
  1082. /* Handle transition to B0 status */
  1083. if ((old_termios->c_cflag & CBAUD) &&
  1084.     !(tty->termios->c_cflag & CBAUD)) {
  1085. sClrDTR(cp);
  1086. sClrRTS(cp);
  1087. }
  1088. /* Handle transition away from B0 status */
  1089. if (!(old_termios->c_cflag & CBAUD) &&
  1090.     (tty->termios->c_cflag & CBAUD)) {
  1091. if (!tty->hw_stopped ||
  1092.     !(tty->termios->c_cflag & CRTSCTS)) {
  1093. sSetRTS(cp);
  1094. }
  1095. sSetDTR(cp);
  1096. }
  1097. if ((old_termios->c_cflag & CRTSCTS) &&
  1098.     !(tty->termios->c_cflag & CRTSCTS)) {
  1099. tty->hw_stopped = 0;
  1100. rp_start(tty);
  1101. }
  1102. }
  1103. /*
  1104.  * Here are the routines used by rp_ioctl
  1105.  */
  1106. #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
  1107. static void send_break( struct r_port * info, int duration)
  1108. {
  1109. current->state = TASK_INTERRUPTIBLE;
  1110. cli();
  1111. sSendBreak(&info->channel);
  1112. schedule_timeout(duration);
  1113. sClrBreak(&info->channel);
  1114. sti();
  1115. }
  1116. #else
  1117. static void rp_break(struct tty_struct *tty, int break_state)
  1118. {
  1119. struct r_port * info = (struct r_port *)tty->driver_data;
  1120. unsigned long flags;
  1121. if (rocket_paranoia_check(info, tty->device, "rp_break"))
  1122. return;
  1123. save_flags(flags); cli();
  1124. if (break_state == -1) {
  1125. sSendBreak(&info->channel);
  1126. } else {
  1127. sClrBreak(&info->channel);
  1128. }
  1129. restore_flags(flags);
  1130. }
  1131. #endif
  1132. static int get_modem_info(struct r_port * info, unsigned int *value)
  1133. {
  1134. unsigned int control, result, ChanStatus;
  1135. ChanStatus = sGetChanStatusLo(&info->channel);
  1136. control = info->channel.TxControl[3];
  1137. result =  ((control & SET_RTS) ? TIOCM_RTS : 0)
  1138. | ((control & SET_DTR) ? TIOCM_DTR : 0)
  1139. | ((ChanStatus  & CD_ACT) ? TIOCM_CAR : 0)
  1140. /* TIOCM_RNG not supported */
  1141. | ((ChanStatus  & DSR_ACT) ? TIOCM_DSR : 0)
  1142. | ((ChanStatus  & CTS_ACT) ? TIOCM_CTS : 0);
  1143. if (copy_to_user(value, &result, sizeof(int)))
  1144. return -EFAULT;
  1145. return 0;
  1146. }
  1147. static int set_modem_info(struct r_port * info, unsigned int cmd,
  1148.   unsigned int *value)
  1149. {
  1150. unsigned int arg;
  1151. if (copy_from_user(&arg, value, sizeof(int)))
  1152. return -EFAULT;
  1153. switch (cmd) {
  1154. case TIOCMBIS: 
  1155. if (arg & TIOCM_RTS)
  1156. info->channel.TxControl[3] |= SET_RTS;
  1157. if (arg & TIOCM_DTR)
  1158. info->channel.TxControl[3] |= SET_DTR;
  1159. break;
  1160. case TIOCMBIC:
  1161. if (arg & TIOCM_RTS)
  1162. info->channel.TxControl[3] &= ~SET_RTS;
  1163. if (arg & TIOCM_DTR)
  1164. info->channel.TxControl[3] &= ~SET_DTR;
  1165. break;
  1166. case TIOCMSET:
  1167. info->channel.TxControl[3] =
  1168. ((info->channel.TxControl[3] & ~(SET_RTS | SET_DTR))
  1169.  | ((arg & TIOCM_RTS) ? SET_RTS : 0)
  1170.  | ((arg & TIOCM_DTR) ? SET_DTR : 0));
  1171. break;
  1172. default:
  1173. return -EINVAL;
  1174. }
  1175. sOutDW(info->channel.IndexAddr,
  1176.        *(DWord_t *) &(info->channel.TxControl[0]));
  1177. return 0;
  1178. }
  1179. static int get_config(struct r_port * info, struct rocket_config * retinfo)
  1180. {
  1181. struct rocket_config tmp;
  1182.   
  1183. if (!retinfo)
  1184. return -EFAULT;
  1185. memset(&tmp, 0, sizeof(tmp));
  1186. tmp.line = info->line;
  1187. tmp.flags = info->flags;
  1188. tmp.close_delay = info->close_delay;
  1189. tmp.closing_wait = info->closing_wait;
  1190. tmp.port = rcktpt_io_addr[(info->line >> 5) & 3];
  1191. if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
  1192. return -EFAULT;
  1193. return 0;
  1194. }
  1195. static int set_config(struct r_port * info, struct rocket_config * new_info)
  1196. {
  1197. struct rocket_config new_serial;
  1198. if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
  1199. return -EFAULT;
  1200. #ifdef CAP_SYS_ADMIN
  1201. if (!capable(CAP_SYS_ADMIN))
  1202. #else
  1203. if (!suser())
  1204. #endif
  1205. {
  1206. if ((new_serial.flags & ~ROCKET_USR_MASK) !=
  1207.     (info->flags & ~ROCKET_USR_MASK))
  1208. return -EPERM;
  1209. info->flags = ((info->flags & ~ROCKET_USR_MASK) |
  1210.        (new_serial.flags & ROCKET_USR_MASK));
  1211. configure_r_port(info);
  1212. return 0;
  1213. }
  1214. info->flags = ((info->flags & ~ROCKET_FLAGS) |
  1215. (new_serial.flags & ROCKET_FLAGS));
  1216. info->close_delay = new_serial.close_delay;
  1217. info->closing_wait = new_serial.closing_wait;
  1218. #if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
  1219. if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
  1220. info->tty->alt_speed = 57600;
  1221. if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
  1222. info->tty->alt_speed = 115200;
  1223. if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
  1224. info->tty->alt_speed = 230400;
  1225. if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
  1226. info->tty->alt_speed = 460800;
  1227. #endif
  1228. configure_r_port(info);
  1229. return 0;
  1230. }
  1231. static int get_ports(struct r_port * info, struct rocket_ports * retports)
  1232. {
  1233. struct rocket_ports tmp;
  1234. int board, port, index;
  1235.   
  1236. if (!retports)
  1237. return -EFAULT;
  1238. memset(&tmp, 0, sizeof(tmp));
  1239. tmp.tty_major = rocket_driver.major;
  1240. tmp.callout_major = callout_driver.major;
  1241. for (board = 0; board < 4; board++) {
  1242. index = board << 5;
  1243. for (port = 0; port < 32; port++, index++) {
  1244. if (rp_table[index])
  1245. tmp.port_bitmap[board] |= 1 << port;
  1246. }
  1247. }
  1248. if (copy_to_user(retports,&tmp,sizeof(*retports)))
  1249. return -EFAULT;
  1250. return 0;
  1251. }
  1252. static int rp_ioctl(struct tty_struct *tty, struct file * file,
  1253.     unsigned int cmd, unsigned long arg)
  1254. {
  1255. struct r_port * info = (struct r_port *)tty->driver_data;
  1256. #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
  1257. int retval, tmp;
  1258. #endif
  1259. if (cmd != RCKP_GET_PORTS &&
  1260.     rocket_paranoia_check(info, tty->device, "rp_ioctl"))
  1261. return -ENODEV;
  1262. switch (cmd) {
  1263. #if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
  1264. case TCSBRK: /* SVID version: non-zero arg --> no break */
  1265. retval = tty_check_change(tty);
  1266. if (retval)
  1267. return retval;
  1268. tty_wait_until_sent(tty, 0);
  1269. if (signal_pending(current))
  1270. return -EINTR;
  1271. if (!arg) {
  1272. send_break(info, HZ/4); /* 1/4 second */
  1273. if (signal_pending(current))
  1274. return -EINTR;
  1275. }
  1276. return 0;
  1277. case TCSBRKP: /* support for POSIX tcsendbreak() */
  1278. retval = tty_check_change(tty);
  1279. if (retval)
  1280. return retval;
  1281. tty_wait_until_sent(tty, 0);
  1282. if (signal_pending(current))
  1283. return -EINTR;
  1284. send_break(info, arg ? arg*(HZ/10) : HZ/4);
  1285. if (signal_pending(current))
  1286. return -EINTR;
  1287. return 0;
  1288. case TIOCGSOFTCAR:
  1289. tmp = C_CLOCAL(tty) ? 1 : 0;
  1290. if (copy_to_user((void *)arg, &tmp, sizeof(int)))
  1291. return -EFAULT;
  1292. return 0;
  1293. case TIOCSSOFTCAR:
  1294. if (copy_from_user(&tmp, (void *)arg, sizeof(int)))
  1295. return -EFAULT;
  1296. tty->termios->c_cflag =
  1297. ((tty->termios->c_cflag & ~CLOCAL) |
  1298.  (tmp ? CLOCAL : 0));
  1299. return 0;
  1300. #endif
  1301. case TIOCMGET:
  1302. return get_modem_info(info, (unsigned int *) arg);
  1303. case TIOCMBIS:
  1304. case TIOCMBIC:
  1305. case TIOCMSET:
  1306. return set_modem_info(info, cmd, (unsigned int *) arg);
  1307. case RCKP_GET_STRUCT:
  1308. if (copy_to_user((void *) arg, info,
  1309.  sizeof(struct r_port)))
  1310. return -EFAULT;
  1311. return 0;
  1312. case RCKP_GET_CONFIG:
  1313. return get_config(info, (struct rocket_config *) arg);
  1314. case RCKP_SET_CONFIG:
  1315. return set_config(info, (struct rocket_config *) arg);
  1316. case RCKP_GET_PORTS:
  1317. return get_ports(info, (struct rocket_ports *) arg);
  1318. default:
  1319. return -ENOIOCTLCMD;
  1320. }
  1321. return 0;
  1322. }
  1323. #if (defined(ROCKET_DEBUG_FLOW) || defined(ROCKET_DEBUG_THROTTLE))
  1324. static char *rp_tty_name(struct tty_struct *tty, char *buf)
  1325. {
  1326. if (tty)
  1327. sprintf(buf, "%s%d", tty->driver.name,
  1328. MINOR(tty->device) - tty->driver.minor_start +
  1329. tty->driver.name_base);
  1330. else
  1331. strcpy(buf, "NULL tty");
  1332. return buf;
  1333. }
  1334. #endif
  1335. static void rp_send_xchar(struct tty_struct *tty, char ch)
  1336. {
  1337. struct r_port *info = (struct r_port *)tty->driver_data;
  1338. CHANNEL_t *cp;
  1339. if (rocket_paranoia_check(info, tty->device, "rp_send_xchar"))
  1340. return;
  1341. cp = &info->channel;
  1342. if (sGetTxCnt(cp)) 
  1343. sWriteTxPrioByte(cp, ch);
  1344. else
  1345. sWriteTxByte(sGetTxRxDataIO(cp), ch);
  1346. }
  1347. static void rp_throttle(struct tty_struct * tty)
  1348. {
  1349. struct r_port *info = (struct r_port *)tty->driver_data;
  1350. CHANNEL_t *cp;
  1351. #ifdef ROCKET_DEBUG_THROTTLE
  1352. char buf[64];
  1353. printk("throttle %s: %d....n", rp_tty_name(tty, buf),
  1354.        tty->ldisc.chars_in_buffer(tty));
  1355. #endif
  1356. if (rocket_paranoia_check(info, tty->device, "rp_throttle"))
  1357. return;
  1358. cp = &info->channel;
  1359. if (I_IXOFF(tty))
  1360. rp_send_xchar(tty, STOP_CHAR(tty));
  1361. sClrRTS(&info->channel);
  1362. }
  1363. static void rp_unthrottle(struct tty_struct * tty)
  1364. {
  1365. struct r_port *info = (struct r_port *)tty->driver_data;
  1366. CHANNEL_t *cp;
  1367. #ifdef ROCKET_DEBUG_THROTTLE
  1368. char buf[64];
  1369. printk("unthrottle %s: %d....n", rp_tty_name(tty, buf),
  1370.        tty->ldisc.chars_in_buffer(tty));
  1371. #endif
  1372. if (rocket_paranoia_check(info, tty->device, "rp_throttle"))
  1373. return;
  1374. cp = &info->channel;
  1375. if (I_IXOFF(tty))
  1376. rp_send_xchar(tty, START_CHAR(tty));
  1377. sSetRTS(&info->channel);
  1378. }
  1379. /*
  1380.  * ------------------------------------------------------------
  1381.  * rp_stop() and rp_start()
  1382.  *
  1383.  * This routines are called before setting or resetting tty->stopped.
  1384.  * They enable or disable transmitter interrupts, as necessary.
  1385.  * ------------------------------------------------------------
  1386.  */
  1387. static void rp_stop(struct tty_struct *tty)
  1388. {
  1389. struct r_port * info = (struct r_port *)tty->driver_data;
  1390. #ifdef ROCKET_DEBUG_FLOW
  1391. char buf[64];
  1392. printk("stop %s: %d %d....n", rp_tty_name(tty, buf),
  1393.        info->xmit_cnt, info->xmit_fifo_room);
  1394. #endif
  1395. if (rocket_paranoia_check(info, tty->device, "rp_stop"))
  1396. return;
  1397. if (sGetTxCnt(&info->channel))
  1398. sDisTransmit(&info->channel);
  1399. }
  1400. static void rp_start(struct tty_struct *tty)
  1401. {
  1402. struct r_port * info = (struct r_port *)tty->driver_data;
  1403. #ifdef ROCKET_DEBUG_FLOW
  1404. char buf[64];
  1405. printk("start %s: %d %d....n", rp_tty_name(tty, buf),
  1406.        info->xmit_cnt, info->xmit_fifo_room);
  1407. #endif
  1408. if (rocket_paranoia_check(info, tty->device, "rp_stop"))
  1409. return;
  1410. sEnTransmit(&info->channel);
  1411. xmit_flags[info->line >> 5] |= (1 << (info->line & 0x1f));
  1412. }
  1413. /*
  1414.  * rp_wait_until_sent() --- wait until the transmitter is empty
  1415.  */
  1416. static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
  1417. {
  1418. struct r_port *info = (struct r_port *)tty->driver_data;
  1419. CHANNEL_t *cp;
  1420. unsigned long orig_jiffies;
  1421. int check_time, exit_time;
  1422. int txcnt;
  1423. if (rocket_paranoia_check(info, tty->device, "rp_wait_until_sent"))
  1424. return;
  1425. cp = &info->channel;
  1426. orig_jiffies = jiffies;
  1427. #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
  1428. printk("In RP_wait_until_sent(%d) (jiff=%lu)...", timeout, jiffies);
  1429. printk("cps=%d...", info->cps);
  1430. #endif
  1431. while (1) {
  1432. txcnt = sGetTxCnt(cp);
  1433. if (!txcnt) {
  1434. if (sGetChanStatusLo(cp) & TXSHRMT)
  1435. break;
  1436. check_time = (HZ / info->cps) / 5;
  1437. } else
  1438. check_time = HZ * txcnt / info->cps;
  1439. if (timeout) {
  1440. exit_time = orig_jiffies + timeout - jiffies;
  1441. if (exit_time <= 0)
  1442. break;
  1443. if (exit_time < check_time)
  1444. check_time = exit_time;
  1445. }
  1446. if (check_time == 0)
  1447. check_time = 1;
  1448. #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
  1449. printk("txcnt = %d (jiff=%lu,check=%d)...", txcnt,
  1450.        jiffies, check_time);
  1451. #endif
  1452. current->state = TASK_INTERRUPTIBLE;
  1453. schedule_timeout(check_time);
  1454. if (signal_pending(current))
  1455. break;
  1456. }
  1457. current->state = TASK_RUNNING;
  1458. #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
  1459. printk("txcnt = %d (jiff=%lu)...donen", txcnt, jiffies);
  1460. #endif
  1461. }
  1462. /*
  1463.  * rp_hangup() --- called by tty_hangup() when a hangup is signaled.
  1464.  */
  1465. static void rp_hangup(struct tty_struct *tty)
  1466. {
  1467. CHANNEL_t *cp;
  1468. struct r_port * info = (struct r_port *)tty->driver_data;
  1469. if (rocket_paranoia_check(info, tty->device, "rp_hangup"))
  1470. return;
  1471. #if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP))
  1472. printk("rp_hangup of ttyR%d...", info->line);
  1473. #endif
  1474. /*
  1475.  * If the port is in the process of being closed, just force
  1476.  * the transmit buffer to be empty, and let rp_close handle
  1477.  * the clean up.
  1478.  */
  1479. if (info->flags & ROCKET_CLOSING) {
  1480. cli();
  1481. info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
  1482. sti();
  1483. wake_up_interruptible(&tty->write_wait);
  1484. return;
  1485. }
  1486. if (info->count) {
  1487. #ifdef MODULE
  1488. MOD_DEC_USE_COUNT;
  1489. #endif
  1490. rp_num_ports_open--;
  1491. }
  1492. xmit_flags[info->line >> 5] &= ~(1 << (info->line & 0x1f));
  1493. info->count = 0;
  1494. info->flags &= ~(ROCKET_NORMAL_ACTIVE|ROCKET_CALLOUT_ACTIVE);
  1495. info->tty = 0;
  1496. cp = &info->channel;
  1497. sDisRxFIFO(cp);
  1498. sDisTransmit(cp);
  1499. sDisInterrupts(cp, (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN));
  1500. sDisCTSFlowCtl(cp);
  1501. sDisTxSoftFlowCtl(cp);
  1502. sClrTxXOFF(cp);
  1503. info->flags &= ~ROCKET_INITIALIZED;
  1504. wake_up_interruptible(&info->open_wait);
  1505. }
  1506. /*
  1507.  * The Rocketport write routines.  The Rocketport driver uses a
  1508.  * double-buffering strategy, with the twist that if the in-memory CPU
  1509.  * buffer is empty, and there's space in the transmit FIFO, the
  1510.  * writing routines will write directly to transmit FIFO.
  1511.  *
  1512.  * This gets a little tricky, but I'm pretty sure I got it all right.
  1513.  */
  1514. static void rp_put_char(struct tty_struct *tty, unsigned char ch)
  1515. {
  1516. struct r_port * info = (struct r_port *)tty->driver_data;
  1517. CHANNEL_t *cp;
  1518. if (rocket_paranoia_check(info, tty->device, "rp_put_char"))
  1519. return;
  1520. #ifdef ROCKET_DEBUG_WRITE
  1521. printk("rp_put_char %c...", ch);
  1522. #endif
  1523. cp = &info->channel;
  1524. if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
  1525. info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
  1526. if (tty->stopped || tty->hw_stopped ||
  1527.     info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
  1528. info->xmit_buf[info->xmit_head++] = ch;
  1529. info->xmit_head &= XMIT_BUF_SIZE-1;
  1530. info->xmit_cnt++;
  1531. xmit_flags[info->line >> 5] |= (1 << (info->line & 0x1f));
  1532. } else {
  1533. sOutB(sGetTxRxDataIO(cp), ch);
  1534. info->xmit_fifo_room--;
  1535. }
  1536. }
  1537. static int rp_write(struct tty_struct * tty, int from_user,
  1538.     const unsigned char *buf, int count)
  1539. {
  1540. struct r_port * info = (struct r_port *)tty->driver_data;
  1541. CHANNEL_t *cp;
  1542. const unsigned char *b;
  1543. int c, retval = 0;
  1544. unsigned long flags;
  1545. if (count <= 0 || rocket_paranoia_check(info, tty->device, "rp_write"))
  1546. return 0;
  1547. #ifdef ROCKET_DEBUG_WRITE
  1548. printk("rp_write %d chars...", count);
  1549. #endif
  1550. cp = &info->channel;
  1551. if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
  1552. info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
  1553. if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0
  1554.     && info->xmit_fifo_room >= 0) {
  1555. c = MIN(count, info->xmit_fifo_room);
  1556. b = buf;
  1557. if (from_user) {
  1558. down(&tmp_buf_sem);
  1559. c -= copy_from_user(tmp_buf, buf, c);
  1560. b = tmp_buf;
  1561. up(&tmp_buf_sem);
  1562. /* In case we got pre-empted */
  1563. if (!c) {
  1564. retval = -EFAULT;
  1565. goto end;
  1566. }
  1567. if (info->tty == 0)
  1568. goto end;
  1569. c = MIN(c, info->xmit_fifo_room);
  1570. }
  1571. sOutStrW(sGetTxRxDataIO(cp), b, c/2);
  1572. if (c & 1)
  1573. sOutB(sGetTxRxDataIO(cp), b[c-1]);
  1574. retval += c;
  1575. buf += c;
  1576. count -= c;
  1577. info->xmit_fifo_room -= c;
  1578. }
  1579. if (!count)
  1580. goto end;
  1581. save_flags(flags);
  1582. while (1) {
  1583. if (info->tty == 0) {
  1584. restore_flags(flags);
  1585. goto end;
  1586. }
  1587. c = MIN(count, MIN(XMIT_BUF_SIZE - info->xmit_cnt - 1,
  1588.    XMIT_BUF_SIZE - info->xmit_head));
  1589. if (c <= 0)
  1590. break;
  1591. b = buf;
  1592. if (from_user) {
  1593. down(&tmp_buf_sem);
  1594. c -= copy_from_user(tmp_buf, buf, c);
  1595. b = tmp_buf;
  1596. up(&tmp_buf_sem);
  1597. if (!c) {
  1598. if (retval == 0)
  1599. retval = -EFAULT;
  1600. goto end_intr;
  1601. }
  1602. /* In case we got pre-empted */
  1603. if (info->tty == 0)
  1604. goto end_intr;
  1605. }
  1606. cli();
  1607. c = MIN(c, MIN(XMIT_BUF_SIZE - info->xmit_cnt - 1,
  1608.        XMIT_BUF_SIZE - info->xmit_head));
  1609. memcpy(info->xmit_buf + info->xmit_head, b, c);
  1610. info->xmit_head = (info->xmit_head + c) & (XMIT_BUF_SIZE-1);
  1611. info->xmit_cnt += c;
  1612. restore_flags(flags);
  1613. buf += c;
  1614. count -= c;
  1615. retval += c;
  1616. }
  1617. end_intr:
  1618. if ((retval > 0) && !tty->stopped && !tty->hw_stopped)
  1619. xmit_flags[info->line >> 5] |= (1 << (info->line & 0x1f));
  1620. restore_flags(flags);
  1621. end:
  1622. if (info->xmit_cnt < WAKEUP_CHARS) {
  1623. if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
  1624.     tty->ldisc.write_wakeup)
  1625. (tty->ldisc.write_wakeup)(tty);
  1626. wake_up_interruptible(&tty->write_wait);
  1627. }
  1628. return retval;
  1629. }
  1630. /*
  1631.  * Return the number of characters that can be sent.  We estimate
  1632.  * only using the in-memory transmit buffer only, and ignore the
  1633.  * potential space in the transmit FIFO.
  1634.  */
  1635. static int rp_write_room(struct tty_struct *tty)
  1636. {
  1637. struct r_port * info = (struct r_port *)tty->driver_data;
  1638. int ret;
  1639. if (rocket_paranoia_check(info, tty->device, "rp_write_room"))
  1640. return 0;
  1641. ret = XMIT_BUF_SIZE - info->xmit_cnt - 1;
  1642. if (ret < 0)
  1643. ret = 0;
  1644. #ifdef ROCKET_DEBUG_WRITE
  1645. printk("rp_write_room returns %d...", ret);
  1646. #endif
  1647. return ret;
  1648. }
  1649. /*
  1650.  * Return the number of characters in the buffer.  Again, this only
  1651.  * counts those characters in the in-memory transmit buffer.
  1652.  */
  1653. static int rp_chars_in_buffer(struct tty_struct *tty)
  1654. {
  1655. struct r_port * info = (struct r_port *)tty->driver_data;
  1656. CHANNEL_t *cp;
  1657. if (rocket_paranoia_check(info, tty->device, "rp_chars_in_buffer"))
  1658. return 0;
  1659. cp = &info->channel;
  1660. #ifdef ROCKET_DEBUG_WRITE
  1661. printk("rp_chars_in_buffer returns %d...", info->xmit_cnt);
  1662. #endif
  1663. return info->xmit_cnt;
  1664. }
  1665. static void rp_flush_buffer(struct tty_struct *tty)
  1666. {
  1667. struct r_port * info = (struct r_port *)tty->driver_data;
  1668. CHANNEL_t *cp;
  1669. if (rocket_paranoia_check(info, tty->device, "rp_flush_buffer"))
  1670. return;
  1671. cli();
  1672. info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
  1673. sti();
  1674. wake_up_interruptible(&tty->write_wait);
  1675. if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
  1676.     tty->ldisc.write_wakeup)
  1677. (tty->ldisc.write_wakeup)(tty);
  1678. cp = &info->channel;
  1679. sFlushTxFIFO(cp);
  1680. }
  1681. #ifdef ENABLE_PCI
  1682. #if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
  1683. /* For compatibility */
  1684. static struct pci_dev *pci_find_slot(unsigned char bus,
  1685.      unsigned char device_fn)
  1686. {
  1687. unsigned short vendor_id, device_id;
  1688. int ret, error;
  1689. static struct pci_dev ret_struct;
  1690. error = pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID,
  1691. &vendor_id);
  1692. ret = pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID,
  1693. &device_id);
  1694. if (error == 0)
  1695. error = ret;
  1696. if (error) {
  1697. printk("PCI RocketPort error: %s not initializing due to error"
  1698.        "reading configuration spacen",
  1699.        pcibios_strerror(error));
  1700. return(0);
  1701. }
  1702. memset(&ret_struct, 0, sizeof(ret_struct));
  1703. ret_struct.device = device_id;
  1704. return &ret_struct;
  1705. }
  1706. #endif
  1707.      
  1708. int __init register_PCI(int i, unsigned int bus, unsigned int device_fn)
  1709. {
  1710. int num_aiops, aiop, max_num_aiops, num_chan, chan;
  1711. unsigned int aiopio[MAX_AIOPS_PER_BOARD];
  1712. char *str;
  1713. CONTROLLER_t *ctlp;
  1714. struct pci_dev *dev = pci_find_slot(bus, device_fn);
  1715. #if (LINUX_VERSION_CODE < 0x020163) /* 2.1.99 */
  1716. int ret;
  1717. unsigned int port;
  1718. #endif
  1719. if (!dev)
  1720. return 0;
  1721. if (pci_enable_device(dev))
  1722. return 0;
  1723. rcktpt_io_addr[i] = pci_resource_start (dev, 0);
  1724. switch(dev->device) {
  1725. case PCI_DEVICE_ID_RP4QUAD:
  1726. str = "Quadcable";
  1727. max_num_aiops = 1;
  1728. break;
  1729. case PCI_DEVICE_ID_RP8OCTA:
  1730. str = "Octacable";
  1731. max_num_aiops = 1;
  1732. break;
  1733. case PCI_DEVICE_ID_RP8INTF:
  1734. str = "8";
  1735. max_num_aiops = 1;
  1736. break;
  1737. case PCI_DEVICE_ID_RP8J:
  1738. str = "8J";
  1739. max_num_aiops = 1;
  1740. break;
  1741. case PCI_DEVICE_ID_RP16INTF:
  1742. str = "16";
  1743. max_num_aiops = 2;
  1744. break;
  1745. case PCI_DEVICE_ID_RP32INTF:
  1746. str = "32";
  1747. max_num_aiops = 4;
  1748. break;
  1749. case PCI_DEVICE_ID_RPP4:
  1750. str = "Plus Quadcable";
  1751. max_num_aiops = 1;
  1752. break;
  1753. case PCI_DEVICE_ID_RPP8:
  1754. str = "Plus Octacable";
  1755. max_num_aiops = 1;
  1756. break;
  1757. case PCI_DEVICE_ID_RP8M:
  1758. str = "8-port Modem";
  1759. max_num_aiops = 1;
  1760. break;
  1761. default:
  1762. str = "(unknown/unsupported)";
  1763. max_num_aiops = 0;
  1764. break;
  1765. }
  1766. for(aiop=0;aiop < max_num_aiops;aiop++)
  1767. aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x40);
  1768. ctlp = sCtlNumToCtlPtr(i);
  1769. num_aiops = sPCIInitController(ctlp, i,
  1770. aiopio, max_num_aiops, 0,
  1771. FREQ_DIS, 0);
  1772. printk("Rocketport controller #%d found at %02x:%02x, "
  1773.        "%d AIOP(s) (PCI Rocketport %s)n", i, bus, device_fn,
  1774.        num_aiops, str);
  1775. if(num_aiops <= 0) {
  1776. rcktpt_io_addr[i] = 0;
  1777. return(0);
  1778. }
  1779. for(aiop = 0;aiop < num_aiops; aiop++) {
  1780. sResetAiopByNum(ctlp, aiop);
  1781. sEnAiop(ctlp, aiop);
  1782. num_chan = sGetAiopNumChan(ctlp, aiop);
  1783. for(chan=0;chan < num_chan; chan++)
  1784. init_r_port(i, aiop, chan);
  1785. }
  1786. return(1);
  1787. }
  1788. static int __init init_PCI(int boards_found)
  1789. {
  1790. unsigned char bus, device_fn;
  1791. int i, count = 0;
  1792. for(i=0; i < (NUM_BOARDS - boards_found); i++) {
  1793. if (!pcibios_find_device(PCI_VENDOR_ID_RP,
  1794. PCI_DEVICE_ID_RP4QUAD, i, &bus, &device_fn)) 
  1795. if (register_PCI(count+boards_found, bus, device_fn))
  1796. count++;
  1797. if (!pcibios_find_device(PCI_VENDOR_ID_RP,
  1798. PCI_DEVICE_ID_RP8J, i, &bus, &device_fn)) 
  1799. if (register_PCI(count+boards_found, bus, device_fn))
  1800. count++;
  1801. if(!pcibios_find_device(PCI_VENDOR_ID_RP,
  1802. PCI_DEVICE_ID_RP8OCTA, i, &bus, &device_fn)) 
  1803. if(register_PCI(count+boards_found, bus, device_fn))
  1804. count++;
  1805. if(!pcibios_find_device(PCI_VENDOR_ID_RP,
  1806. PCI_DEVICE_ID_RP8INTF, i, &bus, &device_fn)) 
  1807. if(register_PCI(count+boards_found, bus, device_fn))
  1808. count++;
  1809. if(!pcibios_find_device(PCI_VENDOR_ID_RP,
  1810. PCI_DEVICE_ID_RP16INTF, i, &bus, &device_fn)) 
  1811. if(register_PCI(count+boards_found, bus, device_fn))
  1812. count++;
  1813. if(!pcibios_find_device(PCI_VENDOR_ID_RP,
  1814. PCI_DEVICE_ID_RP32INTF, i, &bus, &device_fn)) 
  1815. if(register_PCI(count+boards_found, bus, device_fn))
  1816. count++;
  1817. if(!pcibios_find_device(PCI_VENDOR_ID_RP,
  1818. PCI_DEVICE_ID_RP4QUAD, i, &bus, &device_fn)) 
  1819. if(register_PCI(count+boards_found, bus, device_fn))
  1820. count++;
  1821. if(!pcibios_find_device(PCI_VENDOR_ID_RP,
  1822. PCI_DEVICE_ID_RP8J, i, &bus, &device_fn)) 
  1823. if(register_PCI(count+boards_found, bus, device_fn))
  1824. count++;
  1825. if(!pcibios_find_device(PCI_VENDOR_ID_RP,
  1826. PCI_DEVICE_ID_RPP4, i, &bus, &device_fn)) 
  1827. if(register_PCI(count+boards_found, bus, device_fn))
  1828. count++;
  1829. if(!pcibios_find_device(PCI_VENDOR_ID_RP,
  1830. PCI_DEVICE_ID_RPP8, i, &bus, &device_fn)) 
  1831. if(register_PCI(count+boards_found, bus, device_fn))
  1832. count++;
  1833. if(!pcibios_find_device(PCI_VENDOR_ID_RP,
  1834. PCI_DEVICE_ID_RP8M, i, &bus, &device_fn)) 
  1835. if(register_PCI(count+boards_found, bus, device_fn))
  1836. count++;
  1837. }
  1838. return(count);
  1839. }
  1840. #endif
  1841. static int __init init_ISA(int i, int *reserved_controller)
  1842. {
  1843. int num_aiops, num_chan;
  1844. int aiop, chan;
  1845. unsigned int aiopio[MAX_AIOPS_PER_BOARD];
  1846. CONTROLLER_t *ctlp;
  1847. if (rcktpt_io_addr[i] == 0)
  1848. return(0);
  1849. if (check_region(rcktpt_io_addr[i],64)) {
  1850. printk("RocketPort board address 0x%lx in use...n",
  1851. rcktpt_io_addr[i]);
  1852. rcktpt_io_addr[i] = 0;
  1853. return(0);
  1854. }
  1855. for (aiop=0; aiop<MAX_AIOPS_PER_BOARD; aiop++)
  1856. aiopio[aiop]= rcktpt_io_addr[i] + (aiop * 0x400);
  1857. ctlp= sCtlNumToCtlPtr(i);
  1858. num_aiops = sInitController(ctlp, i, controller + (i*0x400),
  1859.     aiopio, MAX_AIOPS_PER_BOARD, 0,
  1860.     FREQ_DIS, 0);
  1861. if (num_aiops <= 0) {
  1862. rcktpt_io_addr[i] = 0;
  1863. return(0);
  1864. }
  1865. for (aiop = 0; aiop < num_aiops; aiop++) {
  1866. sResetAiopByNum(ctlp, aiop);
  1867. sEnAiop(ctlp, aiop);
  1868. num_chan = sGetAiopNumChan(ctlp,aiop);
  1869. for (chan=0; chan < num_chan; chan++)
  1870. init_r_port(i, aiop, chan);
  1871. }
  1872. printk("Rocketport controller #%d found at 0x%lx, "
  1873.        "%d AIOPsn", i, rcktpt_io_addr[i],
  1874.        num_aiops);
  1875. if (rcktpt_io_addr[i] + 0x40 == controller) {
  1876. *reserved_controller = 1;
  1877. request_region(rcktpt_io_addr[i], 68,
  1878.        "Comtrol Rocketport");
  1879. } else {
  1880. request_region(rcktpt_io_addr[i], 64,
  1881.        "Comtrol Rocketport");
  1882. }
  1883. return(1);
  1884. }
  1885. /*
  1886.  * The module "startup" routine; it's run when the module is loaded.
  1887.  */
  1888. int __init rp_init(void)
  1889. {
  1890. int i, retval, pci_boards_found, isa_boards_found;
  1891. int reserved_controller = 0;
  1892. printk("Rocketport device driver module, version %s, %sn",
  1893.        ROCKET_VERSION, ROCKET_DATE);
  1894. /*
  1895.  * Set up the timer channel.  If it is already in use by
  1896.  * some other driver, give up.
  1897.  */
  1898. if (rocket_timer.function) {
  1899. printk("rocket.o: Timer already in use!n");
  1900. return -EBUSY;
  1901. }
  1902. init_timer(&rocket_timer);
  1903. rocket_timer.function = rp_do_poll;
  1904. /*
  1905.  * Initialize the array of pointers to our own internal state
  1906.  * structures.
  1907.  */
  1908. memset(rp_table, 0, sizeof(rp_table));
  1909. memset(xmit_flags, 0, sizeof(xmit_flags));
  1910. if (board1 == 0)
  1911. board1 = 0x180;
  1912. if (controller == 0)
  1913. controller = board1 + 0x40;
  1914. if (check_region(controller, 4)) {
  1915. printk("Controller IO addresses in use, unloading driver.n");
  1916. return -EBUSY;
  1917. }
  1918. rcktpt_io_addr[0] = board1;
  1919. rcktpt_io_addr[1] = board2;
  1920. rcktpt_io_addr[2] = board3;
  1921. rcktpt_io_addr[3] = board4;
  1922. /*
  1923.  * If support_low_speed is set, use the slow clock prescale,
  1924.  * which supports 50 bps
  1925.  */
  1926. if (support_low_speed) {
  1927. sClockPrescale = 0x19; /* mod 9 (divide by 10) prescale */
  1928. rp_baud_base = 230400;
  1929. } else {
  1930. sClockPrescale = 0x14; /* mod 4 (devide by 5) prescale */
  1931. rp_baud_base = 460800;
  1932. }
  1933. /*
  1934.  * OK, let's probe each of the controllers looking for boards.
  1935.  */
  1936. isa_boards_found = 0;
  1937. pci_boards_found = 0;
  1938. for (i=0; i < NUM_BOARDS; i++) {
  1939. if(init_ISA(i, &reserved_controller))
  1940. isa_boards_found++;
  1941. }
  1942. #ifdef ENABLE_PCI
  1943. if (pcibios_present()) {
  1944. if(isa_boards_found < NUM_BOARDS)
  1945. pci_boards_found = init_PCI(isa_boards_found);
  1946. } else {
  1947. printk("No PCI BIOS foundn");
  1948. }
  1949. #endif
  1950. max_board = pci_boards_found + isa_boards_found;
  1951. if (max_board == 0) {
  1952. printk("No rocketport ports found; unloading driver.n");
  1953. rocket_timer.function = 0;
  1954. return -ENODEV;
  1955. }
  1956. if (reserved_controller == 0)
  1957. request_region(controller, 4, "Comtrol Rocketport");
  1958. /*
  1959.  * Set up the tty driver structure and then register this
  1960.  * driver with the tty layer.
  1961.  */
  1962. memset(&rocket_driver, 0, sizeof(struct tty_driver));
  1963. rocket_driver.magic = TTY_DRIVER_MAGIC;
  1964. #ifdef CONFIG_DEVFS_FS
  1965. rocket_driver.name = "tts/R%d";
  1966. #else
  1967. rocket_driver.name = "ttyR";
  1968. #endif
  1969. rocket_driver.major = TTY_ROCKET_MAJOR;
  1970. rocket_driver.minor_start = 0;
  1971. rocket_driver.num = MAX_RP_PORTS;
  1972. rocket_driver.type = TTY_DRIVER_TYPE_SERIAL;
  1973. rocket_driver.subtype = SERIAL_TYPE_NORMAL;
  1974. rocket_driver.init_termios = tty_std_termios;
  1975. rocket_driver.init_termios.c_cflag =
  1976. B9600 | CS8 | CREAD | HUPCL | CLOCAL;
  1977. rocket_driver.flags = TTY_DRIVER_REAL_RAW;
  1978. rocket_driver.refcount = &rocket_refcount;
  1979. rocket_driver.table = rocket_table;
  1980. rocket_driver.termios = rocket_termios;
  1981. rocket_driver.termios_locked = rocket_termios_locked;
  1982. rocket_driver.open = rp_open;
  1983. rocket_driver.close = rp_close;
  1984. rocket_driver.write = rp_write;
  1985. rocket_driver.put_char = rp_put_char;
  1986. rocket_driver.write_room = rp_write_room;
  1987. rocket_driver.chars_in_buffer = rp_chars_in_buffer;
  1988. rocket_driver.flush_buffer = rp_flush_buffer;
  1989. rocket_driver.ioctl = rp_ioctl;
  1990. rocket_driver.throttle = rp_throttle;
  1991. rocket_driver.unthrottle = rp_unthrottle;
  1992. rocket_driver.set_termios = rp_set_termios;
  1993. rocket_driver.stop = rp_stop;
  1994. rocket_driver.start = rp_start;
  1995. rocket_driver.hangup = rp_hangup;
  1996. #if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
  1997. rocket_driver.break_ctl = rp_break;
  1998. #endif
  1999. #if (LINUX_VERSION_CODE >= 131343)
  2000. rocket_driver.send_xchar = rp_send_xchar;
  2001. rocket_driver.wait_until_sent = rp_wait_until_sent;
  2002. #endif
  2003. /*
  2004.  * The callout device is just like normal device except for
  2005.  * the minor number and the subtype code.
  2006.  */
  2007. callout_driver = rocket_driver;
  2008. #ifdef CONFIG_DEVFS_FS
  2009. callout_driver.name = "cua/R%d";
  2010. #else
  2011. callout_driver.name = "cur";
  2012. #endif
  2013. callout_driver.major = CUA_ROCKET_MAJOR;
  2014. callout_driver.minor_start = 0;
  2015. callout_driver.subtype = SERIAL_TYPE_CALLOUT;
  2016. retval = tty_register_driver(&callout_driver);
  2017. if (retval < 0) {
  2018. printk("Couldn't install Rocketport callout driver "
  2019.        "(error %d)n", -retval);
  2020. return -1;
  2021. }
  2022. retval = tty_register_driver(&rocket_driver);
  2023. if (retval < 0) {
  2024. printk("Couldn't install tty Rocketport driver "
  2025.        "(error %d)n", -retval);
  2026. return -1;
  2027. }
  2028. #ifdef ROCKET_DEBUG_OPEN
  2029. printk("Rocketport driver is major %d, callout is %dn",
  2030.        rocket_driver.major, callout_driver.major);
  2031. #endif
  2032. return 0;
  2033. }
  2034. #ifdef MODULE
  2035. int init_module(void)
  2036. {
  2037. return rp_init();
  2038. }
  2039. void
  2040. cleanup_module( void) {
  2041. int retval;
  2042. int i;
  2043. int released_controller = 0;
  2044. del_timer_sync(&rocket_timer);
  2045. retval = tty_unregister_driver(&callout_driver);
  2046. if (retval) {
  2047. printk("Error %d while trying to unregister "
  2048.        "rocketport callout drivern", -retval);
  2049. }
  2050. retval = tty_unregister_driver(&rocket_driver);
  2051. if (retval) {
  2052. printk("Error %d while trying to unregister "
  2053.        "rocketport drivern", -retval);
  2054. }
  2055. for (i = 0; i < MAX_RP_PORTS; i++) {
  2056. if (rp_table[i])
  2057. kfree(rp_table[i]);
  2058. }
  2059. for (i=0; i < NUM_BOARDS; i++) {
  2060. if (rcktpt_io_addr[i] <= 0)
  2061. continue;
  2062. if (rcktpt_io_addr[i] + 0x40 == controller) {
  2063. released_controller++;
  2064. release_region(rcktpt_io_addr[i], 68);
  2065. } else
  2066. release_region(rcktpt_io_addr[i], 64);
  2067. if (released_controller == 0)
  2068. release_region(controller, 4);
  2069. }
  2070. if (tmp_buf)
  2071. free_page((unsigned long) tmp_buf);
  2072. rocket_timer.function = 0;
  2073. }
  2074. #endif
  2075. /***********************************************************************
  2076. Copyright 1994 Comtrol Corporation.
  2077. All Rights Reserved.
  2078. The following source code is subject to Comtrol Corporation's
  2079. Developer's License Agreement.
  2080. This source code is protected by United States copyright law and 
  2081. international copyright treaties.
  2082. This source code may only be used to develop software products that
  2083. will operate with Comtrol brand hardware.
  2084. You may not reproduce nor distribute this source code in its original
  2085. form but must produce a derivative work which includes portions of
  2086. this source code only.
  2087. The portions of this source code which you use in your derivative
  2088. work must bear Comtrol's copyright notice:
  2089. Copyright 1994 Comtrol Corporation.
  2090. ***********************************************************************/
  2091. #ifndef TRUE
  2092. #define TRUE 1
  2093. #endif
  2094. #ifndef FALSE
  2095. #define FALSE 0
  2096. #endif
  2097. static Byte_t RData[RDATASIZE] =
  2098. {
  2099.    0x00, 0x09, 0xf6, 0x82,
  2100.    0x02, 0x09, 0x86, 0xfb,
  2101.    0x04, 0x09, 0x00, 0x0a,
  2102.    0x06, 0x09, 0x01, 0x0a,
  2103.    0x08, 0x09, 0x8a, 0x13,
  2104.    0x0a, 0x09, 0xc5, 0x11,
  2105.    0x0c, 0x09, 0x86, 0x85,
  2106.    0x0e, 0x09, 0x20, 0x0a,
  2107.    0x10, 0x09, 0x21, 0x0a,
  2108.    0x12, 0x09, 0x41, 0xff,
  2109.    0x14, 0x09, 0x82, 0x00,
  2110.    0x16, 0x09, 0x82, 0x7b,
  2111.    0x18, 0x09, 0x8a, 0x7d,
  2112.    0x1a, 0x09, 0x88, 0x81,
  2113.    0x1c, 0x09, 0x86, 0x7a,
  2114.    0x1e, 0x09, 0x84, 0x81,
  2115.    0x20, 0x09, 0x82, 0x7c,
  2116.    0x22, 0x09, 0x0a, 0x0a 
  2117. };
  2118. static Byte_t RRegData[RREGDATASIZE]=
  2119. {
  2120.    0x00, 0x09, 0xf6, 0x82,             /* 00: Stop Rx processor */
  2121.    0x08, 0x09, 0x8a, 0x13,             /* 04: Tx software flow control */
  2122.    0x0a, 0x09, 0xc5, 0x11,             /* 08: XON char */
  2123.    0x0c, 0x09, 0x86, 0x85,             /* 0c: XANY */
  2124.    0x12, 0x09, 0x41, 0xff,             /* 10: Rx mask char */
  2125.    0x14, 0x09, 0x82, 0x00,             /* 14: Compare/Ignore #0 */
  2126.    0x16, 0x09, 0x82, 0x7b,             /* 18: Compare #1 */
  2127.    0x18, 0x09, 0x8a, 0x7d,             /* 1c: Compare #2 */
  2128.    0x1a, 0x09, 0x88, 0x81,             /* 20: Interrupt #1 */
  2129.    0x1c, 0x09, 0x86, 0x7a,             /* 24: Ignore/Replace #1 */
  2130.    0x1e, 0x09, 0x84, 0x81,             /* 28: Interrupt #2 */
  2131.    0x20, 0x09, 0x82, 0x7c,             /* 2c: Ignore/Replace #2 */
  2132.    0x22, 0x09, 0x0a, 0x0a              /* 30: Rx FIFO Enable */
  2133. };
  2134. CONTROLLER_T sController[CTL_SIZE] =
  2135. {
  2136.    {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
  2137.    {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
  2138.    {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}},
  2139.    {-1,-1,0,0,0,0,0,0,0,0,0,{0,0,0,0},{0,0,0,0},{-1,-1,-1,-1},{0,0,0,0}}
  2140. };
  2141. #if 0
  2142. /* IRQ number to MUDBAC register 2 mapping */
  2143. Byte_t sIRQMap[16] =
  2144. {
  2145.    0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80
  2146. };
  2147. #endif
  2148. Byte_t sBitMapClrTbl[8] =
  2149. {
  2150.    0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
  2151. };
  2152. Byte_t sBitMapSetTbl[8] =
  2153. {
  2154.    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
  2155. };
  2156. int sClockPrescale = 0x14;
  2157. /***************************************************************************
  2158. Function: sInitController
  2159. Purpose:  Initialization of controller global registers and controller
  2160.           structure.
  2161. Call:     sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
  2162.                           IRQNum,Frequency,PeriodicOnly)
  2163.           CONTROLLER_T *CtlP; Ptr to controller structure
  2164.           int CtlNum; Controller number
  2165.           ByteIO_t MudbacIO; Mudbac base I/O address.
  2166.           ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
  2167.              This list must be in the order the AIOPs will be found on the
  2168.              controller.  Once an AIOP in the list is not found, it is
  2169.              assumed that there are no more AIOPs on the controller.
  2170.           int AiopIOListSize; Number of addresses in AiopIOList
  2171.           int IRQNum; Interrupt Request number.  Can be any of the following:
  2172.                          0: Disable global interrupts
  2173.                          3: IRQ 3
  2174.                          4: IRQ 4
  2175.                          5: IRQ 5
  2176.                          9: IRQ 9
  2177.                          10: IRQ 10
  2178.                          11: IRQ 11
  2179.                          12: IRQ 12
  2180.                          15: IRQ 15
  2181.           Byte_t Frequency: A flag identifying the frequency
  2182.                    of the periodic interrupt, can be any one of the following:
  2183.                       FREQ_DIS - periodic interrupt disabled
  2184.                       FREQ_137HZ - 137 Hertz
  2185.                       FREQ_69HZ - 69 Hertz
  2186.                       FREQ_34HZ - 34 Hertz
  2187.                       FREQ_17HZ - 17 Hertz
  2188.                       FREQ_9HZ - 9 Hertz
  2189.                       FREQ_4HZ - 4 Hertz
  2190.                    If IRQNum is set to 0 the Frequency parameter is
  2191.                    overidden, it is forced to a value of FREQ_DIS.
  2192.           int PeriodicOnly: TRUE if all interrupts except the periodic
  2193.                                interrupt are to be blocked.
  2194.                             FALSE is both the periodic interrupt and
  2195.                                other channel interrupts are allowed.
  2196.                             If IRQNum is set to 0 the PeriodicOnly parameter is
  2197.                                overidden, it is forced to a value of FALSE.
  2198. Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
  2199.                initialization failed.
  2200. Comments:
  2201.           If periodic interrupts are to be disabled but AIOP interrupts
  2202.           are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
  2203.           If interrupts are to be completely disabled set IRQNum to 0.
  2204.           Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
  2205.           invalid combination.
  2206.           This function performs initialization of global interrupt modes,
  2207.           but it does not actually enable global interrupts.  To enable
  2208.           and disable global interrupts use functions sEnGlobalInt() and
  2209.           sDisGlobalInt().  Enabling of global interrupts is normally not
  2210.           done until all other initializations are complete.
  2211.           Even if interrupts are globally enabled, they must also be
  2212.           individually enabled for each channel that is to generate
  2213.           interrupts.
  2214. Warnings: No range checking on any of the parameters is done.
  2215.           No context switches are allowed while executing this function.
  2216.           After this function all AIOPs on the controller are disabled,
  2217.           they can be enabled with sEnAiop().
  2218. */
  2219. int sInitController( CONTROLLER_T *CtlP,
  2220. int CtlNum,
  2221. ByteIO_t MudbacIO,
  2222. ByteIO_t *AiopIOList,
  2223. int AiopIOListSize,
  2224. int IRQNum,
  2225. Byte_t Frequency,
  2226. int PeriodicOnly)
  2227. {
  2228. int i;
  2229. ByteIO_t io;
  2230.    CtlP->CtlNum = CtlNum;
  2231.    CtlP->CtlID = CTLID_0001;        /* controller release 1 */
  2232.    CtlP->BusType = isISA;     
  2233.    CtlP->MBaseIO = MudbacIO;
  2234.    CtlP->MReg1IO = MudbacIO + 1;
  2235.    CtlP->MReg2IO = MudbacIO + 2;
  2236.    CtlP->MReg3IO = MudbacIO + 3;
  2237. #if 1
  2238.    CtlP->MReg2 = 0;                 /* interrupt disable */
  2239.    CtlP->MReg3 = 0;                 /* no periodic interrupts */
  2240. #else
  2241.    if(sIRQMap[IRQNum] == 0)            /* interrupts globally disabled */
  2242.    {
  2243.       CtlP->MReg2 = 0;                 /* interrupt disable */
  2244.       CtlP->MReg3 = 0;                 /* no periodic interrupts */
  2245.    }
  2246.    else
  2247.    {
  2248.       CtlP->MReg2 = sIRQMap[IRQNum];   /* set IRQ number */
  2249.       CtlP->MReg3 = Frequency;         /* set frequency */
  2250.       if(PeriodicOnly)                 /* periodic interrupt only */
  2251.       {
  2252.          CtlP->MReg3 |= PERIODIC_ONLY;
  2253.       }
  2254.    }
  2255. #endif
  2256.    sOutB(CtlP->MReg2IO,CtlP->MReg2);
  2257.    sOutB(CtlP->MReg3IO,CtlP->MReg3);
  2258.    sControllerEOI(CtlP);               /* clear EOI if warm init */
  2259.    /* Init AIOPs */
  2260.    CtlP->NumAiop = 0;
  2261.    for(i=0; i < AiopIOListSize; i++)
  2262.    {
  2263.       io = AiopIOList[i];
  2264.       CtlP->AiopIO[i] = (WordIO_t)io;
  2265.       CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
  2266.       sOutB(CtlP->MReg2IO,CtlP->MReg2 | (i & 0x03)); /* AIOP index */
  2267.       sOutB(MudbacIO,(Byte_t)(io >> 6)); /* set up AIOP I/O in MUDBAC */
  2268.       sEnAiop(CtlP,i);                         /* enable the AIOP */
  2269.       CtlP->AiopID[i] = sReadAiopID(io);       /* read AIOP ID */
  2270.       if(CtlP->AiopID[i] == AIOPID_NULL)       /* if AIOP does not exist */
  2271.       {
  2272.          sDisAiop(CtlP,i);                     /* disable AIOP */
  2273.          break;                                /* done looking for AIOPs */
  2274.       }
  2275.       CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
  2276.       sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE);      /* clock prescaler */
  2277.       sOutB(io + _INDX_DATA,sClockPrescale);
  2278.       CtlP->NumAiop++;                         /* bump count of AIOPs */
  2279.       sDisAiop(CtlP,i);                        /* disable AIOP */
  2280.    }
  2281.    if(CtlP->NumAiop == 0)
  2282.       return(-1);
  2283.    else
  2284.       return(CtlP->NumAiop);
  2285. }
  2286. /***************************************************************************
  2287. Function: sPCIInitController
  2288. Purpose:  Initialization of controller global registers and controller
  2289.           structure.
  2290. Call:     sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
  2291.                           IRQNum,Frequency,PeriodicOnly)
  2292.           CONTROLLER_T *CtlP; Ptr to controller structure
  2293.           int CtlNum; Controller number
  2294.           ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
  2295.              This list must be in the order the AIOPs will be found on the
  2296.              controller.  Once an AIOP in the list is not found, it is
  2297.              assumed that there are no more AIOPs on the controller.
  2298.           int AiopIOListSize; Number of addresses in AiopIOList
  2299.           int IRQNum; Interrupt Request number.  Can be any of the following:
  2300.                          0: Disable global interrupts
  2301.                          3: IRQ 3
  2302.                          4: IRQ 4
  2303.                          5: IRQ 5
  2304.                          9: IRQ 9
  2305.                          10: IRQ 10
  2306.                          11: IRQ 11
  2307.                          12: IRQ 12
  2308.                          15: IRQ 15
  2309.           Byte_t Frequency: A flag identifying the frequency
  2310.                    of the periodic interrupt, can be any one of the following:
  2311.                       FREQ_DIS - periodic interrupt disabled
  2312.                       FREQ_137HZ - 137 Hertz
  2313.                       FREQ_69HZ - 69 Hertz
  2314.                       FREQ_34HZ - 34 Hertz
  2315.                       FREQ_17HZ - 17 Hertz
  2316.                       FREQ_9HZ - 9 Hertz
  2317.                       FREQ_4HZ - 4 Hertz
  2318.                    If IRQNum is set to 0 the Frequency parameter is
  2319.                    overidden, it is forced to a value of FREQ_DIS.
  2320.           int PeriodicOnly: TRUE if all interrupts except the periodic
  2321.                                interrupt are to be blocked.
  2322.                             FALSE is both the periodic interrupt and
  2323.                                other channel interrupts are allowed.
  2324.                             If IRQNum is set to 0 the PeriodicOnly parameter is
  2325.                                overidden, it is forced to a value of FALSE.
  2326. Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
  2327.                initialization failed.
  2328. Comments:
  2329.           If periodic interrupts are to be disabled but AIOP interrupts
  2330.           are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
  2331.           If interrupts are to be completely disabled set IRQNum to 0.
  2332.           Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
  2333.           invalid combination.
  2334.           This function performs initialization of global interrupt modes,
  2335.           but it does not actually enable global interrupts.  To enable
  2336.           and disable global interrupts use functions sEnGlobalInt() and
  2337.           sDisGlobalInt().  Enabling of global interrupts is normally not
  2338.           done until all other initializations are complete.
  2339.           Even if interrupts are globally enabled, they must also be
  2340.           individually enabled for each channel that is to generate
  2341.           interrupts.
  2342. Warnings: No range checking on any of the parameters is done.
  2343.           No context switches are allowed while executing this function.
  2344.           After this function all AIOPs on the controller are disabled,
  2345.           they can be enabled with sEnAiop().
  2346. */
  2347. int sPCIInitController( CONTROLLER_T *CtlP,
  2348. int CtlNum,
  2349. ByteIO_t *AiopIOList,
  2350. int AiopIOListSize,
  2351. int IRQNum,
  2352. Byte_t Frequency,
  2353. int PeriodicOnly)
  2354. {
  2355. int i;
  2356. ByteIO_t io;
  2357.    CtlP->CtlNum = CtlNum;
  2358.    CtlP->CtlID = CTLID_0001;        /* controller release 1 */
  2359.    CtlP->BusType = isPCI;        /* controller release 1 */
  2360.    CtlP->PCIIO = (WordIO_t)((ByteIO_t)AiopIOList[0] + _PCI_INT_FUNC);
  2361.    sPCIControllerEOI(CtlP);               /* clear EOI if warm init */
  2362.    /* Init AIOPs */
  2363.    CtlP->NumAiop = 0;
  2364.    for(i=0; i < AiopIOListSize; i++)
  2365.    {
  2366.       io = AiopIOList[i];
  2367.       CtlP->AiopIO[i] = (WordIO_t)io;
  2368.       CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
  2369.       CtlP->AiopID[i] = sReadAiopID(io);       /* read AIOP ID */
  2370.       if(CtlP->AiopID[i] == AIOPID_NULL)       /* if AIOP does not exist */
  2371.          break;                                /* done looking for AIOPs */
  2372.       CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t)io); /* num channels in AIOP */
  2373.       sOutW((WordIO_t)io + _INDX_ADDR,_CLK_PRE);      /* clock prescaler */
  2374.       sOutB(io + _INDX_DATA,sClockPrescale);
  2375.       CtlP->NumAiop++;                         /* bump count of AIOPs */
  2376.    }
  2377.    if(CtlP->NumAiop == 0)
  2378.       return(-1);
  2379.    else
  2380.       return(CtlP->NumAiop);
  2381. }
  2382. /***************************************************************************
  2383. Function: sReadAiopID
  2384. Purpose:  Read the AIOP idenfication number directly from an AIOP.
  2385. Call:     sReadAiopID(io)
  2386.           ByteIO_t io: AIOP base I/O address
  2387. Return:   int: Flag AIOPID_XXXX if a valid AIOP is found, where X
  2388.                  is replace by an identifying number.
  2389.           Flag AIOPID_NULL if no valid AIOP is found
  2390. Warnings: No context switches are allowed while executing this function.
  2391. */
  2392. int sReadAiopID(ByteIO_t io)
  2393. {
  2394.    Byte_t AiopID;               /* ID byte from AIOP */
  2395.    sOutB(io + _CMD_REG,RESET_ALL);     /* reset AIOP */
  2396.    sOutB(io + _CMD_REG,0x0);
  2397.    AiopID = sInB(io + _CHN_STAT0) & 0x07;
  2398.    if(AiopID == 0x06)
  2399.       return(1);
  2400.    else                                /* AIOP does not exist */
  2401.       return(-1);
  2402. }
  2403. /***************************************************************************
  2404. Function: sReadAiopNumChan
  2405. Purpose:  Read the number of channels available in an AIOP directly from
  2406.           an AIOP.
  2407. Call:     sReadAiopNumChan(io)
  2408.           WordIO_t io: AIOP base I/O address
  2409. Return:   int: The number of channels available
  2410. Comments: The number of channels is determined by write/reads from identical
  2411.           offsets within the SRAM address spaces for channels 0 and 4.
  2412.           If the channel 4 space is mirrored to channel 0 it is a 4 channel
  2413.           AIOP, otherwise it is an 8 channel.
  2414. Warnings: No context switches are allowed while executing this function.
  2415. */
  2416. int sReadAiopNumChan(WordIO_t io)
  2417. {
  2418.    Word_t x;
  2419.    sOutDW((DWordIO_t)io + _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */
  2420.    sOutW(io + _INDX_ADDR,0);       /* read from SRAM, chan 0 */
  2421.    x = sInW(io + _INDX_DATA);
  2422.    sOutW(io + _INDX_ADDR,0x4000);  /* read from SRAM, chan 4 */
  2423.    if(x != sInW(io + _INDX_DATA))  /* if different must be 8 chan */
  2424.       return(8);
  2425.    else
  2426.       return(4);
  2427. }
  2428. /***************************************************************************
  2429. Function: sInitChan
  2430. Purpose:  Initialization of a channel and channel structure
  2431. Call:     sInitChan(CtlP,ChP,AiopNum,ChanNum)
  2432.           CONTROLLER_T *CtlP; Ptr to controller structure
  2433.           CHANNEL_T *ChP; Ptr to channel structure
  2434.           int AiopNum; AIOP number within controller
  2435.           int ChanNum; Channel number within AIOP
  2436. Return:   int: TRUE if initialization succeeded, FALSE if it fails because channel
  2437.                number exceeds number of channels available in AIOP.
  2438. Comments: This function must be called before a channel can be used.
  2439. Warnings: No range checking on any of the parameters is done.
  2440.           No context switches are allowed while executing this function.
  2441. */
  2442. int sInitChan( CONTROLLER_T *CtlP,
  2443. CHANNEL_T *ChP,
  2444. int AiopNum,
  2445. int ChanNum)
  2446. {
  2447.    int i;
  2448.    WordIO_t AiopIO;
  2449.    WordIO_t ChIOOff;
  2450.    Byte_t *ChR;
  2451.    Word_t ChOff;
  2452.    static Byte_t R[4];
  2453.    int brd9600;
  2454.    if(ChanNum >= CtlP->AiopNumChan[AiopNum])
  2455.       return(FALSE);                   /* exceeds num chans in AIOP */
  2456.    /* Channel, AIOP, and controller identifiers */
  2457.    ChP->CtlP = CtlP;
  2458.    ChP->ChanID = CtlP->AiopID[AiopNum];
  2459.    ChP->AiopNum = AiopNum;
  2460.    ChP->ChanNum = ChanNum;
  2461.    /* Global direct addresses */
  2462.    AiopIO = CtlP->AiopIO[AiopNum];
  2463.    ChP->Cmd = (ByteIO_t)AiopIO + _CMD_REG;
  2464.    ChP->IntChan = (ByteIO_t)AiopIO + _INT_CHAN;
  2465.    ChP->IntMask = (ByteIO_t)AiopIO + _INT_MASK;
  2466.    ChP->IndexAddr = (DWordIO_t)AiopIO + _INDX_ADDR;
  2467.    ChP->IndexData = AiopIO + _INDX_DATA;
  2468.    /* Channel direct addresses */
  2469.    ChIOOff = AiopIO + ChP->ChanNum * 2;
  2470.    ChP->TxRxData = ChIOOff + _TD0;
  2471.    ChP->ChanStat = ChIOOff + _CHN_STAT0;
  2472.    ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
  2473.    ChP->IntID = (ByteIO_t)AiopIO + ChP->ChanNum + _INT_ID0;
  2474.    /* Initialize the channel from the RData array */
  2475.    for(i=0; i < RDATASIZE; i+=4)
  2476.    {
  2477.       R[0] = RData[i];
  2478.       R[1] = RData[i+1] + 0x10 * ChanNum;
  2479.       R[2] = RData[i+2];
  2480.       R[3] = RData[i+3];
  2481.       sOutDW(ChP->IndexAddr,*((DWord_t *)&R[0]));
  2482.    }
  2483.    ChR = ChP->R;
  2484.    for(i=0; i < RREGDATASIZE; i+=4)
  2485.    {
  2486.       ChR[i] = RRegData[i];
  2487.       ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum;
  2488.       ChR[i+2] = RRegData[i+2];
  2489.       ChR[i+3] = RRegData[i+3];
  2490.    }
  2491.    /* Indexed registers */
  2492.    ChOff = (Word_t)ChanNum * 0x1000;
  2493.    if (sClockPrescale == 0x14)
  2494.    brd9600 = 47;
  2495.    else
  2496.    brd9600 = 23;
  2497.    ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD);
  2498.    ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8);
  2499.    ChP->BaudDiv[2] = (Byte_t)brd9600;
  2500.    ChP->BaudDiv[3] = (Byte_t)(brd9600 >> 8);
  2501.    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->BaudDiv[0]);
  2502.    ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL);
  2503.    ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8);
  2504.    ChP->TxControl[2] = 0;
  2505.    ChP->TxControl[3] = 0;
  2506.    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
  2507.    ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL);
  2508.    ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8);
  2509.    ChP->RxControl[2] = 0;
  2510.    ChP->RxControl[3] = 0;
  2511.    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
  2512.    ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS);
  2513.    ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8);
  2514.    ChP->TxEnables[2] = 0;
  2515.    ChP->TxEnables[3] = 0;
  2516.    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxEnables[0]);
  2517.    ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1);
  2518.    ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8);
  2519.    ChP->TxCompare[2] = 0;
  2520.    ChP->TxCompare[3] = 0;
  2521.    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxCompare[0]);
  2522.    ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1);
  2523.    ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8);
  2524.    ChP->TxReplace1[2] = 0;
  2525.    ChP->TxReplace1[3] = 0;
  2526.    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace1[0]);
  2527.    ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2);
  2528.    ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8);
  2529.    ChP->TxReplace2[2] = 0;
  2530.    ChP->TxReplace2[3] = 0;
  2531.    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxReplace2[0]);
  2532.    ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
  2533.    ChP->TxFIFO = ChOff + _TX_FIFO;
  2534.    sOutB(ChP->Cmd,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */
  2535.    sOutB(ChP->Cmd,(Byte_t)ChanNum);  /* remove reset Tx FIFO count */
  2536.    sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
  2537.    sOutW(ChP->IndexData,0);
  2538.    ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
  2539.    ChP->RxFIFO = ChOff + _RX_FIFO;
  2540.    sOutB(ChP->Cmd,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */
  2541.    sOutB(ChP->Cmd,(Byte_t)ChanNum);  /* remove reset Rx FIFO count */
  2542.    sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
  2543.    sOutW(ChP->IndexData,0);
  2544.    sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
  2545.    sOutW(ChP->IndexData,0);
  2546.    ChP->TxPrioCnt = ChOff + _TXP_CNT;
  2547.    sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioCnt);
  2548.    sOutB(ChP->IndexData,0);
  2549.    ChP->TxPrioPtr = ChOff + _TXP_PNTR;
  2550.    sOutW((WordIO_t)ChP->IndexAddr,ChP->TxPrioPtr);
  2551.    sOutB(ChP->IndexData,0);
  2552.    ChP->TxPrioBuf = ChOff + _TXP_BUF;
  2553.    sEnRxProcessor(ChP);                /* start the Rx processor */
  2554.    return(TRUE);
  2555. }
  2556. /***************************************************************************
  2557. Function: sStopRxProcessor
  2558. Purpose:  Stop the receive processor from processing a channel.
  2559. Call:     sStopRxProcessor(ChP)
  2560.           CHANNEL_T *ChP; Ptr to channel structure
  2561. Comments: The receive processor can be started again with sStartRxProcessor().
  2562.           This function causes the receive processor to skip over the
  2563.           stopped channel.  It does not stop it from processing other channels.
  2564. Warnings: No context switches are allowed while executing this function.
  2565.           Do not leave the receive processor stopped for more than one
  2566.           character time.
  2567.           After calling this function a delay of 4 uS is required to ensure
  2568.           that the receive processor is no longer processing this channel.
  2569. */
  2570. void sStopRxProcessor(CHANNEL_T *ChP)
  2571. {
  2572.    Byte_t R[4];
  2573.    R[0] = ChP->R[0];
  2574.    R[1] = ChP->R[1];
  2575.    R[2] = 0x0a;
  2576.    R[3] = ChP->R[3];
  2577.    sOutDW(ChP->IndexAddr,*(DWord_t *)&R[0]);
  2578. }
  2579. /***************************************************************************
  2580. Function: sFlushRxFIFO
  2581. Purpose:  Flush the Rx FIFO
  2582. Call:     sFlushRxFIFO(ChP)
  2583.           CHANNEL_T *ChP; Ptr to channel structure
  2584. Return:   void
  2585. Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
  2586.           while it is being flushed the receive processor is stopped
  2587.           and the transmitter is disabled.  After these operations a
  2588.           4 uS delay is done before clearing the pointers to allow
  2589.           the receive processor to stop.  These items are handled inside
  2590.           this function.
  2591. Warnings: No context switches are allowed while executing this function.
  2592. */
  2593. void sFlushRxFIFO(CHANNEL_T *ChP)
  2594. {
  2595.    int i;
  2596.    Byte_t Ch;                   /* channel number within AIOP */
  2597.    int RxFIFOEnabled;                  /* TRUE if Rx FIFO enabled */
  2598.    if(sGetRxCnt(ChP) == 0)             /* Rx FIFO empty */
  2599.       return;                          /* don't need to flush */
  2600.    RxFIFOEnabled = FALSE;
  2601.    if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */
  2602.    {
  2603.       RxFIFOEnabled = TRUE;
  2604.       sDisRxFIFO(ChP);                 /* disable it */
  2605.       for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/
  2606.          sInB(ChP->IntChan); /* depends on bus i/o timing */
  2607.    }
  2608.    sGetChanStatus(ChP);          /* clear any pending Rx errors in chan stat */
  2609.    Ch = (Byte_t)sGetChanNum(ChP);
  2610.    sOutB(ChP->Cmd,Ch | RESRXFCNT);     /* apply reset Rx FIFO count */
  2611.    sOutB(ChP->Cmd,Ch);                 /* remove reset Rx FIFO count */
  2612.    sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs); /* clear Rx out ptr */
  2613.    sOutW(ChP->IndexData,0);
  2614.    sOutW((WordIO_t)ChP->IndexAddr,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */
  2615.    sOutW(ChP->IndexData,0);
  2616.    if(RxFIFOEnabled)
  2617.       sEnRxFIFO(ChP);                  /* enable Rx FIFO */
  2618. }
  2619. /***************************************************************************
  2620. Function: sFlushTxFIFO
  2621. Purpose:  Flush the Tx FIFO
  2622. Call:     sFlushTxFIFO(ChP)
  2623.           CHANNEL_T *ChP; Ptr to channel structure
  2624. Return:   void
  2625. Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
  2626.           while it is being flushed the receive processor is stopped
  2627.           and the transmitter is disabled.  After these operations a
  2628.           4 uS delay is done before clearing the pointers to allow
  2629.           the receive processor to stop.  These items are handled inside
  2630.           this function.
  2631. Warnings: No context switches are allowed while executing this function.
  2632. */
  2633. void sFlushTxFIFO(CHANNEL_T *ChP)
  2634. {
  2635.    int i;
  2636.    Byte_t Ch;                   /* channel number within AIOP */
  2637.    int TxEnabled;                      /* TRUE if transmitter enabled */
  2638.    if(sGetTxCnt(ChP) == 0)             /* Tx FIFO empty */
  2639.       return;                          /* don't need to flush */
  2640.    TxEnabled = FALSE;
  2641.    if(ChP->TxControl[3] & TX_ENABLE)
  2642.    {
  2643.       TxEnabled = TRUE;
  2644.       sDisTransmit(ChP);               /* disable transmitter */
  2645.    }
  2646.    sStopRxProcessor(ChP);              /* stop Rx processor */
  2647.    for(i = 0; i < 4000/200; i++)         /* delay 4 uS to allow proc to stop */
  2648.       sInB(ChP->IntChan); /* depends on bus i/o timing */
  2649.    Ch = (Byte_t)sGetChanNum(ChP);
  2650.    sOutB(ChP->Cmd,Ch | RESTXFCNT);     /* apply reset Tx FIFO count */
  2651.    sOutB(ChP->Cmd,Ch);                 /* remove reset Tx FIFO count */
  2652.    sOutW((WordIO_t)ChP->IndexAddr,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */
  2653.    sOutW(ChP->IndexData,0);
  2654.    if(TxEnabled)
  2655.       sEnTransmit(ChP);                /* enable transmitter */
  2656.    sStartRxProcessor(ChP);             /* restart Rx processor */
  2657. }
  2658. /***************************************************************************
  2659. Function: sWriteTxPrioByte
  2660. Purpose:  Write a byte of priority transmit data to a channel
  2661. Call:     sWriteTxPrioByte(ChP,Data)
  2662.           CHANNEL_T *ChP; Ptr to channel structure
  2663.           Byte_t Data; The transmit data byte
  2664. Return:   int: 1 if the bytes is successfully written, otherwise 0.
  2665. Comments: The priority byte is transmitted before any data in the Tx FIFO.
  2666. Warnings: No context switches are allowed while executing this function.
  2667. */
  2668. int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data)
  2669. {
  2670.    Byte_t DWBuf[4];             /* buffer for double word writes */
  2671.    Word_t *WordPtr;          /* must be far because Win SS != DS */
  2672.    register DWordIO_t IndexAddr;
  2673.    if(sGetTxCnt(ChP) > 1)              /* write it to Tx priority buffer */
  2674.    {
  2675.       IndexAddr = ChP->IndexAddr;
  2676.       sOutW((WordIO_t)IndexAddr,ChP->TxPrioCnt); /* get priority buffer status */
  2677.       if(sInB((ByteIO_t)ChP->IndexData) & PRI_PEND) /* priority buffer busy */
  2678.          return(0);                    /* nothing sent */
  2679.       WordPtr = (Word_t *)(&DWBuf[0]);
  2680.       *WordPtr = ChP->TxPrioBuf;       /* data byte address */
  2681.       DWBuf[2] = Data;                 /* data byte value */
  2682.       sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
  2683.       *WordPtr = ChP->TxPrioCnt;       /* Tx priority count address */
  2684.       DWBuf[2] = PRI_PEND + 1;         /* indicate 1 byte pending */
  2685.       DWBuf[3] = 0;                    /* priority buffer pointer */
  2686.       sOutDW(IndexAddr,*((DWord_t *)(&DWBuf[0]))); /* write it out */
  2687.    }
  2688.    else                                /* write it to Tx FIFO */
  2689.    {
  2690.       sWriteTxByte(sGetTxRxDataIO(ChP),Data);
  2691.    }
  2692.    return(1);                          /* 1 byte sent */
  2693. }
  2694. /***************************************************************************
  2695. Function: sEnInterrupts
  2696. Purpose:  Enable one or more interrupts for a channel
  2697. Call:     sEnInterrupts(ChP,Flags)
  2698.           CHANNEL_T *ChP; Ptr to channel structure
  2699.           Word_t Flags: Interrupt enable flags, can be any combination
  2700.              of the following flags:
  2701.                 TXINT_EN:   Interrupt on Tx FIFO empty
  2702.                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
  2703.                             sSetRxTrigger())
  2704.                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
  2705.                 MCINT_EN:   Interrupt on modem input change
  2706.                 CHANINT_EN: Allow channel interrupt signal to the AIOP's
  2707.                             Interrupt Channel Register.
  2708. Return:   void
  2709. Comments: If an interrupt enable flag is set in Flags, that interrupt will be
  2710.           enabled.  If an interrupt enable flag is not set in Flags, that
  2711.           interrupt will not be changed.  Interrupts can be disabled with
  2712.           function sDisInterrupts().
  2713.           This function sets the appropriate bit for the channel in the AIOP's
  2714.           Interrupt Mask Register if the CHANINT_EN flag is set.  This allows
  2715.           this channel's bit to be set in the AIOP's Interrupt Channel Register.
  2716.           Interrupts must also be globally enabled before channel interrupts
  2717.           will be passed on to the host.  This is done with function
  2718.           sEnGlobalInt().
  2719.           In some cases it may be desirable to disable interrupts globally but
  2720.           enable channel interrupts.  This would allow the global interrupt
  2721.           status register to be used to determine which AIOPs need service.
  2722. */
  2723. void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags)
  2724. {
  2725.    Byte_t Mask;                 /* Interrupt Mask Register */
  2726.    ChP->RxControl[2] |=
  2727.       ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
  2728.    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
  2729.    ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN);
  2730.    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
  2731.    if(Flags & CHANINT_EN)
  2732.    {
  2733.       Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
  2734.       sOutB(ChP->IntMask,Mask);
  2735.    }
  2736. }
  2737. /***************************************************************************
  2738. Function: sDisInterrupts
  2739. Purpose:  Disable one or more interrupts for a channel
  2740. Call:     sDisInterrupts(ChP,Flags)
  2741.           CHANNEL_T *ChP; Ptr to channel structure
  2742.           Word_t Flags: Interrupt flags, can be any combination
  2743.              of the following flags:
  2744.                 TXINT_EN:   Interrupt on Tx FIFO empty
  2745.                 RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
  2746.                             sSetRxTrigger())
  2747.                 SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
  2748.                 MCINT_EN:   Interrupt on modem input change
  2749.                 CHANINT_EN: Disable channel interrupt signal to the
  2750.                             AIOP's Interrupt Channel Register.
  2751. Return:   void
  2752. Comments: If an interrupt flag is set in Flags, that interrupt will be
  2753.           disabled.  If an interrupt flag is not set in Flags, that
  2754.           interrupt will not be changed.  Interrupts can be enabled with
  2755.           function sEnInterrupts().
  2756.           This function clears the appropriate bit for the channel in the AIOP's
  2757.           Interrupt Mask Register if the CHANINT_EN flag is set.  This blocks
  2758.           this channel's bit from being set in the AIOP's Interrupt Channel
  2759.           Register.
  2760. */
  2761. void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags)
  2762. {
  2763.    Byte_t Mask;                 /* Interrupt Mask Register */
  2764.    ChP->RxControl[2] &=
  2765.          ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
  2766.    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->RxControl[0]);
  2767.    ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN);
  2768.    sOutDW(ChP->IndexAddr,*(DWord_t *)&ChP->TxControl[0]);
  2769.    if(Flags & CHANINT_EN)
  2770.    {
  2771.       Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
  2772.       sOutB(ChP->IntMask,Mask);
  2773.    }
  2774. }