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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*******************************************************************************
  2. *
  3. *   (c) 1999 by Computone Corporation
  4. *
  5. ********************************************************************************
  6. *
  7. *
  8. *   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
  9. *                serial I/O controllers.
  10. *
  11. *   DESCRIPTION: High-level interface code for the device driver. Uses the
  12. *                Extremely Low Level Interface Support (i2ellis.c). Provides an
  13. *                interface to the standard loadware, to support drivers or
  14. *                application code. (This is included source code, not a separate
  15. *                compilation module.)
  16. *
  17. *******************************************************************************/
  18. //------------------------------------------------------------------------------
  19. // Note on Strategy:
  20. // Once the board has been initialized, it will interrupt us when:
  21. // 1) It has something in the fifo for us to read (incoming data, flow control
  22. // packets, or whatever).
  23. // 2) It has stripped whatever we have sent last time in the FIFO (and
  24. // consequently is ready for more).
  25. //
  26. // Note also that the buffer sizes declared in i2lib.h are VERY SMALL. This
  27. // worsens performance considerably, but is done so that a great many channels
  28. // might use only a little memory.
  29. //------------------------------------------------------------------------------
  30. //------------------------------------------------------------------------------
  31. // Revision History:
  32. //
  33. // 0.00 -  4/16/91 --- First Draft
  34. // 0.01 -  4/29/91 --- 1st beta release
  35. // 0.02 -  6/14/91 --- Changes to allow small model compilation
  36. // 0.03 -  6/17/91 MAG Break reporting protected from interrupts routines with
  37. //                     in-line asm added for moving data to/from ring buffers,
  38. //                     replacing a variety of methods used previously.
  39. // 0.04 -  6/21/91 MAG Initial flow-control packets not queued until
  40. //                     i2_enable_interrupts time. Former versions would enqueue
  41. //                     them at i2_init_channel time, before we knew how many
  42. //                     channels were supposed to exist!
  43. // 0.05 - 10/12/91 MAG Major changes: works through the ellis.c routines now;
  44. //                     supports new 16-bit protocol and expandable boards.
  45. //      - 10/24/91 MAG Most changes in place and stable.
  46. // 0.06 -  2/20/92 MAG Format of CMD_HOTACK corrected: the command takes no
  47. //                     argument.
  48. // 0.07 -- 3/11/92 MAG Support added to store special packet types at interrupt
  49. //                     level (mostly responses to specific commands.)
  50. // 0.08 -- 3/30/92 MAG Support added for STAT_MODEM packet
  51. // 0.09 -- 6/24/93 MAG i2Link... needed to update number of boards BEFORE
  52. //                     turning on the interrupt.
  53. // 0.10 -- 6/25/93 MAG To avoid gruesome death from a bad board, we sanity check
  54. //                     some incoming.
  55. //
  56. // 1.1  - 12/25/96 AKM Linux version.
  57. //      - 10/09/98 DMC Revised Linux version.
  58. //------------------------------------------------------------------------------
  59. //************
  60. //* Includes *
  61. //************
  62. #include <linux/sched.h>
  63. #include "i2lib.h"
  64. //***********************
  65. //* Function Prototypes *
  66. //***********************
  67. static void i2QueueNeeds(i2eBordStrPtr, i2ChanStrPtr, int);
  68. static i2ChanStrPtr i2DeQueueNeeds(i2eBordStrPtr, int );
  69. static void i2StripFifo(i2eBordStrPtr);
  70. static void i2StuffFifoBypass(i2eBordStrPtr);
  71. static void i2StuffFifoFlow(i2eBordStrPtr);
  72. static void i2StuffFifoInline(i2eBordStrPtr);
  73. static int i2RetryFlushOutput(i2ChanStrPtr);
  74. // Not a documented part of the library routines (careful...) but the Diagnostic
  75. // i2diag.c finds them useful to help the throughput in certain limited
  76. // single-threaded operations.
  77. static void iiSendPendingMail(i2eBordStrPtr);
  78. static void serviceOutgoingFifo(i2eBordStrPtr);
  79. // Functions defined in ip2.c as part of interrupt handling
  80. static void do_input(i2ChanStrPtr);
  81. static void do_status(i2ChanStrPtr);
  82. //***************
  83. //* Debug  Data *
  84. //***************
  85. #ifdef DEBUG_FIFO
  86. unsigned char DBGBuf[0x4000];
  87. unsigned short I = 0;
  88. static void
  89. WriteDBGBuf(char *s, unsigned char *src, unsigned short n ) 
  90. {
  91. char *p = src;
  92. // XXX: We need a spin lock here if we ever use this again
  93. while (*s) { // copy label
  94. DBGBuf[I] = *s++;
  95. I = I++ & 0x3fff;
  96. }
  97. while (n--) { // copy data
  98. DBGBuf[I] = *p++;
  99. I = I++ & 0x3fff;
  100. }
  101. }
  102. static void
  103. fatality(i2eBordStrPtr pB )
  104. {
  105. int i;
  106. for (i=0;i<sizeof(DBGBuf);i++) {
  107. if ((i%16) == 0)
  108. printk("n%4x:",i);
  109. printk("%02x ",DBGBuf[i]);
  110. }
  111. printk("n");
  112. for (i=0;i<sizeof(DBGBuf);i++) {
  113. if ((i%16) == 0)
  114. printk("n%4x:",i);
  115. if (DBGBuf[i] >= ' ' && DBGBuf[i] <= '~') {
  116. printk(" %c ",DBGBuf[i]);
  117. } else {
  118. printk(" . ");
  119. }
  120. }
  121. printk("n");
  122. printk("Last index %xn",I);
  123. }
  124. #endif /* DEBUG_FIFO */
  125. //********
  126. //* Code *
  127. //********
  128. inline int
  129. i2Validate ( i2ChanStrPtr pCh )
  130. {
  131. //ip2trace(pCh->port_index, ITRC_VERIFY,ITRC_ENTER,2,pCh->validity,
  132. // (CHANNEL_MAGIC | CHANNEL_SUPPORT));
  133. return ((pCh->validity & (CHANNEL_MAGIC_BITS | CHANNEL_SUPPORT)) 
  134.   == (CHANNEL_MAGIC | CHANNEL_SUPPORT));
  135. }
  136. //******************************************************************************
  137. // Function:   iiSendPendingMail(pB)
  138. // Parameters: Pointer to a board structure
  139. // Returns:    Nothing
  140. //
  141. // Description:
  142. // If any outgoing mail bits are set and there is outgoing mailbox is empty,
  143. // send the mail and clear the bits.
  144. //******************************************************************************
  145. static inline void
  146. iiSendPendingMail(i2eBordStrPtr pB)
  147. {
  148. if (pB->i2eOutMailWaiting && (!pB->i2eWaitingForEmptyFifo) )
  149. {
  150. if (iiTrySendMail(pB, pB->i2eOutMailWaiting))
  151. {
  152. /* If we were already waiting for fifo to empty,
  153.  * or just sent MB_OUT_STUFFED, then we are
  154.  * still waiting for it to empty, until we should
  155.  * receive an MB_IN_STRIPPED from the board.
  156.  */
  157. pB->i2eWaitingForEmptyFifo |=
  158. (pB->i2eOutMailWaiting & MB_OUT_STUFFED);
  159. pB->i2eOutMailWaiting = 0;
  160. pB->SendPendingRetry = 0;
  161. } else {
  162. /* The only time we hit this area is when "iiTrySendMail" has
  163. failed.  That only occurs when the outbound mailbox is
  164. still busy with the last message.  We take a short breather
  165. to let the board catch up with itself and then try again.
  166. 16 Retries is the limit - then we got a borked board.
  167. //|=mhw=|// */
  168. if( ++pB->SendPendingRetry < 16 ) {
  169. init_timer( &(pB->SendPendingTimer) );
  170. pB->SendPendingTimer.expires  = jiffies + 1;
  171. pB->SendPendingTimer.function = (void*)(unsigned long)iiSendPendingMail;
  172. pB->SendPendingTimer.data     = (unsigned long)pB;
  173. add_timer( &(pB->SendPendingTimer) );
  174. } else {
  175. printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mailn" );
  176. }
  177. }
  178. }
  179. }
  180. //******************************************************************************
  181. // Function:   i2InitChannels(pB, nChannels, pCh)
  182. // Parameters: Pointer to Ellis Board structure
  183. //             Number of channels to initialize
  184. //             Pointer to first element in an array of channel structures
  185. // Returns:    Success or failure
  186. //
  187. // Description:
  188. //
  189. // This function patches pointers, back-pointers, and initializes all the
  190. // elements in the channel structure array.
  191. //
  192. // This should be run after the board structure is initialized, through having
  193. // loaded the standard loadware (otherwise it complains).
  194. //
  195. // In any case, it must be done before any serious work begins initializing the
  196. // irq's or sending commands...
  197. //
  198. //******************************************************************************
  199. static int
  200. i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh)
  201. {
  202. int index, stuffIndex;
  203. i2ChanStrPtr *ppCh;
  204. if (pB->i2eValid != I2E_MAGIC) {
  205. COMPLETE(pB, I2EE_BADMAGIC);
  206. }
  207. if (pB->i2eState != II_STATE_STDLOADED) {
  208. COMPLETE(pB, I2EE_BADSTATE);
  209. }
  210. LOCK_INIT(&pB->read_fifo_spinlock);
  211. LOCK_INIT(&pB->write_fifo_spinlock);
  212. LOCK_INIT(&pB->Dbuf_spinlock);
  213. LOCK_INIT(&pB->Bbuf_spinlock);
  214. LOCK_INIT(&pB->Fbuf_spinlock);
  215. // NO LOCK needed yet - this is init
  216. pB->i2eChannelPtr = pCh;
  217. pB->i2eChannelCnt = nChannels;
  218. pB->i2Fbuf_strip = pB->i2Fbuf_stuff = 0;
  219. pB->i2Dbuf_strip = pB->i2Dbuf_stuff = 0;
  220. pB->i2Bbuf_strip = pB->i2Bbuf_stuff = 0;
  221. pB->SendPendingRetry = 0;
  222. memset ( pCh, 0, sizeof (i2ChanStr) * nChannels );
  223. for (index = stuffIndex = 0, ppCh = (i2ChanStrPtr *)(pB->i2Fbuf);
  224.   nChannels && index < ABS_MOST_PORTS;
  225.   index++)
  226. {
  227. if ( !(pB->i2eChannelMap[index >> 4] & (1 << (index & 0xf)) ) ) {
  228. continue;
  229. }
  230. LOCK_INIT(&pCh->Ibuf_spinlock);
  231. LOCK_INIT(&pCh->Obuf_spinlock);
  232. LOCK_INIT(&pCh->Cbuf_spinlock);
  233. LOCK_INIT(&pCh->Pbuf_spinlock);
  234. // NO LOCK needed yet - this is init
  235. // Set up validity flag according to support level
  236. if (pB->i2eGoodMap[index >> 4] & (1 << (index & 0xf)) ) {
  237. pCh->validity = CHANNEL_MAGIC | CHANNEL_SUPPORT;
  238. } else {
  239. pCh->validity = CHANNEL_MAGIC;
  240. }
  241. pCh->pMyBord = pB;      /* Back-pointer */
  242. // Prepare an outgoing flow-control packet to send as soon as the chance
  243. // occurs.
  244. if ( pCh->validity & CHANNEL_SUPPORT ) {
  245. pCh->infl.hd.i2sChannel = index;
  246. pCh->infl.hd.i2sCount = 5;
  247. pCh->infl.hd.i2sType = PTYPE_BYPASS;
  248. pCh->infl.fcmd = 37;
  249. pCh->infl.asof = 0;
  250. pCh->infl.room = IBUF_SIZE - 1;
  251. pCh->whenSendFlow = (IBUF_SIZE/5)*4; // when 80% full
  252. // The following is similar to calling i2QueueNeeds, except that this
  253. // is done in longhand, since we are setting up initial conditions on
  254. // many channels at once.
  255. pCh->channelNeeds = NEED_FLOW;  // Since starting from scratch
  256. pCh->sinceLastFlow = 0;         // No bytes received since last flow
  257. // control packet was queued
  258. stuffIndex++;
  259. *ppCh++ = pCh;      // List this channel as needing
  260. // initial flow control packet sent
  261. }
  262. // Don't allow anything to be sent until the status packets come in from
  263. // the board.
  264. pCh->outfl.asof = 0;
  265. pCh->outfl.room = 0;
  266. // Initialize all the ring buffers
  267. pCh->Ibuf_stuff = pCh->Ibuf_strip = 0;
  268. pCh->Obuf_stuff = pCh->Obuf_strip = 0;
  269. pCh->Cbuf_stuff = pCh->Cbuf_strip = 0;
  270. memset( &pCh->icount, 0, sizeof (struct async_icount) );
  271. pCh->hotKeyIn       = HOT_CLEAR;
  272. pCh->channelOptions = 0;
  273. pCh->bookMarks      = 0;
  274. init_waitqueue_head(&pCh->pBookmarkWait);
  275. init_waitqueue_head(&pCh->open_wait);
  276. init_waitqueue_head(&pCh->close_wait);
  277. init_waitqueue_head(&pCh->delta_msr_wait);
  278. // Set base and divisor so default custom rate is 9600
  279. pCh->BaudBase    = 921600; // MAX for ST654, changed after we get
  280. pCh->BaudDivisor = 96; // the boxids (UART types) later
  281. pCh->dataSetIn   = 0;
  282. pCh->dataSetOut  = 0;
  283. pCh->wopen       = 0;
  284. pCh->throttled   = 0;
  285. pCh->speed       = CBR_9600;
  286. pCh->flags    = 0;
  287. pCh->session  = 0;
  288. pCh->pgrp     = 0;
  289. pCh->ClosingDelay     = 5*HZ/10;
  290. pCh->ClosingWaitTime  = 30*HZ;
  291. // Initialize task queue objects
  292. pCh->tqueue_input.routine = (void(*)(void*)) do_input;
  293. pCh->tqueue_input.data = pCh;
  294. pCh->tqueue_status.routine = (void(*)(void*)) do_status;
  295. pCh->tqueue_status.data = pCh;
  296. #ifdef IP2DEBUG_TRACE
  297. pCh->trace = ip2trace;
  298. #endif
  299. ++pCh;
  300.       --nChannels;
  301. }
  302. // No need to check for wrap here; this is initialization.
  303. pB->i2Fbuf_stuff = stuffIndex;
  304. COMPLETE(pB, I2EE_GOOD);
  305. }
  306. //******************************************************************************
  307. // Function:   i2DeQueueNeeds(pB, type)
  308. // Parameters: Pointer to a board structure
  309. //             type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW
  310. // Returns:   
  311. //             Pointer to a channel structure
  312. //
  313. // Description: Returns pointer struct of next channel that needs service of
  314. //  the type specified. Otherwise returns a NULL reference.
  315. //
  316. //******************************************************************************
  317. static i2ChanStrPtr 
  318. i2DeQueueNeeds(i2eBordStrPtr pB, int type)
  319. {
  320. unsigned short queueIndex;
  321. unsigned long flags;
  322. i2ChanStrPtr pCh = NULL;
  323. switch(type) {
  324. case  NEED_INLINE:
  325. WRITE_LOCK_IRQSAVE(&pB->Dbuf_spinlock,flags);
  326. if ( pB->i2Dbuf_stuff != pB->i2Dbuf_strip)
  327. {
  328. queueIndex = pB->i2Dbuf_strip;
  329. pCh = pB->i2Dbuf[queueIndex];
  330. queueIndex++;
  331. if (queueIndex >= CH_QUEUE_SIZE) {
  332. queueIndex = 0;
  333. }
  334. pB->i2Dbuf_strip = queueIndex;
  335. pCh->channelNeeds &= ~NEED_INLINE;
  336. }
  337. WRITE_UNLOCK_IRQRESTORE(&pB->Dbuf_spinlock,flags); 
  338. break;
  339. case NEED_BYPASS:
  340. WRITE_LOCK_IRQSAVE(&pB->Bbuf_spinlock,flags);
  341. if (pB->i2Bbuf_stuff != pB->i2Bbuf_strip)
  342. {
  343. queueIndex = pB->i2Bbuf_strip;
  344. pCh = pB->i2Bbuf[queueIndex];
  345. queueIndex++;
  346. if (queueIndex >= CH_QUEUE_SIZE) {
  347. queueIndex = 0;
  348. }
  349. pB->i2Bbuf_strip = queueIndex;
  350. pCh->channelNeeds &= ~NEED_BYPASS;
  351. }
  352. WRITE_UNLOCK_IRQRESTORE(&pB->Bbuf_spinlock,flags); 
  353. break;
  354. case NEED_FLOW:
  355. WRITE_LOCK_IRQSAVE(&pB->Fbuf_spinlock,flags);
  356. if (pB->i2Fbuf_stuff != pB->i2Fbuf_strip)
  357. {
  358. queueIndex = pB->i2Fbuf_strip;
  359. pCh = pB->i2Fbuf[queueIndex];
  360. queueIndex++;
  361. if (queueIndex >= CH_QUEUE_SIZE) {
  362. queueIndex = 0;
  363. }
  364. pB->i2Fbuf_strip = queueIndex;
  365. pCh->channelNeeds &= ~NEED_FLOW;
  366. }
  367. WRITE_UNLOCK_IRQRESTORE(&pB->Fbuf_spinlock,flags); 
  368. break;
  369. default:
  370. printk(KERN_ERR "i2DeQueueNeeds called with bad type:%xn",type);
  371. break;
  372. }
  373. return pCh;
  374. }
  375. //******************************************************************************
  376. // Function:   i2QueueNeeds(pB, pCh, type)
  377. // Parameters: Pointer to a board structure
  378. //             Pointer to a channel structure
  379. //             type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW
  380. // Returns:    Nothing
  381. //
  382. // Description:
  383. // For each type of need selected, if the given channel is not already in the
  384. // queue, adds it, and sets the flag indicating it is in the queue.
  385. //******************************************************************************
  386. static void
  387. i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type)
  388. {
  389. unsigned short queueIndex;
  390. unsigned long flags;
  391. // We turn off all the interrupts during this brief process, since the
  392. // interrupt-level code might want to put things on the queue as well.
  393. switch (type) {
  394. case NEED_INLINE:
  395. WRITE_LOCK_IRQSAVE(&pB->Dbuf_spinlock,flags);
  396. if ( !(pCh->channelNeeds & NEED_INLINE) )
  397. {
  398. pCh->channelNeeds |= NEED_INLINE;
  399. queueIndex = pB->i2Dbuf_stuff;
  400. pB->i2Dbuf[queueIndex++] = pCh;
  401. if (queueIndex >= CH_QUEUE_SIZE)
  402. queueIndex = 0;
  403. pB->i2Dbuf_stuff = queueIndex;
  404. }
  405. WRITE_UNLOCK_IRQRESTORE(&pB->Dbuf_spinlock,flags); 
  406. break;
  407. case NEED_BYPASS:
  408. WRITE_LOCK_IRQSAVE(&pB->Bbuf_spinlock,flags);
  409. if ((type & NEED_BYPASS) && !(pCh->channelNeeds & NEED_BYPASS))
  410. {
  411. pCh->channelNeeds |= NEED_BYPASS;
  412. queueIndex = pB->i2Bbuf_stuff;
  413. pB->i2Bbuf[queueIndex++] = pCh;
  414. if (queueIndex >= CH_QUEUE_SIZE)
  415. queueIndex = 0;
  416. pB->i2Bbuf_stuff = queueIndex;
  417. WRITE_UNLOCK_IRQRESTORE(&pB->Bbuf_spinlock,flags); 
  418. break;
  419. case NEED_FLOW:
  420. WRITE_LOCK_IRQSAVE(&pB->Fbuf_spinlock,flags);
  421. if ((type & NEED_FLOW) && !(pCh->channelNeeds & NEED_FLOW))
  422. {
  423. pCh->channelNeeds |= NEED_FLOW;
  424. queueIndex = pB->i2Fbuf_stuff;
  425. pB->i2Fbuf[queueIndex++] = pCh;
  426. if (queueIndex >= CH_QUEUE_SIZE)
  427. queueIndex = 0;
  428. pB->i2Fbuf_stuff = queueIndex;
  429. }
  430. WRITE_UNLOCK_IRQRESTORE(&pB->Fbuf_spinlock,flags); 
  431. break;
  432. case NEED_CREDIT:
  433. pCh->channelNeeds |= NEED_CREDIT;
  434. break;
  435. default:
  436. printk(KERN_ERR "i2QueueNeeds called with bad type:%xn",type);
  437. break;
  438. }
  439. return;
  440. }
  441. //******************************************************************************
  442. // Function:   i2QueueCommands(type, pCh, timeout, nCommands, pCs,...)
  443. // Parameters: type - PTYPE_BYPASS or PTYPE_INLINE
  444. //             pointer to the channel structure
  445. //             maximum period to wait
  446. //             number of commands (n)
  447. //             n commands
  448. // Returns:    Number of commands sent, or -1 for error
  449. //
  450. // get board lock before calling
  451. //
  452. // Description:
  453. // Queues up some commands to be sent to a channel. To send possibly several
  454. // bypass or inline commands to the given channel. The timeout parameter
  455. // indicates how many HUNDREDTHS OF SECONDS to wait until there is room:
  456. // 0 = return immediately if no room, -ive  = wait forever, +ive = number of
  457. // 1/100 seconds to wait. Return values:
  458. // -1 Some kind of nasty error: bad channel structure or invalid arguments.
  459. //  0 No room to send all the commands
  460. // (+)   Number of commands sent
  461. //******************************************************************************
  462. static int
  463. i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,
  464.  cmdSyntaxPtr pCs0,...)
  465. {
  466. int totalsize = 0;
  467. int blocksize;
  468. int lastended;
  469. cmdSyntaxPtr *ppCs;
  470. cmdSyntaxPtr pCs;
  471. int count;
  472. int flag;
  473. i2eBordStrPtr pB;
  474. unsigned short maxBlock;
  475. unsigned short maxBuff;
  476. short bufroom;
  477. unsigned short stuffIndex;
  478. unsigned char *pBuf;
  479. unsigned char *pInsert;
  480. unsigned char *pDest, *pSource;
  481. unsigned short channel;
  482. int cnt;
  483. unsigned long flags = 0;
  484. rwlock_t *lock_var_p = NULL;
  485. // Make sure the channel exists, otherwise do nothing
  486. if ( !i2Validate ( pCh ) ) {
  487. return -1;
  488. }
  489. ip2trace (CHANN, ITRC_QUEUE, ITRC_ENTER, 0 );
  490. pB = pCh->pMyBord;
  491. // Board must also exist, and THE INTERRUPT COMMAND ALREADY SENT
  492. if (pB->i2eValid != I2E_MAGIC || pB->i2eUsingIrq == IRQ_UNDEFINED) {
  493. return -2;
  494. }
  495. // If the board has gone fatal, return bad, and also hit the trap routine if
  496. // it exists.
  497. if (pB->i2eFatal) {
  498. if ( pB->i2eFatalTrap ) {
  499. (*(pB)->i2eFatalTrap)(pB);
  500. }
  501. return -3;
  502. }
  503. // Set up some variables, Which buffers are we using?  How big are they?
  504. switch(type)
  505. {
  506. case PTYPE_INLINE:
  507. flag = INL;
  508. maxBlock = MAX_OBUF_BLOCK;
  509. maxBuff = OBUF_SIZE;
  510. pBuf = pCh->Obuf;
  511. break;
  512. case PTYPE_BYPASS:
  513. flag = BYP;
  514. maxBlock = MAX_CBUF_BLOCK;
  515. maxBuff = CBUF_SIZE;
  516. pBuf = pCh->Cbuf;
  517. break;
  518. default:
  519. return -4;
  520. }
  521. // Determine the total size required for all the commands
  522. totalsize = blocksize = sizeof(i2CmdHeader);
  523. lastended = 0;
  524. ppCs = &pCs0;
  525. for ( count = nCommands; count; count--, ppCs++)
  526. {
  527. pCs = *ppCs;
  528. cnt = pCs->length;
  529. // Will a new block be needed for this one? 
  530. // Two possible reasons: too
  531. // big or previous command has to be at the end of a packet.
  532. if ((blocksize + cnt > maxBlock) || lastended) {
  533. blocksize = sizeof(i2CmdHeader);
  534. totalsize += sizeof(i2CmdHeader);
  535. }
  536. totalsize += cnt;
  537. blocksize += cnt;
  538. // If this command had to end a block, then we will make sure to
  539. // account for it should there be any more blocks.
  540. lastended = pCs->flags & END;
  541. }
  542. for (;;) {
  543. // Make sure any pending flush commands go out before we add more data.
  544. if ( !( pCh->flush_flags && i2RetryFlushOutput( pCh ) ) ) {
  545. // How much room (this time through) ?
  546. switch(type) {
  547. case PTYPE_INLINE:
  548. lock_var_p = &pCh->Obuf_spinlock;
  549. WRITE_LOCK_IRQSAVE(lock_var_p,flags);
  550. stuffIndex = pCh->Obuf_stuff;
  551. bufroom = pCh->Obuf_strip - stuffIndex;
  552. break;
  553. case PTYPE_BYPASS:
  554. lock_var_p = &pCh->Cbuf_spinlock;
  555. WRITE_LOCK_IRQSAVE(lock_var_p,flags);
  556. stuffIndex = pCh->Cbuf_stuff;
  557. bufroom = pCh->Cbuf_strip - stuffIndex;
  558. break;
  559. default:
  560. return -5;
  561. }
  562. if (--bufroom < 0) {
  563. bufroom += maxBuff;
  564. }
  565. ip2trace (CHANN, ITRC_QUEUE, 2, 1, bufroom );
  566. // Check for overflow
  567. if (totalsize <= bufroom) {
  568. // Normal Expected path - We still hold LOCK
  569. break; /* from for()- Enough room: goto proceed */
  570. }
  571. }
  572. ip2trace (CHANN, ITRC_QUEUE, 3, 1, totalsize );
  573. // Prepare to wait for buffers to empty
  574. WRITE_UNLOCK_IRQRESTORE(lock_var_p,flags); 
  575. serviceOutgoingFifo(pB); // Dump what we got
  576. if (timeout == 0) {
  577. return 0;   // Tired of waiting
  578. }
  579. if (timeout > 0)
  580. timeout--;   // So negative values == forever
  581. if (!in_interrupt()) {
  582. current->state = TASK_INTERRUPTIBLE;
  583. schedule_timeout(1); // short nap 
  584. } else {
  585. // we cannot sched/sleep in interrrupt silly
  586. return 0;   
  587. }
  588. if (signal_pending(current)) {
  589. return 0;   // Wake up! Time to die!!!
  590. }
  591. ip2trace (CHANN, ITRC_QUEUE, 4, 0 );
  592. } // end of for(;;)
  593. // At this point we have room and the lock - stick them in.
  594. channel = pCh->infl.hd.i2sChannel;
  595. pInsert = &pBuf[stuffIndex];     // Pointer to start of packet
  596. pDest = CMD_OF(pInsert);         // Pointer to start of command
  597. // When we start counting, the block is the size of the header
  598. for (blocksize = sizeof(i2CmdHeader), count = nCommands,
  599. lastended = 0, ppCs = &pCs0;
  600. count;
  601. count--, ppCs++)
  602. {
  603. pCs = *ppCs;         // Points to command protocol structure
  604. // If this is a bookmark request command, post the fact that a bookmark
  605. // request is pending. NOTE THIS TRICK ONLY WORKS BECAUSE CMD_BMARK_REQ
  606. // has no parameters!  The more general solution would be to reference
  607. // pCs->cmd[0].
  608. if (pCs == CMD_BMARK_REQ) {
  609. pCh->bookMarks++;
  610. ip2trace (CHANN, ITRC_DRAIN, 30, 1, pCh->bookMarks );
  611. }
  612. cnt = pCs->length;
  613. // If this command would put us over the maximum block size or 
  614. // if the last command had to be at the end of a block, we end
  615. // the existing block here and start a new one.
  616. if ((blocksize + cnt > maxBlock) || lastended) {
  617. ip2trace (CHANN, ITRC_QUEUE, 5, 0 );
  618. PTYPE_OF(pInsert) = type;
  619. CHANNEL_OF(pInsert) = channel;
  620. // count here does not include the header
  621. CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader);
  622. stuffIndex += blocksize;
  623. if(stuffIndex >= maxBuff) {
  624. stuffIndex = 0;
  625. pInsert = pBuf;
  626. }
  627. pInsert = &pBuf[stuffIndex];  // Pointer to start of next pkt
  628. pDest = CMD_OF(pInsert);
  629. blocksize = sizeof(i2CmdHeader);
  630. }
  631. // Now we know there is room for this one in the current block
  632. blocksize += cnt;       // Total bytes in this command
  633. pSource = pCs->cmd;     // Copy the command into the buffer
  634. while (cnt--) {
  635. *pDest++ = *pSource++;
  636. }
  637. // If this command had to end a block, then we will make sure to account
  638. // for it should there be any more blocks.
  639. lastended = pCs->flags & END;
  640. } // end for
  641. // Clean up the final block by writing header, etc
  642. PTYPE_OF(pInsert) = type;
  643. CHANNEL_OF(pInsert) = channel;
  644. // count here does not include the header
  645. CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader);
  646. stuffIndex += blocksize;
  647. if(stuffIndex >= maxBuff) {
  648. stuffIndex = 0;
  649. pInsert = pBuf;
  650. }
  651. // Updates the index, and post the need for service. When adding these to
  652. // the queue of channels, we turn off the interrupt while doing so,
  653. // because at interrupt level we might want to push a channel back to the
  654. // end of the queue.
  655. switch(type)
  656. {
  657. case PTYPE_INLINE:
  658. pCh->Obuf_stuff = stuffIndex;  // Store buffer pointer
  659. WRITE_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags); 
  660. pB->debugInlineQueued++;
  661. // Add the channel pointer to list of channels needing service (first
  662. // come...), if it's not already there.
  663. i2QueueNeeds(pB, pCh, NEED_INLINE);
  664. break;
  665. case PTYPE_BYPASS:
  666. pCh->Cbuf_stuff = stuffIndex;  // Store buffer pointer
  667. WRITE_UNLOCK_IRQRESTORE(&pCh->Cbuf_spinlock,flags); 
  668. pB->debugBypassQueued++;
  669. // Add the channel pointer to list of channels needing service (first
  670. // come...), if it's not already there.
  671. i2QueueNeeds(pB, pCh, NEED_BYPASS);
  672. break;
  673. }
  674. ip2trace (CHANN, ITRC_QUEUE, ITRC_RETURN, 1, nCommands );
  675. return nCommands; // Good status: number of commands sent
  676. }
  677. //******************************************************************************
  678. // Function:   i2GetStatus(pCh,resetBits)
  679. // Parameters: Pointer to a channel structure
  680. //             Bit map of status bits to clear
  681. // Returns:    Bit map of current status bits
  682. //
  683. // Description:
  684. // Returns the state of data set signals, and whether a break has been received,
  685. // (see i2lib.h for bit-mapped result). resetBits is a bit-map of any status
  686. // bits to be cleared: I2_BRK, I2_PAR, I2_FRA, I2_OVR,... These are cleared
  687. // AFTER the condition is passed. If pCh does not point to a valid channel,
  688. // returns -1 (which would be impossible otherwise.
  689. //******************************************************************************
  690. static int
  691. i2GetStatus(i2ChanStrPtr pCh, int resetBits)
  692. {
  693. unsigned short status;
  694. i2eBordStrPtr pB;
  695. ip2trace (CHANN, ITRC_STATUS, ITRC_ENTER, 2, pCh->dataSetIn, resetBits );
  696. // Make sure the channel exists, otherwise do nothing */
  697. if ( !i2Validate ( pCh ) )
  698. return -1;
  699. pB = pCh->pMyBord;
  700. status = pCh->dataSetIn;
  701. // Clear any specified error bits: but note that only actual error bits can
  702. // be cleared, regardless of the value passed.
  703. if (resetBits)
  704. {
  705. pCh->dataSetIn &= ~(resetBits & (I2_BRK | I2_PAR | I2_FRA | I2_OVR));
  706. pCh->dataSetIn &= ~(I2_DDCD | I2_DCTS | I2_DDSR | I2_DRI);
  707. }
  708. ip2trace (CHANN, ITRC_STATUS, ITRC_RETURN, 1, pCh->dataSetIn );
  709. return status;
  710. }
  711. //******************************************************************************
  712. // Function:   i2Input(pChpDest,count)
  713. // Parameters: Pointer to a channel structure
  714. //             Pointer to data buffer
  715. //             Number of bytes to read
  716. // Returns:    Number of bytes read, or -1 for error
  717. //
  718. // Description:
  719. // Strips data from the input buffer and writes it to pDest. If there is a
  720. // collosal blunder, (invalid structure pointers or the like), returns -1.
  721. // Otherwise, returns the number of bytes read.
  722. //******************************************************************************
  723. static int
  724. i2Input(i2ChanStrPtr pCh)
  725. {
  726. int amountToMove;
  727. unsigned short stripIndex;
  728. int count;
  729. unsigned long flags = 0;
  730. ip2trace (CHANN, ITRC_INPUT, ITRC_ENTER, 0);
  731. // Ensure channel structure seems real
  732. if ( !i2Validate( pCh ) ) {
  733. count = -1;
  734. goto i2Input_exit;
  735. }
  736. WRITE_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags);
  737. // initialize some accelerators and private copies
  738. stripIndex = pCh->Ibuf_strip;
  739. count = pCh->Ibuf_stuff - stripIndex;
  740. // If buffer is empty or requested data count was 0, (trivial case) return
  741. // without any further thought.
  742. if ( count == 0 ) {
  743. WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);
  744. goto i2Input_exit;
  745. }
  746. // Adjust for buffer wrap
  747. if ( count < 0 ) {
  748. count += IBUF_SIZE;
  749. }
  750. // Don't give more than can be taken by the line discipline
  751. amountToMove = pCh->pTTY->ldisc.receive_room( pCh->pTTY );
  752. if (count > amountToMove) {
  753. count = amountToMove;
  754. }
  755. // How much could we copy without a wrap?
  756. amountToMove = IBUF_SIZE - stripIndex;
  757. if (amountToMove > count) {
  758. amountToMove = count;
  759. }
  760. // Move the first block
  761. pCh->pTTY->ldisc.receive_buf( pCh->pTTY, 
  762.  &(pCh->Ibuf[stripIndex]), NULL, amountToMove );
  763. // If we needed to wrap, do the second data move
  764. if (count > amountToMove) {
  765. pCh->pTTY->ldisc.receive_buf( pCh->pTTY, 
  766.  pCh->Ibuf, NULL, count - amountToMove );
  767. }
  768. // Bump and wrap the stripIndex all at once by the amount of data read. This
  769. // method is good regardless of whether the data was in one or two pieces.
  770. stripIndex += count;
  771. if (stripIndex >= IBUF_SIZE) {
  772. stripIndex -= IBUF_SIZE;
  773. }
  774. pCh->Ibuf_strip = stripIndex;
  775. // Update our flow control information and possibly queue ourselves to send
  776. // it, depending on how much data has been stripped since the last time a
  777. // packet was sent.
  778. pCh->infl.asof += count;
  779. if ((pCh->sinceLastFlow += count) >= pCh->whenSendFlow) {
  780. pCh->sinceLastFlow -= pCh->whenSendFlow;
  781. WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);
  782. i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);
  783. } else {
  784. WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);
  785. }
  786. i2Input_exit:
  787. ip2trace (CHANN, ITRC_INPUT, ITRC_RETURN, 1, count);
  788. return count;
  789. }
  790. //******************************************************************************
  791. // Function:   i2InputFlush(pCh)
  792. // Parameters: Pointer to a channel structure
  793. // Returns:    Number of bytes stripped, or -1 for error
  794. //
  795. // Description:
  796. // Strips any data from the input buffer. If there is a collosal blunder,
  797. // (invalid structure pointers or the like), returns -1. Otherwise, returns the
  798. // number of bytes stripped.
  799. //******************************************************************************
  800. static int
  801. i2InputFlush(i2ChanStrPtr pCh)
  802. {
  803. int count;
  804. unsigned long flags;
  805. // Ensure channel structure seems real
  806. if ( !i2Validate ( pCh ) )
  807. return -1;
  808. ip2trace (CHANN, ITRC_INPUT, 10, 0);
  809. WRITE_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags);
  810. count = pCh->Ibuf_stuff - pCh->Ibuf_strip;
  811. // Adjust for buffer wrap
  812. if (count < 0) {
  813. count += IBUF_SIZE;
  814. }
  815. // Expedient way to zero out the buffer
  816. pCh->Ibuf_strip = pCh->Ibuf_stuff;
  817. // Update our flow control information and possibly queue ourselves to send
  818. // it, depending on how much data has been stripped since the last time a
  819. // packet was sent.
  820. pCh->infl.asof += count;
  821. if ( (pCh->sinceLastFlow += count) >= pCh->whenSendFlow )
  822. {
  823. pCh->sinceLastFlow -= pCh->whenSendFlow;
  824. WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);
  825. i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);
  826. } else {
  827. WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);
  828. }
  829. ip2trace (CHANN, ITRC_INPUT, 19, 1, count);
  830. return count;
  831. }
  832. //******************************************************************************
  833. // Function:   i2InputAvailable(pCh)
  834. // Parameters: Pointer to a channel structure
  835. // Returns:    Number of bytes available, or -1 for error
  836. //
  837. // Description:
  838. // If there is a collosal blunder, (invalid structure pointers or the like),
  839. // returns -1. Otherwise, returns the number of bytes stripped. Otherwise,
  840. // returns the number of bytes available in the buffer.
  841. //******************************************************************************
  842. #if 0
  843. static int
  844. i2InputAvailable(i2ChanStrPtr pCh)
  845. {
  846. int count;
  847. // Ensure channel structure seems real
  848. if ( !i2Validate ( pCh ) ) return -1;
  849. // initialize some accelerators and private copies
  850. READ_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,flags);
  851. count = pCh->Ibuf_stuff - pCh->Ibuf_strip;
  852. READ_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,flags);
  853. // Adjust for buffer wrap
  854. if (count < 0)
  855. {
  856. count += IBUF_SIZE;
  857. }
  858. return count;
  859. }
  860. #endif 
  861. //******************************************************************************
  862. // Function:   i2Output(pCh, pSource, count)
  863. // Parameters: Pointer to channel structure
  864. //             Pointer to source data
  865. //             Number of bytes to send
  866. // Returns:    Number of bytes sent, or -1 for error
  867. //
  868. // Description:
  869. // Queues the data at pSource to be sent as data packets to the board. If there
  870. // is a collosal blunder, (invalid structure pointers or the like), returns -1.
  871. // Otherwise, returns the number of bytes written. What if there is not enough
  872. // room for all the data? If pCh->channelOptions & CO_NBLOCK_WRITE is set, then
  873. // we transfer as many characters as we can now, then return. If this bit is
  874. // clear (default), routine will spin along until all the data is buffered.
  875. // Should this occur, the 1-ms delay routine is called while waiting to avoid
  876. // applications that one cannot break out of.
  877. //******************************************************************************
  878. static int
  879. i2Output(i2ChanStrPtr pCh, const char *pSource, int count, int user )
  880. {
  881. i2eBordStrPtr pB;
  882. unsigned char *pInsert;
  883. int amountToMove;
  884. int countOriginal = count;
  885. unsigned short channel;
  886. unsigned short stuffIndex;
  887. unsigned long flags;
  888. int rc = 0;
  889. int bailout = 10;
  890. ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, user );
  891. // Ensure channel structure seems real
  892. if ( !i2Validate ( pCh ) ) 
  893. return -1;
  894. // initialize some accelerators and private copies
  895. pB = pCh->pMyBord;
  896. channel = pCh->infl.hd.i2sChannel;
  897. // If the board has gone fatal, return bad, and also hit the trap routine if
  898. // it exists.
  899. if (pB->i2eFatal) {
  900. if (pB->i2eFatalTrap) {
  901. (*(pB)->i2eFatalTrap)(pB);
  902. }
  903. return -1;
  904. }
  905. // Proceed as though we would do everything
  906. while ( count > 0 ) {
  907. // How much room in output buffer is there?
  908. READ_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags);
  909. amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;
  910. READ_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags);
  911. if (amountToMove < 0) {
  912. amountToMove += OBUF_SIZE;
  913. }
  914. // Subtract off the headers size and see how much room there is for real
  915. // data. If this is negative, we will discover later.
  916. amountToMove -= sizeof (i2DataHeader);
  917. // Don't move more (now) than can go in a single packet
  918. if ( amountToMove > (int)(MAX_OBUF_BLOCK - sizeof(i2DataHeader)) ) {
  919. amountToMove = MAX_OBUF_BLOCK - sizeof(i2DataHeader);
  920. }
  921. // Don't move more than the count we were given
  922. if (amountToMove > count) {
  923. amountToMove = count;
  924. }
  925. // Now we know how much we must move: NB because the ring buffers have
  926. // an overflow area at the end, we needn't worry about wrapping in the
  927. // middle of a packet.
  928. // Small WINDOW here with no LOCK but I can't call Flush with LOCK
  929. // We would be flushing (or ending flush) anyway
  930. ip2trace (CHANN, ITRC_OUTPUT, 10, 1, amountToMove );
  931. if ( !(pCh->flush_flags && i2RetryFlushOutput(pCh) ) 
  932. && amountToMove > 0 )
  933. {
  934. WRITE_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags);
  935. stuffIndex = pCh->Obuf_stuff;
  936.       
  937. // Had room to move some data: don't know whether the block size,
  938. // buffer space, or what was the limiting factor...
  939. pInsert = &(pCh->Obuf[stuffIndex]);
  940. // Set up the header
  941. CHANNEL_OF(pInsert)     = channel;
  942. PTYPE_OF(pInsert)       = PTYPE_DATA;
  943. TAG_OF(pInsert)         = 0;
  944. ID_OF(pInsert)          = ID_ORDINARY_DATA;
  945. DATA_COUNT_OF(pInsert)  = amountToMove;
  946. // Move the data
  947. if ( user ) {
  948. COPY_FROM_USER(rc, (char*)(DATA_OF(pInsert)), pSource,
  949. amountToMove );
  950. } else {
  951. memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove );
  952. }
  953. // Adjust pointers and indices
  954. pSource += amountToMove;
  955. pCh->Obuf_char_count += amountToMove;
  956. stuffIndex  += amountToMove + sizeof(i2DataHeader);
  957. count  -= amountToMove;
  958. if (stuffIndex >= OBUF_SIZE) {
  959. stuffIndex = 0;
  960. }
  961. pCh->Obuf_stuff = stuffIndex;
  962. WRITE_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags);
  963. ip2trace (CHANN, ITRC_OUTPUT, 13, 1, stuffIndex );
  964. } else {
  965. // Cannot move data
  966. // becuz we need to stuff a flush 
  967. // or amount to move is <= 0
  968. ip2trace(CHANN, ITRC_OUTPUT, 14, 3,
  969. amountToMove,  pB->i2eFifoRemains,
  970. pB->i2eWaitingForEmptyFifo );
  971. // Put this channel back on queue
  972. // this ultimatly gets more data or wakes write output
  973. i2QueueNeeds(pB, pCh, NEED_INLINE);
  974. if ( pB->i2eWaitingForEmptyFifo ) {
  975. ip2trace (CHANN, ITRC_OUTPUT, 16, 0 );
  976. // or schedule
  977. if (!in_interrupt()) {
  978. ip2trace (CHANN, ITRC_OUTPUT, 61, 0 );
  979. current->state = TASK_INTERRUPTIBLE;
  980. schedule_timeout(2);
  981. if (signal_pending(current)) {
  982. break;
  983. }
  984. continue;
  985. } else {
  986. ip2trace (CHANN, ITRC_OUTPUT, 62, 0 );
  987. // let interrupt in = WAS restore_flags()
  988. // We hold no lock nor is irq off anymore???
  989. break;
  990. }
  991. break;   // from while(count)
  992. }
  993. else if ( pB->i2eFifoRemains < 32 && !pB->i2eTxMailEmpty ( pB ) )
  994. {
  995. ip2trace (CHANN, ITRC_OUTPUT, 19, 2,
  996. pB->i2eFifoRemains,
  997. pB->i2eTxMailEmpty );
  998. break;   // from while(count)
  999. } else if ( pCh->channelNeeds & NEED_CREDIT ) {
  1000. ip2trace (CHANN, ITRC_OUTPUT, 22, 0 );
  1001. break;   // from while(count)
  1002. } else if ( --bailout) {
  1003. // Try to throw more things (maybe not us) in the fifo if we're
  1004. // not already waiting for it.
  1005. ip2trace (CHANN, ITRC_OUTPUT, 20, 0 );
  1006. serviceOutgoingFifo(pB);
  1007. //break;  CONTINUE;
  1008. } else {
  1009. ip2trace (CHANN, ITRC_OUTPUT, 21, 3,
  1010. pB->i2eFifoRemains,
  1011. pB->i2eOutMailWaiting,
  1012. pB->i2eWaitingForEmptyFifo );
  1013. break;   // from while(count)
  1014. }
  1015. }
  1016. } // End of while(count)
  1017. i2QueueNeeds(pB, pCh, NEED_INLINE);
  1018. // We drop through either when the count expires, or when there is some
  1019. // count left, but there was a non-blocking write.
  1020. if (countOriginal > count) {
  1021. ip2trace (CHANN, ITRC_OUTPUT, 17, 2, countOriginal, count );
  1022. serviceOutgoingFifo( pB );
  1023. }
  1024. ip2trace (CHANN, ITRC_OUTPUT, ITRC_RETURN, 2, countOriginal, count );
  1025. return countOriginal - count;
  1026. }
  1027. //******************************************************************************
  1028. // Function:   i2FlushOutput(pCh)
  1029. // Parameters: Pointer to a channel structure
  1030. // Returns:    Nothing
  1031. //
  1032. // Description:
  1033. // Sends bypass command to start flushing (waiting possibly forever until there
  1034. // is room), then sends inline command to stop flushing output, (again waiting
  1035. // possibly forever).
  1036. //******************************************************************************
  1037. static inline void
  1038. i2FlushOutput(i2ChanStrPtr pCh)
  1039. {
  1040. ip2trace (CHANN, ITRC_FLUSH, 1, 1, pCh->flush_flags );
  1041. if (pCh->flush_flags)
  1042. return;
  1043. if ( 1 != i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {
  1044. pCh->flush_flags = STARTFL_FLAG; // Failed - flag for later
  1045. ip2trace (CHANN, ITRC_FLUSH, 2, 0 );
  1046. } else if ( 1 != i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) ) {
  1047. pCh->flush_flags = STOPFL_FLAG; // Failed - flag for later
  1048. ip2trace (CHANN, ITRC_FLUSH, 3, 0 );
  1049. }
  1050. }
  1051. static int 
  1052. i2RetryFlushOutput(i2ChanStrPtr pCh)
  1053. {
  1054. int old_flags = pCh->flush_flags;
  1055. ip2trace (CHANN, ITRC_FLUSH, 14, 1, old_flags );
  1056. pCh->flush_flags = 0; // Clear flag so we can avoid recursion
  1057. // and queue the commands
  1058. if ( old_flags & STARTFL_FLAG ) {
  1059. if ( 1 == i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {
  1060. old_flags = STOPFL_FLAG; //Success - send stop flush
  1061. } else {
  1062. old_flags = STARTFL_FLAG; //Failure - Flag for retry later
  1063. }
  1064. ip2trace (CHANN, ITRC_FLUSH, 15, 1, old_flags );
  1065. }
  1066. if ( old_flags & STOPFL_FLAG ) {
  1067. if ( 1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) > 0 ) {
  1068. old_flags = 0; // Success - clear flags
  1069. }
  1070. ip2trace (CHANN, ITRC_FLUSH, 16, 1, old_flags );
  1071. }
  1072. pCh->flush_flags = old_flags;
  1073. ip2trace (CHANN, ITRC_FLUSH, 17, 1, old_flags );
  1074. return old_flags;
  1075. }
  1076. //******************************************************************************
  1077. // Function:   i2DrainOutput(pCh,timeout)
  1078. // Parameters: Pointer to a channel structure
  1079. //             Maximum period to wait
  1080. // Returns:    ?
  1081. //
  1082. // Description:
  1083. // Uses the bookmark request command to ask the board to send a bookmark back as
  1084. // soon as all the data is completely sent.
  1085. //******************************************************************************
  1086. static void
  1087. i2DrainWakeup(i2ChanStrPtr pCh)
  1088. {
  1089. ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires );
  1090. pCh->BookmarkTimer.expires = 0;
  1091. wake_up_interruptible( &pCh->pBookmarkWait );
  1092. }
  1093. static void
  1094. i2DrainOutput(i2ChanStrPtr pCh, int timeout)
  1095. {
  1096. wait_queue_t wait;
  1097. i2eBordStrPtr pB;
  1098. ip2trace (CHANN, ITRC_DRAIN, ITRC_ENTER, 1, pCh->BookmarkTimer.expires);
  1099. pB = pCh->pMyBord;
  1100. // If the board has gone fatal, return bad, 
  1101. // and also hit the trap routine if it exists.
  1102. if (pB->i2eFatal) {
  1103. if (pB->i2eFatalTrap) {
  1104. (*(pB)->i2eFatalTrap)(pB);
  1105. }
  1106. return;
  1107. }
  1108. if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) {
  1109. // One per customer (channel)
  1110. init_timer( &(pCh->BookmarkTimer) );
  1111. pCh->BookmarkTimer.expires  = jiffies + timeout;
  1112. pCh->BookmarkTimer.function = (void*)(unsigned long)i2DrainWakeup;
  1113. pCh->BookmarkTimer.data     = (unsigned long)pCh;
  1114. ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires );
  1115. add_timer( &(pCh->BookmarkTimer) );
  1116. }
  1117. i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ );
  1118. init_waitqueue_entry(&wait, current);
  1119. add_wait_queue(&(pCh->pBookmarkWait), &wait);
  1120. set_current_state( TASK_INTERRUPTIBLE );
  1121. serviceOutgoingFifo( pB );
  1122. schedule(); // Now we take our interruptible sleep on
  1123. // Clean up the queue
  1124. set_current_state( TASK_RUNNING );
  1125. remove_wait_queue(&(pCh->pBookmarkWait), &wait);
  1126. // if expires == 0 then timer poped, then do not need to del_timer
  1127. if ((timeout > 0) && pCh->BookmarkTimer.expires && 
  1128. (pCh->BookmarkTimer.expires > jiffies)) {
  1129. del_timer( &(pCh->BookmarkTimer) );
  1130. pCh->BookmarkTimer.expires = 0;
  1131. ip2trace (CHANN, ITRC_DRAIN, 3, 1, pCh->BookmarkTimer.expires );
  1132. }
  1133. ip2trace (CHANN, ITRC_DRAIN, ITRC_RETURN, 1, pCh->BookmarkTimer.expires );
  1134. return;
  1135. }
  1136. //******************************************************************************
  1137. // Function:   i2OutputFree(pCh)
  1138. // Parameters: Pointer to a channel structure
  1139. // Returns:    Space in output buffer
  1140. //
  1141. // Description:
  1142. // Returns -1 if very gross error. Otherwise returns the amount of bytes still
  1143. // free in the output buffer.
  1144. //******************************************************************************
  1145. static int
  1146. i2OutputFree(i2ChanStrPtr pCh)
  1147. {
  1148. int amountToMove;
  1149. unsigned long flags;
  1150. // Ensure channel structure seems real
  1151. if ( !i2Validate ( pCh ) ) {
  1152. return -1;
  1153. }
  1154. READ_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags);
  1155. amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;
  1156. READ_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags);
  1157. if (amountToMove < 0) {
  1158. amountToMove += OBUF_SIZE;
  1159. }
  1160. // If this is negative, we will discover later
  1161. amountToMove -= sizeof(i2DataHeader);
  1162. return (amountToMove < 0) ? 0 : amountToMove;
  1163. }
  1164. static void
  1165. ip2_owake( PTTY tp)
  1166. {
  1167. i2ChanStrPtr  pCh;
  1168. if (tp == NULL) return;
  1169. pCh = tp->driver_data;
  1170. ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags,
  1171. (1 << TTY_DO_WRITE_WAKEUP) );
  1172. wake_up_interruptible ( &tp->write_wait );
  1173. if ( ( tp->flags & (1 << TTY_DO_WRITE_WAKEUP) ) 
  1174.   && tp->ldisc.write_wakeup )
  1175. {
  1176. (tp->ldisc.write_wakeup) ( tp );
  1177. ip2trace (CHANN, ITRC_SICMD, 11, 0 );
  1178. }
  1179. }
  1180. static inline void
  1181. set_baud_params(i2eBordStrPtr pB) 
  1182. {
  1183. int i,j;
  1184. i2ChanStrPtr  *pCh;
  1185. pCh = (i2ChanStrPtr *) pB->i2eChannelPtr;
  1186. for (i = 0; i < ABS_MAX_BOXES; i++) {
  1187. if (pB->channelBtypes.bid_value[i]) {
  1188. if (BID_HAS_654(pB->channelBtypes.bid_value[i])) {
  1189. for (j = 0; j < ABS_BIGGEST_BOX; j++) {
  1190. if (pCh[i*16+j] == NULL)
  1191. break;
  1192. (pCh[i*16+j])->BaudBase    = 921600; // MAX for ST654
  1193. (pCh[i*16+j])->BaudDivisor = 96;
  1194. }
  1195. } else { // has cirrus cd1400
  1196. for (j = 0; j < ABS_BIGGEST_BOX; j++) {
  1197. if (pCh[i*16+j] == NULL)
  1198. break;
  1199. (pCh[i*16+j])->BaudBase    = 115200; // MAX for CD1400
  1200. (pCh[i*16+j])->BaudDivisor = 12;
  1201. }
  1202. }
  1203. }
  1204. }
  1205. }
  1206. //******************************************************************************
  1207. // Function:   i2StripFifo(pB)
  1208. // Parameters: Pointer to a board structure
  1209. // Returns:    ?
  1210. //
  1211. // Description:
  1212. // Strips all the available data from the incoming FIFO, identifies the type of
  1213. // packet, and either buffers the data or does what needs to be done.
  1214. //
  1215. // Note there is no overflow checking here: if the board sends more data than it
  1216. // ought to, we will not detect it here, but blindly overflow...
  1217. //******************************************************************************
  1218. // A buffer for reading in blocks for unknown channels
  1219. static unsigned char junkBuffer[IBUF_SIZE];
  1220. // A buffer to read in a status packet. Because of the size of the count field
  1221. // for these things, the maximum packet size must be less than MAX_CMD_PACK_SIZE
  1222. static unsigned char cmdBuffer[MAX_CMD_PACK_SIZE + 4];
  1223. // This table changes the bit order from MSR order given by STAT_MODEM packet to
  1224. // status bits used in our library.
  1225. static char xlatDss[16] = {
  1226. 0      | 0     | 0      | 0      ,
  1227. 0      | 0     | 0      | I2_CTS ,
  1228. 0      | 0     | I2_DSR | 0      ,
  1229. 0      | 0     | I2_DSR | I2_CTS ,
  1230. 0      | I2_RI | 0      | 0      ,
  1231. 0      | I2_RI | 0      | I2_CTS ,
  1232. 0      | I2_RI | I2_DSR | 0      ,
  1233. 0      | I2_RI | I2_DSR | I2_CTS ,
  1234. I2_DCD | 0     | 0      | 0      ,
  1235. I2_DCD | 0     | 0      | I2_CTS ,
  1236. I2_DCD | 0     | I2_DSR | 0      ,
  1237. I2_DCD | 0     | I2_DSR | I2_CTS ,
  1238. I2_DCD | I2_RI | 0      | 0      ,
  1239. I2_DCD | I2_RI | 0      | I2_CTS ,
  1240. I2_DCD | I2_RI | I2_DSR | 0      ,
  1241. I2_DCD | I2_RI | I2_DSR | I2_CTS };
  1242. static inline void
  1243. i2StripFifo(i2eBordStrPtr pB)
  1244. {
  1245. i2ChanStrPtr pCh;
  1246. int channel;
  1247. int count;
  1248. unsigned short stuffIndex;
  1249. int amountToRead;
  1250. unsigned char *pc, *pcLimit;
  1251. unsigned char uc;
  1252. unsigned char dss_change;
  1253. unsigned long bflags,cflags;
  1254. // ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_ENTER, 0 );
  1255. while (HAS_INPUT(pB)) {
  1256. // ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 2, 0 );
  1257. // Process packet from fifo a one atomic unit
  1258. WRITE_LOCK_IRQSAVE(&pB->read_fifo_spinlock,bflags);
  1259.    
  1260. // The first word (or two bytes) will have channel number and type of
  1261. // packet, possibly other information
  1262. pB->i2eLeadoffWord[0] = iiReadWord(pB);
  1263. switch(PTYPE_OF(pB->i2eLeadoffWord))
  1264. {
  1265. case PTYPE_DATA:
  1266. pB->got_input = 1;
  1267. // ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 3, 0 );
  1268. channel = CHANNEL_OF(pB->i2eLeadoffWord); /* Store channel */
  1269. count = iiReadWord(pB);          /* Count is in the next word */
  1270. // NEW: Check the count for sanity! Should the hardware fail, our death
  1271. // is more pleasant. While an oversize channel is acceptable (just more
  1272. // than the driver supports), an over-length count clearly means we are
  1273. // sick!
  1274. if ( ((unsigned int)count) > IBUF_SIZE ) {
  1275. pB->i2eFatal = 2;
  1276. WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags);
  1277. return;     /* Bail out ASAP */
  1278. }
  1279. // Channel is illegally big ?
  1280. if ((channel >= pB->i2eChannelCnt) ||
  1281. (NULL==(pCh = ((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])))
  1282. {
  1283. iiReadBuf(pB, junkBuffer, count);
  1284. WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags);
  1285. break;         /* From switch: ready for next packet */
  1286. }
  1287. // Channel should be valid, then
  1288. // If this is a hot-key, merely post its receipt for now. These are
  1289. // always supposed to be 1-byte packets, so we won't even check the
  1290. // count. Also we will post an acknowledgement to the board so that
  1291. // more data can be forthcoming. Note that we are not trying to use
  1292. // these sequences in this driver, merely to robustly ignore them.
  1293. if(ID_OF(pB->i2eLeadoffWord) == ID_HOT_KEY)
  1294. {
  1295. pCh->hotKeyIn = iiReadWord(pB) & 0xff;
  1296. WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags);
  1297. i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_HOTACK);
  1298. break;   /* From the switch: ready for next packet */
  1299. }
  1300. // Normal data! We crudely assume there is room for the data in our
  1301. // buffer because the board wouldn't have exceeded his credit limit.
  1302. WRITE_LOCK_IRQSAVE(&pCh->Ibuf_spinlock,cflags);
  1303. // We have 2 locks now
  1304. stuffIndex = pCh->Ibuf_stuff;
  1305. amountToRead = IBUF_SIZE - stuffIndex;
  1306. if (amountToRead > count)
  1307. amountToRead = count;
  1308. // stuffIndex would have been already adjusted so there would 
  1309. // always be room for at least one, and count is always at least
  1310. // one.
  1311. iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead);
  1312. pCh->icount.rx += amountToRead;
  1313. // Update the stuffIndex by the amount of data moved. Note we could
  1314. // never ask for more data than would just fit. However, we might
  1315. // have read in one more byte than we wanted because the read
  1316. // rounds up to even bytes. If this byte is on the end of the
  1317. // packet, and is padding, we ignore it. If the byte is part of
  1318. // the actual data, we need to move it.
  1319. stuffIndex += amountToRead;
  1320. if (stuffIndex >= IBUF_SIZE) {
  1321. if ((amountToRead & 1) && (count > amountToRead)) {
  1322. pCh->Ibuf[0] = pCh->Ibuf[IBUF_SIZE];
  1323. amountToRead++;
  1324. stuffIndex = 1;
  1325. } else {
  1326. stuffIndex = 0;
  1327. }
  1328. }
  1329. // If there is anything left over, read it as well
  1330. if (count > amountToRead) {
  1331. amountToRead = count - amountToRead;
  1332. iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead);
  1333. pCh->icount.rx += amountToRead;
  1334. stuffIndex += amountToRead;
  1335. }
  1336. // Update stuff index
  1337. pCh->Ibuf_stuff = stuffIndex;
  1338. WRITE_UNLOCK_IRQRESTORE(&pCh->Ibuf_spinlock,cflags);
  1339. WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags);
  1340. #ifdef USE_IQ
  1341. queue_task(&pCh->tqueue_input, &tq_immediate);
  1342. mark_bh(IMMEDIATE_BH);
  1343. #else
  1344. do_input(pCh);
  1345. #endif
  1346. // Note we do not need to maintain any flow-control credits at this
  1347. // time:  if we were to increment .asof and decrement .room, there
  1348. // would be no net effect. Instead, when we strip data, we will
  1349. // increment .asof and leave .room unchanged.
  1350. break;   // From switch: ready for next packet
  1351. case PTYPE_STATUS:
  1352. ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 4, 0 );
  1353.       
  1354. count = CMD_COUNT_OF(pB->i2eLeadoffWord);
  1355. iiReadBuf(pB, cmdBuffer, count);
  1356. // We can release early with buffer grab
  1357. WRITE_UNLOCK_IRQRESTORE(&pB->read_fifo_spinlock,bflags);
  1358. pc = cmdBuffer;
  1359. pcLimit = &(cmdBuffer[count]);
  1360. while (pc < pcLimit) {
  1361. channel = *pc++;
  1362. ip2trace (channel, ITRC_SFIFO, 7, 2, channel, *pc );
  1363. /* check for valid channel */
  1364. if (channel < pB->i2eChannelCnt
  1365.  && 
  1366.  (pCh = (((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])) != NULL
  1367. )
  1368. {
  1369. dss_change = 0;
  1370. switch (uc = *pc++)
  1371. {
  1372. /* Breaks and modem signals are easy: just update status */
  1373. case STAT_CTS_UP:
  1374. if ( !(pCh->dataSetIn & I2_CTS) )
  1375. {
  1376. pCh->dataSetIn |= I2_DCTS;
  1377. pCh->icount.cts++;
  1378. dss_change = 1;
  1379. }
  1380. pCh->dataSetIn |= I2_CTS;
  1381. break;
  1382. case STAT_CTS_DN:
  1383. if ( pCh->dataSetIn & I2_CTS )
  1384. {
  1385. pCh->dataSetIn |= I2_DCTS;
  1386. pCh->icount.cts++;
  1387. dss_change = 1;
  1388. }
  1389. pCh->dataSetIn &= ~I2_CTS;
  1390. break;
  1391. case STAT_DCD_UP:
  1392. ip2trace (channel, ITRC_MODEM, 1, 1, pCh->dataSetIn );
  1393. if ( !(pCh->dataSetIn & I2_DCD) )
  1394. {
  1395. ip2trace (CHANN, ITRC_MODEM, 2, 0 );
  1396. pCh->dataSetIn |= I2_DDCD;
  1397. pCh->icount.dcd++;
  1398. dss_change = 1;
  1399. }
  1400. pCh->dataSetIn |= I2_DCD;
  1401. ip2trace (channel, ITRC_MODEM, 3, 1, pCh->dataSetIn );
  1402. break;
  1403. case STAT_DCD_DN:
  1404. ip2trace (channel, ITRC_MODEM, 4, 1, pCh->dataSetIn );
  1405. if ( pCh->dataSetIn & I2_DCD )
  1406. {
  1407. ip2trace (channel, ITRC_MODEM, 5, 0 );
  1408. pCh->dataSetIn |= I2_DDCD;
  1409. pCh->icount.dcd++;
  1410. dss_change = 1;
  1411. }
  1412. pCh->dataSetIn &= ~I2_DCD;
  1413. ip2trace (channel, ITRC_MODEM, 6, 1, pCh->dataSetIn );
  1414. break;
  1415. case STAT_DSR_UP:
  1416. if ( !(pCh->dataSetIn & I2_DSR) )
  1417. {
  1418. pCh->dataSetIn |= I2_DDSR;
  1419. pCh->icount.dsr++;
  1420. dss_change = 1;
  1421. }
  1422. pCh->dataSetIn |= I2_DSR;
  1423. break;
  1424. case STAT_DSR_DN:
  1425. if ( pCh->dataSetIn & I2_DSR )
  1426. {
  1427. pCh->dataSetIn |= I2_DDSR;
  1428. pCh->icount.dsr++;
  1429. dss_change = 1;
  1430. }
  1431. pCh->dataSetIn &= ~I2_DSR;
  1432. break;
  1433. case STAT_RI_UP:
  1434. if ( !(pCh->dataSetIn & I2_RI) )
  1435. {
  1436. pCh->dataSetIn |= I2_DRI;
  1437. pCh->icount.rng++;
  1438. dss_change = 1;
  1439. }
  1440. pCh->dataSetIn |= I2_RI ;
  1441. break;
  1442. case STAT_RI_DN:
  1443. // to be compat with serial.c
  1444. //if ( pCh->dataSetIn & I2_RI )
  1445. //{
  1446. // pCh->dataSetIn |= I2_DRI;
  1447. // pCh->icount.rng++; 
  1448. // dss_change = 1;
  1449. //}
  1450. pCh->dataSetIn &= ~I2_RI ;
  1451. break;
  1452. case STAT_BRK_DET:
  1453. pCh->dataSetIn |= I2_BRK;
  1454. pCh->icount.brk++;
  1455. dss_change = 1;
  1456. break;
  1457. // Bookmarks? one less request we're waiting for
  1458. case STAT_BMARK:
  1459. pCh->bookMarks--;
  1460. if (pCh->bookMarks <= 0 ) {
  1461. pCh->bookMarks = 0;
  1462. wake_up_interruptible( &pCh->pBookmarkWait );
  1463. ip2trace (channel, ITRC_DRAIN, 20, 1, pCh->BookmarkTimer.expires );
  1464. }
  1465. break;
  1466. // Flow control packets? Update the new credits, and if
  1467. // someone was waiting for output, queue him up again.
  1468. case STAT_FLOW:
  1469. pCh->outfl.room =
  1470. ((flowStatPtr)pc)->room -
  1471. (pCh->outfl.asof - ((flowStatPtr)pc)->asof);
  1472. ip2trace (channel, ITRC_STFLW, 1, 1, pCh->outfl.room );
  1473. if (pCh->channelNeeds & NEED_CREDIT)
  1474. {
  1475. ip2trace (channel, ITRC_STFLW, 2, 1, pCh->channelNeeds);
  1476. pCh->channelNeeds &= ~NEED_CREDIT;
  1477. i2QueueNeeds(pB, pCh, NEED_INLINE);
  1478. if ( pCh->pTTY )
  1479. ip2_owake(pCh->pTTY);
  1480. }
  1481. ip2trace (channel, ITRC_STFLW, 3, 1, pCh->channelNeeds);
  1482. pc += sizeof(flowStat);
  1483. break;
  1484. /* Special packets: */
  1485. /* Just copy the information into the channel structure */
  1486. case STAT_STATUS:
  1487. pCh->channelStatus = *((debugStatPtr)pc);
  1488. pc += sizeof(debugStat);
  1489. break;
  1490. case STAT_TXCNT:
  1491. pCh->channelTcount = *((cntStatPtr)pc);
  1492. pc += sizeof(cntStat);
  1493. break;
  1494. case STAT_RXCNT:
  1495. pCh->channelRcount = *((cntStatPtr)pc);
  1496. pc += sizeof(cntStat);
  1497. break;
  1498. case STAT_BOXIDS:
  1499. pB->channelBtypes = *((bidStatPtr)pc);
  1500. pc += sizeof(bidStat);
  1501. set_baud_params(pB);
  1502. break;
  1503. case STAT_HWFAIL:
  1504. i2QueueCommands (PTYPE_INLINE, pCh, 0, 1, CMD_HW_TEST);
  1505. pCh->channelFail = *((failStatPtr)pc);
  1506. pc += sizeof(failStat);
  1507. break;
  1508. /* No explicit match? then
  1509.  * Might be an error packet...
  1510.  */
  1511. default:
  1512. switch (uc & STAT_MOD_ERROR)
  1513. {
  1514. case STAT_ERROR:
  1515. if (uc & STAT_E_PARITY) {
  1516. pCh->dataSetIn |= I2_PAR;
  1517. pCh->icount.parity++;
  1518. }
  1519. if (uc & STAT_E_FRAMING){
  1520. pCh->dataSetIn |= I2_FRA;
  1521. pCh->icount.frame++;
  1522. }
  1523. if (uc & STAT_E_OVERRUN){
  1524. pCh->dataSetIn |= I2_OVR;
  1525. pCh->icount.overrun++;
  1526. }
  1527. break;
  1528. case STAT_MODEM:
  1529. // the answer to DSS_NOW request (not change)
  1530. pCh->dataSetIn = (pCh->dataSetIn
  1531. & ~(I2_RI | I2_CTS | I2_DCD | I2_DSR) )
  1532. | xlatDss[uc & 0xf];
  1533. wake_up_interruptible ( &pCh->dss_now_wait );
  1534. default:
  1535. break;
  1536. }
  1537. }  /* End of switch on status type */
  1538. if (dss_change) {
  1539. #ifdef USE_IQ
  1540. queue_task(&pCh->tqueue_status, &tq_immediate);
  1541. mark_bh(IMMEDIATE_BH);
  1542. #else
  1543. do_status(pCh);
  1544. #endif
  1545. }
  1546. }
  1547. else  /* Or else, channel is invalid */
  1548. {
  1549. // Even though the channel is invalid, we must test the
  1550. // status to see how much additional data it has (to be
  1551. // skipped)
  1552. switch (*pc++)
  1553. {
  1554. case STAT_FLOW:
  1555. pc += 4;    /* Skip the data */
  1556. break;
  1557. default:
  1558. break;
  1559. }
  1560. }
  1561. }  // End of while (there is still some status packet left)
  1562. break;
  1563. default: // Neither packet? should be impossible
  1564. ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 5, 1,
  1565. PTYPE_OF(pB->i2eLeadoffWord) );
  1566. break;
  1567. }  // End of switch on type of packets
  1568. } //while(board HAS_INPUT)
  1569. ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_RETURN, 0 );
  1570. // Send acknowledgement to the board even if there was no data!
  1571. pB->i2eOutMailWaiting |= MB_IN_STRIPPED;
  1572. return;
  1573. }
  1574. //******************************************************************************
  1575. // Function:   i2Write2Fifo(pB,address,count)
  1576. // Parameters: Pointer to a board structure, source address, byte count
  1577. // Returns:    bytes written
  1578. //
  1579. // Description:
  1580. //  Writes count bytes to board io address(implied) from source
  1581. //  Adjusts count, leaves reserve for next time around bypass cmds
  1582. //******************************************************************************
  1583. static int
  1584. i2Write2Fifo(i2eBordStrPtr pB, unsigned char *source, int count,int reserve)
  1585. {
  1586. int rc = 0;
  1587. unsigned long flags;
  1588. WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags);
  1589. if (!pB->i2eWaitingForEmptyFifo) {
  1590. if (pB->i2eFifoRemains > (count+reserve)) {
  1591. pB->i2eFifoRemains -= count;
  1592. iiWriteBuf(pB, source, count);
  1593. pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
  1594. rc =  count;
  1595. }
  1596. }
  1597. WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);
  1598. return rc;
  1599. }
  1600. //******************************************************************************
  1601. // Function:   i2StuffFifoBypass(pB)
  1602. // Parameters: Pointer to a board structure
  1603. // Returns:    Nothing
  1604. //
  1605. // Description:
  1606. // Stuffs as many bypass commands into the fifo as possible. This is simpler
  1607. // than stuffing data or inline commands to fifo, since we do not have
  1608. // flow-control to deal with.
  1609. //******************************************************************************
  1610. static inline void
  1611. i2StuffFifoBypass(i2eBordStrPtr pB)
  1612. {
  1613. i2ChanStrPtr pCh;
  1614. unsigned char *pRemove;
  1615. unsigned short stripIndex;
  1616. unsigned short packetSize;
  1617. unsigned short paddedSize;
  1618. unsigned short notClogged = 1;
  1619. unsigned long flags;
  1620. int bailout = 1000;
  1621. // Continue processing so long as there are entries, or there is room in the
  1622. // fifo. Each entry represents a channel with something to do.
  1623. while ( --bailout && notClogged && 
  1624. (NULL != (pCh = i2DeQueueNeeds(pB,NEED_BYPASS))))
  1625. {
  1626. WRITE_LOCK_IRQSAVE(&pCh->Cbuf_spinlock,flags);
  1627. stripIndex = pCh->Cbuf_strip;
  1628. // as long as there are packets for this channel...
  1629. while (stripIndex != pCh->Cbuf_stuff) {
  1630. pRemove = &(pCh->Cbuf[stripIndex]);
  1631. packetSize = CMD_COUNT_OF(pRemove) + sizeof(i2CmdHeader);
  1632. paddedSize = ROUNDUP(packetSize);
  1633. if (paddedSize > 0) {
  1634. if ( 0 == i2Write2Fifo(pB, pRemove, paddedSize,0)) {
  1635. notClogged = 0; /* fifo full */
  1636. i2QueueNeeds(pB, pCh, NEED_BYPASS); // Put back on queue
  1637. break;   // Break from the channel
  1638. }
  1639. #ifdef DEBUG_FIFO
  1640. WriteDBGBuf("BYPS", pRemove, paddedSize);
  1641. #endif /* DEBUG_FIFO */
  1642. pB->debugBypassCount++;
  1643. pRemove += packetSize;
  1644. stripIndex += packetSize;
  1645. if (stripIndex >= CBUF_SIZE) {
  1646. stripIndex = 0;
  1647. pRemove = pCh->Cbuf;
  1648. }
  1649. }
  1650. // Done with this channel. Move to next, removing this one from 
  1651. // the queue of channels if we cleaned it out (i.e., didn't get clogged.
  1652. pCh->Cbuf_strip = stripIndex;
  1653. WRITE_UNLOCK_IRQRESTORE(&pCh->Cbuf_spinlock,flags);
  1654. }  // Either clogged or finished all the work
  1655. #ifdef IP2DEBUG_TRACE
  1656. if ( !bailout ) {
  1657. ip2trace (ITRC_NO_PORT, ITRC_ERROR, 1, 0 );
  1658. }
  1659. #endif
  1660. }
  1661. //******************************************************************************
  1662. // Function:   i2StuffFifoFlow(pB)
  1663. // Parameters: Pointer to a board structure
  1664. // Returns:    Nothing
  1665. //
  1666. // Description:
  1667. // Stuffs as many flow control packets into the fifo as possible. This is easier
  1668. // even than doing normal bypass commands, because there is always at most one
  1669. // packet, already assembled, for each channel.
  1670. //******************************************************************************
  1671. static inline void
  1672. i2StuffFifoFlow(i2eBordStrPtr pB)
  1673. {
  1674. i2ChanStrPtr pCh;
  1675. unsigned short paddedSize = ROUNDUP(sizeof(flowIn));
  1676. ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_ENTER, 2,
  1677. pB->i2eFifoRemains, paddedSize );
  1678. // Continue processing so long as there are entries, or there is room in the
  1679. // fifo. Each entry represents a channel with something to do.
  1680. while ( (NULL != (pCh = i2DeQueueNeeds(pB,NEED_FLOW)))) {
  1681. pB->debugFlowCount++;
  1682. // NO Chan LOCK needed ???
  1683. if ( 0 == i2Write2Fifo(pB,(unsigned char *)&(pCh->infl),paddedSize,0)) {
  1684. break;
  1685. }
  1686. #ifdef DEBUG_FIFO
  1687. WriteDBGBuf("FLOW",(unsigned char *) &(pCh->infl), paddedSize);
  1688. #endif /* DEBUG_FIFO */
  1689. }  // Either clogged or finished all the work
  1690. ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_RETURN, 0 );
  1691. }
  1692. //******************************************************************************
  1693. // Function:   i2StuffFifoInline(pB)
  1694. // Parameters: Pointer to a board structure
  1695. // Returns:    Nothing
  1696. //
  1697. // Description:
  1698. // Stuffs as much data and inline commands into the fifo as possible. This is
  1699. // the most complex fifo-stuffing operation, since there if now the channel
  1700. // flow-control issue to deal with.
  1701. //******************************************************************************
  1702. static inline void
  1703. i2StuffFifoInline(i2eBordStrPtr pB)
  1704. {
  1705. i2ChanStrPtr pCh;
  1706. unsigned char *pRemove;
  1707. unsigned short stripIndex;
  1708. unsigned short packetSize;
  1709. unsigned short paddedSize;
  1710. unsigned short notClogged = 1;
  1711. unsigned short flowsize;
  1712. unsigned long flags;
  1713. int bailout  = 1000;
  1714. int bailout2;
  1715. ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_ENTER, 3, pB->i2eFifoRemains, 
  1716. pB->i2Dbuf_strip, pB->i2Dbuf_stuff );
  1717. // Continue processing so long as there are entries, or there is room in the
  1718. // fifo. Each entry represents a channel with something to do.
  1719. while ( --bailout && notClogged && 
  1720. (NULL != (pCh = i2DeQueueNeeds(pB,NEED_INLINE))) )
  1721. {
  1722. WRITE_LOCK_IRQSAVE(&pCh->Obuf_spinlock,flags);
  1723. stripIndex = pCh->Obuf_strip;
  1724. ip2trace (CHANN, ITRC_SICMD, 3, 2, stripIndex, pCh->Obuf_stuff );
  1725. // as long as there are packets for this channel...
  1726. bailout2 = 1000;
  1727. while ( --bailout2 && stripIndex != pCh->Obuf_stuff) {
  1728. pRemove = &(pCh->Obuf[stripIndex]);
  1729. // Must determine whether this be a data or command packet to
  1730. // calculate correctly the header size and the amount of
  1731. // flow-control credit this type of packet will use.
  1732. if (PTYPE_OF(pRemove) == PTYPE_DATA) {
  1733. flowsize = DATA_COUNT_OF(pRemove);
  1734. packetSize = flowsize + sizeof(i2DataHeader);
  1735. } else {
  1736. flowsize = CMD_COUNT_OF(pRemove);
  1737. packetSize = flowsize + sizeof(i2CmdHeader);
  1738. }
  1739. flowsize = CREDIT_USAGE(flowsize);
  1740. paddedSize = ROUNDUP(packetSize);
  1741. ip2trace (CHANN, ITRC_SICMD, 4, 2, pB->i2eFifoRemains, paddedSize );
  1742. // If we don't have enough credits from the board to send the data,
  1743. // flag the channel that we are waiting for flow control credit, and
  1744. // break out. This will clean up this channel and remove us from the
  1745. // queue of hot things to do.
  1746. ip2trace (CHANN, ITRC_SICMD, 5, 2, pCh->outfl.room, flowsize );
  1747. if (pCh->outfl.room <= flowsize) {
  1748. // Do Not have the credits to send this packet.
  1749. i2QueueNeeds(pB, pCh, NEED_CREDIT);
  1750. notClogged = 0;
  1751. break;   // So to do next channel
  1752. }
  1753. if ( (paddedSize > 0) 
  1754. && ( 0 == i2Write2Fifo(pB, pRemove, paddedSize, 128))) {
  1755. // Do Not have room in fifo to send this packet.
  1756. notClogged = 0;
  1757. i2QueueNeeds(pB, pCh, NEED_INLINE);
  1758. break;   // Break from the channel
  1759. }
  1760. #ifdef DEBUG_FIFO
  1761. WriteDBGBuf("DATA", pRemove, paddedSize);
  1762. #endif /* DEBUG_FIFO */
  1763. pB->debugInlineCount++;
  1764. pCh->icount.tx += flowsize;
  1765. // Update current credits
  1766. pCh->outfl.room -= flowsize;
  1767. pCh->outfl.asof += flowsize;
  1768. if (PTYPE_OF(pRemove) == PTYPE_DATA) {
  1769. pCh->Obuf_char_count -= DATA_COUNT_OF(pRemove);
  1770. }
  1771. pRemove += packetSize;
  1772. stripIndex += packetSize;
  1773. ip2trace (CHANN, ITRC_SICMD, 6, 2, stripIndex, pCh->Obuf_strip);
  1774. if (stripIndex >= OBUF_SIZE) {
  1775. stripIndex = 0;
  1776. pRemove = pCh->Obuf;
  1777. ip2trace (CHANN, ITRC_SICMD, 7, 1, stripIndex );
  1778. }
  1779. } /* while */
  1780. if ( !bailout2 ) {
  1781. ip2trace (CHANN, ITRC_ERROR, 3, 0 );
  1782. }
  1783. // Done with this channel. Move to next, removing this one from the
  1784. // queue of channels if we cleaned it out (i.e., didn't get clogged.
  1785. pCh->Obuf_strip = stripIndex;
  1786. WRITE_UNLOCK_IRQRESTORE(&pCh->Obuf_spinlock,flags);
  1787. if ( notClogged )
  1788. {
  1789. ip2trace (CHANN, ITRC_SICMD, 8, 0 );
  1790. if ( pCh->pTTY ) {
  1791. ip2_owake(pCh->pTTY);
  1792. }
  1793. }
  1794. }  // Either clogged or finished all the work
  1795. if ( !bailout ) {
  1796. ip2trace (ITRC_NO_PORT, ITRC_ERROR, 4, 0 );
  1797. }
  1798. ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_RETURN, 1,pB->i2Dbuf_strip);
  1799. }
  1800. //******************************************************************************
  1801. // Function:   serviceOutgoingFifo(pB)
  1802. // Parameters: Pointer to a board structure
  1803. // Returns:    Nothing
  1804. //
  1805. // Description:
  1806. // Helper routine to put data in the outgoing fifo, if we aren't already waiting
  1807. // for something to be there. If the fifo has only room for a very little data,
  1808. // go head and hit the board with a mailbox hit immediately. Otherwise, it will
  1809. // have to happen later in the interrupt processing. Since this routine may be
  1810. // called both at interrupt and foreground time, we must turn off interrupts
  1811. // during the entire process.
  1812. //******************************************************************************
  1813. static void
  1814. serviceOutgoingFifo(i2eBordStrPtr pB)
  1815. {
  1816. // If we aren't currently waiting for the board to empty our fifo, service
  1817. // everything that is pending, in priority order (especially, Bypass before
  1818. // Inline).
  1819. if ( ! pB->i2eWaitingForEmptyFifo )
  1820. {
  1821. i2StuffFifoFlow(pB);
  1822. i2StuffFifoBypass(pB);
  1823. i2StuffFifoInline(pB);
  1824. iiSendPendingMail(pB);
  1825. }
  1826. //******************************************************************************
  1827. // Function:   i2ServiceBoard(pB)
  1828. // Parameters: Pointer to a board structure
  1829. // Returns:    Nothing
  1830. //
  1831. // Description:
  1832. // Normally this is called from interrupt level, but there is deliberately
  1833. // nothing in here specific to being called from interrupt level. All the
  1834. // hardware-specific, interrupt-specific things happen at the outer levels.
  1835. //
  1836. // For example, a timer interrupt could drive this routine for some sort of
  1837. // polled operation. The only requirement is that the programmer deal with any
  1838. // atomiticity/concurrency issues that result.
  1839. //
  1840. // This routine responds to the board's having sent mailbox information to the
  1841. // host (which would normally cause an interrupt). This routine reads the
  1842. // incoming mailbox. If there is no data in it, this board did not create the
  1843. // interrupt and/or has nothing to be done to it. (Except, if we have been
  1844. // waiting to write mailbox data to it, we may do so.
  1845. //
  1846. // Based on the value in the mailbox, we may take various actions.
  1847. //
  1848. // No checking here of pB validity: after all, it shouldn't have been called by
  1849. // the handler unless pB were on the list.
  1850. //******************************************************************************
  1851. static inline int
  1852. i2ServiceBoard ( i2eBordStrPtr pB )
  1853. {
  1854. unsigned inmail;
  1855. unsigned long flags;
  1856. /* This should be atomic because of the way we are called... */
  1857. if (NO_MAIL_HERE == ( inmail = pB->i2eStartMail ) ) {
  1858. inmail = iiGetMail(pB);
  1859. }
  1860. pB->i2eStartMail = NO_MAIL_HERE;
  1861. ip2trace (ITRC_NO_PORT, ITRC_INTR, 2, 1, inmail );
  1862. if (inmail != NO_MAIL_HERE) {
  1863. // If the board has gone fatal, nothing to do but hit a bit that will
  1864. // alert foreground tasks to protest!
  1865. if ( inmail & MB_FATAL_ERROR ) {
  1866. pB->i2eFatal = 1;
  1867. goto exit_i2ServiceBoard;
  1868. }
  1869. /* Assuming no fatal condition, we proceed to do work */
  1870. if ( inmail & MB_IN_STUFFED ) {
  1871. pB->i2eFifoInInts++;
  1872. i2StripFifo(pB);     /* There might be incoming packets */
  1873. }
  1874. if (inmail & MB_OUT_STRIPPED) {
  1875. pB->i2eFifoOutInts++;
  1876. WRITE_LOCK_IRQSAVE(&pB->write_fifo_spinlock,flags);
  1877. pB->i2eFifoRemains = pB->i2eFifoSize;
  1878. pB->i2eWaitingForEmptyFifo = 0;
  1879. WRITE_UNLOCK_IRQRESTORE(&pB->write_fifo_spinlock,flags);
  1880. ip2trace (ITRC_NO_PORT, ITRC_INTR, 30, 1, pB->i2eFifoRemains );
  1881. }
  1882. serviceOutgoingFifo(pB);
  1883. }
  1884. ip2trace (ITRC_NO_PORT, ITRC_INTR, 8, 0 );
  1885. exit_i2ServiceBoard:
  1886. return 0;
  1887. }