- for (;;) {
- ppp = tty2ppp (tty);
- if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse
- || tty != ppp->tty)
- return 0;
-
- if (test_and_set_bit (0, &ppp->ubuf->locked) != 0) {
-#if 0
- if (ppp->flags & SC_DEBUG)
- printk (KERN_DEBUG
- "ppp_tty_read: sleeping(ubuf)\n");
-#endif
- current->timeout = 0;
- current->state = TASK_INTERRUPTIBLE;
- schedule ();
-
- if (signal_pending(current))
- return -EINTR;
- continue;
- }
-
-/*
- * Fetch the length of the buffer from the first two bytes.
- */
- if (ppp->ubuf->head == ppp->ubuf->tail)
- len = 0;
- else {
- GETC (c);
- len = c << 8;
- GETC (c);
- len += c;
- if (len)
- break;
- }
-
-/*
- * If there is no length then wait for the data to arrive.
- */
- /* no data */
- clear_bit (0, &ppp->ubuf->locked);
- if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
- current->timeout = 0;
-#if 0
- if (ppp->flags & SC_DEBUG)
- printk (KERN_DEBUG
- "ppp_tty_read: sleeping(read_wait)\n");
-#endif
- interruptible_sleep_on (&ppp->read_wait);
- if (signal_pending(current))
- return -EINTR;
- }
-
-/*
- * Ensure that the frame will fit within the caller's buffer. If not, then
- * discard the frame from the input buffer.
- */
- if (len + 2 > nr) {
- /* Can't copy it, update us_rbuff_head */
-
- if (ppp->flags & SC_DEBUG)
- printk (KERN_DEBUG
- "ppp: read of %lu bytes too small for %ld "
- "frame\n", (unsigned long) nr, (long) len + 2);
- ppp->stats.ppp_ierrors++;
- error = -EOVERFLOW;
- goto out;
- }
-
-/*
- * Fake the insertion of the ADDRESS and CONTROL information because these
- * were not saved in the buffer.
- */
- PUT_USER (error, (u_char) PPP_ALLSTATIONS, buf);
- if (error)
- goto out;
- ++buf;
- PUT_USER (error, (u_char) PPP_UI, buf);
- if (error)
- goto out;
- ++buf;
-
-/*
- * Copy the received data from the buffer to the caller's area.
- */
- ret = len + 2; /* Account for ADDRESS and CONTROL bytes */
- while (len-- > 0) {
- GETC (c);
- PUT_USER (error, c, buf);
- if (error)
- goto out;
- ++buf;
- }
-
- clear_bit (0, &ppp->ubuf->locked);
- return ret;
-
-out:
- ppp->ubuf->tail += len;
- ppp->ubuf->tail &= ppp->ubuf->size;
- clear_bit (0, &ppp->ubuf->locked);
- return error;
-#undef GETC
-}
-
-/* stuff a character into the transmit buffer, using PPP's way of escaping
- special characters.
- also, update fcs to take account of new character */
-
-extern inline void
-ppp_stuff_char (struct ppp *ppp, register struct ppp_buffer *buf,
- register __u8 chr)
-{
-/*
- * The buffer should not be full.
- */
- if (ppp->flags & SC_DEBUG) {
- if ((buf->count < 0) || (buf->count > 3000))
- printk (KERN_DEBUG "ppp_stuff_char: %d %x\n",
- (unsigned int) buf->count,
- (unsigned int) chr);
- }
-/*
- * Update the FCS and if the character needs to be escaped, do it.
- */
- buf->fcs = PPP_FCS (buf->fcs, chr);
- if (in_xmap (ppp, chr)) {
- chr ^= PPP_TRANS;
- ins_char (buf, PPP_ESCAPE);
- }
-/*
- * Add the character to the buffer.
- */
- ins_char (buf, chr);
-}
-
-/*
- * Procedure to encode the data with the proper escaping and send the
- * data to the remote system.
- */
-
-static void
-ppp_dev_xmit_lower (struct ppp *ppp, struct ppp_buffer *buf,
- __u8 *data, int count, int non_ip)
-{
- __u16 write_fcs;
- int address, control;
- int proto;
-
- CHECK_PPP_VOID();
- CHECK_BUF_MAGIC(buf);
- ++ppp->stats.ppp_opackets;
- ppp->stats.ppp_ooctects += count;
-
-/*
- * Insert the leading FLAG character
- */
- buf->count = 0;
-
- if (non_ip || flag_time == 0)
- ins_char (buf, PPP_FLAG);
- else {
- if (jiffies - ppp->last_xmit >= flag_time)
- ins_char (buf, PPP_FLAG);
- }
- ppp->last_xmit = jiffies;
- buf->fcs = PPP_INITFCS;
-/*
- * Emit the address/control information if needed
- */
- address = PPP_ADDRESS (data);
- control = PPP_CONTROL (data);
- proto = PPP_PROTOCOL (data);
-
- if (address != PPP_ALLSTATIONS ||
- control != PPP_UI ||
- (ppp->flags & SC_COMP_AC) == 0) {
- ppp_stuff_char (ppp, buf, address);
- ppp_stuff_char (ppp, buf, control);
- }
-/*
- * Emit the protocol (compressed if possible)
- */
- if ((ppp->flags & SC_COMP_PROT) == 0 || (proto & 0xFF00))
- ppp_stuff_char (ppp, buf, proto >> 8);
-
- ppp_stuff_char (ppp, buf, proto);
-/*
- * Insert the data
- */
- data += 4;
- count -= 4;
-
- while (count-- > 0)
- ppp_stuff_char (ppp, buf, *data++);
-/*
- * Add the trailing CRC and the final flag character
- */
- write_fcs = buf->fcs ^ 0xFFFF;
- ppp_stuff_char (ppp, buf, write_fcs);
- ppp_stuff_char (ppp, buf, write_fcs >> 8);
-/*
- * Add the trailing flag character
- */
- ins_char (buf, PPP_FLAG);
-/*
- * Send the block to the tty driver.
- */
- ppp->stats.ppp_obytes += buf->count;
- ppp_kick_tty (ppp, buf);
-}
-
-/*
- * Compress and send an frame to the peer.
- *
- * Return 0 if frame was queued for transmission.
- * 1 if frame must be re-queued for later driver support.
- */
-