~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to drivers/char/ip2/i2lib.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno
  • Date: 2011-06-07 12:14:05 UTC
  • mfrom: (43.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110607121405-i3h1rd7nrnd2b73h
Tags: 2.6.39-2
[ Ben Hutchings ]
* [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA
  (Closes: #627492)
* cgroups: Disable memory resource controller by default. Allow it
  to be enabled using kernel parameter 'cgroup_enable=memory'.
* rt2800usb: Enable support for more USB devices including
  Linksys WUSB600N (Closes: #596626) (this change was accidentally
  omitted from 2.6.39-1)
* [x86] Remove Celeron from list of processors supporting PAE. Most
  'Celeron M' models do not.
* Update debconf template translations:
  - Swedish (Martin Bagge) (Closes: #628932)
  - French (David Prévot) (Closes: #628191)
* aufs: Update for 2.6.39 (Closes: #627837)
* Add stable 2.6.39.1, including:
  - ext4: dont set PageUptodate in ext4_end_bio()
  - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745)
  - ext3: Fix fs corruption when make_indexed_dir() fails
  - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages
  - sctp: fix race between sctp_bind_addr_free() and
    sctp_bind_addr_conflict()
  - sctp: fix memory leak of the ASCONF queue when free asoc
  - md/bitmap: fix saving of events_cleared and other state
  - cdc_acm: Fix oops when Droids MuIn LCD is connected
  - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827)
  - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184)
  - tmpfs: fix race between truncate and writepage
  - nfs41: Correct offset for LAYOUTCOMMIT
  - xen/mmu: fix a race window causing leave_mm BUG()
  - ext4: fix possible use-after-free in ext4_remove_li_request()
  For the complete list of changes, see:
   http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1
* Bump ABI to 2
* netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC,
  IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT,
  IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET,
  IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules
  (Closes: #629401)

[ Aurelien Jarno ]
* [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE.

Show diffs side-by-side

added added

removed removed

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