/*********************************************************************1*2* Filename: wrapper.c3* Version: 1.24* Description: IrDA SIR async wrapper layer5* Status: Stable6* Author: Dag Brattli <[email protected]>7* Created at: Mon Aug 4 20:40:53 19978* Modified at: Fri Jan 28 13:21:09 20009* Modified by: Dag Brattli <[email protected]>10* Modified at: Fri May 28 3:11 CST 199911* Modified by: Horst von Brand <[email protected]>12*13* Copyright (c) 1998-2000 Dag Brattli <[email protected]>,14* All Rights Reserved.15* Copyright (c) 2000-2002 Jean Tourrilhes <[email protected]>16*17* This program is free software; you can redistribute it and/or18* modify it under the terms of the GNU General Public License as19* published by the Free Software Foundation; either version 2 of20* the License, or (at your option) any later version.21*22* Neither Dag Brattli nor University of Tromsø admit liability nor23* provide warranty for any of this software. This material is24* provided "AS-IS" and at no charge.25*26********************************************************************/2728#include <linux/skbuff.h>29#include <linux/string.h>30#include <linux/module.h>31#include <asm/byteorder.h>3233#include <net/irda/irda.h>34#include <net/irda/wrapper.h>35#include <net/irda/crc.h>36#include <net/irda/irlap.h>37#include <net/irda/irlap_frame.h>38#include <net/irda/irda_device.h>3940/************************** FRAME WRAPPING **************************/41/*42* Unwrap and unstuff SIR frames43*44* Note : at FIR and MIR, HDLC framing is used and usually handled45* by the controller, so we come here only for SIR... Jean II46*/4748/*49* Function stuff_byte (byte, buf)50*51* Byte stuff one single byte and put the result in buffer pointed to by52* buf. The buffer must at all times be able to have two bytes inserted.53*54* This is in a tight loop, better inline it, so need to be prior to callers.55* (2000 bytes on P6 200MHz, non-inlined ~370us, inline ~170us) - Jean II56*/57static inline int stuff_byte(__u8 byte, __u8 *buf)58{59switch (byte) {60case BOF: /* FALLTHROUGH */61case EOF: /* FALLTHROUGH */62case CE:63/* Insert transparently coded */64buf[0] = CE; /* Send link escape */65buf[1] = byte^IRDA_TRANS; /* Complement bit 5 */66return 2;67/* break; */68default:69/* Non-special value, no transparency required */70buf[0] = byte;71return 1;72/* break; */73}74}7576/*77* Function async_wrap (skb, *tx_buff, buffsize)78*79* Makes a new buffer with wrapping and stuffing, should check that80* we don't get tx buffer overflow.81*/82int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize)83{84struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb;85int xbofs;86int i;87int n;88union {89__u16 value;90__u8 bytes[2];91} fcs;9293/* Initialize variables */94fcs.value = INIT_FCS;95n = 0;9697/*98* Send XBOF's for required min. turn time and for the negotiated99* additional XBOFS100*/101102if (cb->magic != LAP_MAGIC) {103/*104* This will happen for all frames sent from user-space.105* Nothing to worry about, but we set the default number of106* BOF's107*/108IRDA_DEBUG(1, "%s(), wrong magic in skb!\n", __func__);109xbofs = 10;110} else111xbofs = cb->xbofs + cb->xbofs_delay;112113IRDA_DEBUG(4, "%s(), xbofs=%d\n", __func__, xbofs);114115/* Check that we never use more than 115 + 48 xbofs */116if (xbofs > 163) {117IRDA_DEBUG(0, "%s(), too many xbofs (%d)\n", __func__,118xbofs);119xbofs = 163;120}121122memset(tx_buff + n, XBOF, xbofs);123n += xbofs;124125/* Start of packet character BOF */126tx_buff[n++] = BOF;127128/* Insert frame and calc CRC */129for (i=0; i < skb->len; i++) {130/*131* Check for the possibility of tx buffer overflow. We use132* bufsize-5 since the maximum number of bytes that can be133* transmitted after this point is 5.134*/135if(n >= (buffsize-5)) {136IRDA_ERROR("%s(), tx buffer overflow (n=%d)\n",137__func__, n);138return n;139}140141n += stuff_byte(skb->data[i], tx_buff+n);142fcs.value = irda_fcs(fcs.value, skb->data[i]);143}144145/* Insert CRC in little endian format (LSB first) */146fcs.value = ~fcs.value;147#ifdef __LITTLE_ENDIAN148n += stuff_byte(fcs.bytes[0], tx_buff+n);149n += stuff_byte(fcs.bytes[1], tx_buff+n);150#else /* ifdef __BIG_ENDIAN */151n += stuff_byte(fcs.bytes[1], tx_buff+n);152n += stuff_byte(fcs.bytes[0], tx_buff+n);153#endif154tx_buff[n++] = EOF;155156return n;157}158EXPORT_SYMBOL(async_wrap_skb);159160/************************* FRAME UNWRAPPING *************************/161/*162* Unwrap and unstuff SIR frames163*164* Complete rewrite by Jean II :165* More inline, faster, more compact, more logical. Jean II166* (16 bytes on P6 200MHz, old 5 to 7 us, new 4 to 6 us)167* (24 bytes on P6 200MHz, old 9 to 10 us, new 7 to 8 us)168* (for reference, 115200 b/s is 1 byte every 69 us)169* And reduce wrapper.o by ~900B in the process ;-)170*171* Then, we have the addition of ZeroCopy, which is optional172* (i.e. the driver must initiate it) and improve final processing.173* (2005 B frame + EOF on P6 200MHz, without 30 to 50 us, with 10 to 25 us)174*175* Note : at FIR and MIR, HDLC framing is used and usually handled176* by the controller, so we come here only for SIR... Jean II177*/178179/*180* We can also choose where we want to do the CRC calculation. We can181* do it "inline", as we receive the bytes, or "postponed", when182* receiving the End-Of-Frame.183* (16 bytes on P6 200MHz, inlined 4 to 6 us, postponed 4 to 5 us)184* (24 bytes on P6 200MHz, inlined 7 to 8 us, postponed 5 to 7 us)185* With ZeroCopy :186* (2005 B frame on P6 200MHz, inlined 10 to 25 us, postponed 140 to 180 us)187* Without ZeroCopy :188* (2005 B frame on P6 200MHz, inlined 30 to 50 us, postponed 150 to 180 us)189* (Note : numbers taken with irq disabled)190*191* From those numbers, it's not clear which is the best strategy, because192* we end up running through a lot of data one way or another (i.e. cache193* misses). I personally prefer to avoid the huge latency spike of the194* "postponed" solution, because it come just at the time when we have195* lot's of protocol processing to do and it will hurt our ability to196* reach low link turnaround times... Jean II197*/198//#define POSTPONE_RX_CRC199200/*201* Function async_bump (buf, len, stats)202*203* Got a frame, make a copy of it, and pass it up the stack! We can try204* to inline it since it's only called from state_inside_frame205*/206static inline void207async_bump(struct net_device *dev,208struct net_device_stats *stats,209iobuff_t *rx_buff)210{211struct sk_buff *newskb;212struct sk_buff *dataskb;213int docopy;214215/* Check if we need to copy the data to a new skb or not.216* If the driver doesn't use ZeroCopy Rx, we have to do it.217* With ZeroCopy Rx, the rx_buff already point to a valid218* skb. But, if the frame is small, it is more efficient to219* copy it to save memory (copy will be fast anyway - that's220* called Rx-copy-break). Jean II */221docopy = ((rx_buff->skb == NULL) ||222(rx_buff->len < IRDA_RX_COPY_THRESHOLD));223224/* Allocate a new skb */225newskb = dev_alloc_skb(docopy ? rx_buff->len + 1 : rx_buff->truesize);226if (!newskb) {227stats->rx_dropped++;228/* We could deliver the current skb if doing ZeroCopy Rx,229* but this would stall the Rx path. Better drop the230* packet... Jean II */231return;232}233234/* Align IP header to 20 bytes (i.e. increase skb->data)235* Note this is only useful with IrLAN, as PPP has a variable236* header size (2 or 1 bytes) - Jean II */237skb_reserve(newskb, 1);238239if(docopy) {240/* Copy data without CRC (length already checked) */241skb_copy_to_linear_data(newskb, rx_buff->data,242rx_buff->len - 2);243/* Deliver this skb */244dataskb = newskb;245} else {246/* We are using ZeroCopy. Deliver old skb */247dataskb = rx_buff->skb;248/* And hook the new skb to the rx_buff */249rx_buff->skb = newskb;250rx_buff->head = newskb->data; /* NOT newskb->head */251//printk(KERN_DEBUG "ZeroCopy : len = %d, dataskb = %p, newskb = %p\n", rx_buff->len, dataskb, newskb);252}253254/* Set proper length on skb (without CRC) */255skb_put(dataskb, rx_buff->len - 2);256257/* Feed it to IrLAP layer */258dataskb->dev = dev;259skb_reset_mac_header(dataskb);260dataskb->protocol = htons(ETH_P_IRDA);261262netif_rx(dataskb);263264stats->rx_packets++;265stats->rx_bytes += rx_buff->len;266267/* Clean up rx_buff (redundant with async_unwrap_bof() ???) */268rx_buff->data = rx_buff->head;269rx_buff->len = 0;270}271272/*273* Function async_unwrap_bof(dev, byte)274*275* Handle Beginning Of Frame character received within a frame276*277*/278static inline void279async_unwrap_bof(struct net_device *dev,280struct net_device_stats *stats,281iobuff_t *rx_buff, __u8 byte)282{283switch(rx_buff->state) {284case LINK_ESCAPE:285case INSIDE_FRAME:286/* Not supposed to happen, the previous frame is not287* finished - Jean II */288IRDA_DEBUG(1, "%s(), Discarding incomplete frame\n",289__func__);290stats->rx_errors++;291stats->rx_missed_errors++;292irda_device_set_media_busy(dev, TRUE);293break;294295case OUTSIDE_FRAME:296case BEGIN_FRAME:297default:298/* We may receive multiple BOF at the start of frame */299break;300}301302/* Now receiving frame */303rx_buff->state = BEGIN_FRAME;304rx_buff->in_frame = TRUE;305306/* Time to initialize receive buffer */307rx_buff->data = rx_buff->head;308rx_buff->len = 0;309rx_buff->fcs = INIT_FCS;310}311312/*313* Function async_unwrap_eof(dev, byte)314*315* Handle End Of Frame character received within a frame316*317*/318static inline void319async_unwrap_eof(struct net_device *dev,320struct net_device_stats *stats,321iobuff_t *rx_buff, __u8 byte)322{323#ifdef POSTPONE_RX_CRC324int i;325#endif326327switch(rx_buff->state) {328case OUTSIDE_FRAME:329/* Probably missed the BOF */330stats->rx_errors++;331stats->rx_missed_errors++;332irda_device_set_media_busy(dev, TRUE);333break;334335case BEGIN_FRAME:336case LINK_ESCAPE:337case INSIDE_FRAME:338default:339/* Note : in the case of BEGIN_FRAME and LINK_ESCAPE,340* the fcs will most likely not match and generate an341* error, as expected - Jean II */342rx_buff->state = OUTSIDE_FRAME;343rx_buff->in_frame = FALSE;344345#ifdef POSTPONE_RX_CRC346/* If we haven't done the CRC as we receive bytes, we347* must do it now... Jean II */348for(i = 0; i < rx_buff->len; i++)349rx_buff->fcs = irda_fcs(rx_buff->fcs,350rx_buff->data[i]);351#endif352353/* Test FCS and signal success if the frame is good */354if (rx_buff->fcs == GOOD_FCS) {355/* Deliver frame */356async_bump(dev, stats, rx_buff);357break;358} else {359/* Wrong CRC, discard frame! */360irda_device_set_media_busy(dev, TRUE);361362IRDA_DEBUG(1, "%s(), crc error\n", __func__);363stats->rx_errors++;364stats->rx_crc_errors++;365}366break;367}368}369370/*371* Function async_unwrap_ce(dev, byte)372*373* Handle Character Escape character received within a frame374*375*/376static inline void377async_unwrap_ce(struct net_device *dev,378struct net_device_stats *stats,379iobuff_t *rx_buff, __u8 byte)380{381switch(rx_buff->state) {382case OUTSIDE_FRAME:383/* Activate carrier sense */384irda_device_set_media_busy(dev, TRUE);385break;386387case LINK_ESCAPE:388IRDA_WARNING("%s: state not defined\n", __func__);389break;390391case BEGIN_FRAME:392case INSIDE_FRAME:393default:394/* Stuffed byte coming */395rx_buff->state = LINK_ESCAPE;396break;397}398}399400/*401* Function async_unwrap_other(dev, byte)402*403* Handle other characters received within a frame404*405*/406static inline void407async_unwrap_other(struct net_device *dev,408struct net_device_stats *stats,409iobuff_t *rx_buff, __u8 byte)410{411switch(rx_buff->state) {412/* This is on the critical path, case are ordered by413* probability (most frequent first) - Jean II */414case INSIDE_FRAME:415/* Must be the next byte of the frame */416if (rx_buff->len < rx_buff->truesize) {417rx_buff->data[rx_buff->len++] = byte;418#ifndef POSTPONE_RX_CRC419rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);420#endif421} else {422IRDA_DEBUG(1, "%s(), Rx buffer overflow, aborting\n",423__func__);424rx_buff->state = OUTSIDE_FRAME;425}426break;427428case LINK_ESCAPE:429/*430* Stuffed char, complement bit 5 of byte431* following CE, IrLAP p.114432*/433byte ^= IRDA_TRANS;434if (rx_buff->len < rx_buff->truesize) {435rx_buff->data[rx_buff->len++] = byte;436#ifndef POSTPONE_RX_CRC437rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);438#endif439rx_buff->state = INSIDE_FRAME;440} else {441IRDA_DEBUG(1, "%s(), Rx buffer overflow, aborting\n",442__func__);443rx_buff->state = OUTSIDE_FRAME;444}445break;446447case OUTSIDE_FRAME:448/* Activate carrier sense */449if(byte != XBOF)450irda_device_set_media_busy(dev, TRUE);451break;452453case BEGIN_FRAME:454default:455rx_buff->data[rx_buff->len++] = byte;456#ifndef POSTPONE_RX_CRC457rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);458#endif459rx_buff->state = INSIDE_FRAME;460break;461}462}463464/*465* Function async_unwrap_char (dev, rx_buff, byte)466*467* Parse and de-stuff frame received from the IrDA-port468*469* This is the main entry point for SIR drivers.470*/471void async_unwrap_char(struct net_device *dev,472struct net_device_stats *stats,473iobuff_t *rx_buff, __u8 byte)474{475switch(byte) {476case CE:477async_unwrap_ce(dev, stats, rx_buff, byte);478break;479case BOF:480async_unwrap_bof(dev, stats, rx_buff, byte);481break;482case EOF:483async_unwrap_eof(dev, stats, rx_buff, byte);484break;485default:486async_unwrap_other(dev, stats, rx_buff, byte);487break;488}489}490EXPORT_SYMBOL(async_unwrap_char);491492493494