⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 strip.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
                /* else, another different byte, so add it to the block */                else                {                    *dst++ = *src ^ Stuff_Magic;                    count++;                }                src++;    /* Consume the byte */                break;        }        if (count == Stuff_MaxCount)        {            StuffData_FinishBlock(code + count);        }    }    if (code == Stuff_NoCode)    {        *code_ptr_ptr = NULL;    }    else    {        *code_ptr_ptr = code_ptr;        StuffData_FinishBlock(code + count);    }    return(dst);}/* * UnStuffData decodes the data at "src", up to (but not including) "end". * It writes the decoded data into the buffer pointed to by "dst", up to a * maximum of "dst_length", and returns the new value of "src" so that a * follow-on call can read more data, continuing from where the first left off. *  * There are three types of results: * 1. The source data runs out before extracting "dst_length" bytes: *    UnStuffData returns NULL to indicate failure. * 2. The source data produces exactly "dst_length" bytes: *    UnStuffData returns new_src = end to indicate that all bytes were consumed. * 3. "dst_length" bytes are extracted, with more remaining. *    UnStuffData returns new_src < end to indicate that there are more bytes *    to be read. *  * Note: The decoding may be destructive, in that it may alter the source * data in the process of decoding it (this is necessary to allow a follow-on * call to resume correctly). */static __u8 *UnStuffData(__u8 *src, __u8 *end, __u8 *dst, __u32 dst_length){    __u8 *dst_end = dst + dst_length;    /* Sanity check */    if (!src || !end || !dst || !dst_length)        return(NULL);    while (src < end && dst < dst_end)    {        int count = (*src ^ Stuff_Magic) & Stuff_CountMask;        switch ((*src ^ Stuff_Magic) & Stuff_CodeMask)        {            case Stuff_Diff:                if (src+1+count >= end)                    return(NULL);                do                {                    *dst++ = *++src ^ Stuff_Magic;                }                while(--count >= 0 && dst < dst_end);                if (count < 0)                    src += 1;                else                {                    if (count == 0)                        *src = Stuff_Same ^ Stuff_Magic;                    else                        *src = (Stuff_Diff + count) ^ Stuff_Magic;                }                break;            case Stuff_DiffZero:                if (src+1+count >= end)                    return(NULL);                do                {                    *dst++ = *++src ^ Stuff_Magic;                }                while(--count >= 0 && dst < dst_end);                if (count < 0)                    *src = Stuff_Zero ^ Stuff_Magic;                else                    *src = (Stuff_DiffZero + count) ^ Stuff_Magic;                break;            case Stuff_Same:                if (src+1 >= end)                    return(NULL);                do                {                    *dst++ = src[1] ^ Stuff_Magic;                }                while(--count >= 0 && dst < dst_end);                if (count < 0)                    src += 2;                else                    *src = (Stuff_Same + count) ^ Stuff_Magic;                break;            case Stuff_Zero:                do                {                    *dst++ = 0;                }                while(--count >= 0 && dst < dst_end);                if (count < 0)                    src += 1;                else                    *src = (Stuff_Zero + count) ^ Stuff_Magic;                break;        }    }    if (dst < dst_end)        return(NULL);    else        return(src);}/************************************************************************//* General routines for STRIP						*//* * get_baud returns the current baud rate, as one of the constants defined in * termbits.h * If the user has issued a baud rate override using the 'setserial' command * and the logical current rate is set to 38.4, then the true baud rate * currently in effect (57.6 or 115.2) is returned. */static unsigned int get_baud(struct tty_struct *tty)    {    if (!tty || !tty->termios) return(0);    if ((tty->termios->c_cflag & CBAUD) == B38400 && tty->driver_data)        {        struct async_struct *info = (struct async_struct *)tty->driver_data;        if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI ) return(B57600);        if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) return(B115200);        }    return(tty->termios->c_cflag & CBAUD);    }/* * set_baud sets the baud rate to the rate defined by baudcode * Note: The rate B38400 should be avoided, because the user may have * issued a 'setserial' speed override to map that to a different speed. * We could achieve a true rate of 38400 if we needed to by cancelling * any user speed override that is in place, but that might annoy the * user, so it is simplest to just avoid using 38400. */static void set_baud(struct tty_struct *tty, unsigned int baudcode)    {    struct termios old_termios = *(tty->termios);    tty->termios->c_cflag &= ~CBAUD; /* Clear the old baud setting */    tty->termios->c_cflag |= baudcode; /* Set the new baud setting */    tty->driver.set_termios(tty, &old_termios);    }/* * Convert a string to a Metricom Address. */#define IS_RADIO_ADDRESS(p) (                                                 \  isdigit((p)[0]) && isdigit((p)[1]) && isdigit((p)[2]) && isdigit((p)[3]) && \  (p)[4] == '-' &&                                                            \  isdigit((p)[5]) && isdigit((p)[6]) && isdigit((p)[7]) && isdigit((p)[8])    )static int string_to_radio_address(MetricomAddress *addr, __u8 *p){    if (!IS_RADIO_ADDRESS(p)) return(1);    addr->c[0] = 0;    addr->c[1] = 0;    addr->c[2] = READHEX(p[0]) << 4 | READHEX(p[1]);    addr->c[3] = READHEX(p[2]) << 4 | READHEX(p[3]);    addr->c[4] = READHEX(p[5]) << 4 | READHEX(p[6]);    addr->c[5] = READHEX(p[7]) << 4 | READHEX(p[8]);    return(0);}/* * Convert a Metricom Address to a string. */static __u8 *radio_address_to_string(const MetricomAddress *addr, MetricomAddressString *p){    sprintf(p->c, "%02X%02X-%02X%02X", addr->c[2], addr->c[3], addr->c[4], addr->c[5]);    return(p->c);}/* * Note: Must make sure sx_size is big enough to receive a stuffed * MAX_RECV_MTU packet. Additionally, we also want to ensure that it's * big enough to receive a large radio neighbour list (currently 4K). */static int allocate_buffers(struct strip *strip_info){    struct net_device *dev = &strip_info->dev;    int sx_size    = MAX(STRIP_ENCAP_SIZE(MAX_RECV_MTU), 4096);    int tx_size    = STRIP_ENCAP_SIZE(dev->mtu) + MaxCommandStringLength;    __u8 *r = kmalloc(MAX_RECV_MTU, GFP_ATOMIC);    __u8 *s = kmalloc(sx_size,      GFP_ATOMIC);    __u8 *t = kmalloc(tx_size,      GFP_ATOMIC);    if (r && s && t)    {        strip_info->rx_buff = r;        strip_info->sx_buff = s;        strip_info->tx_buff = t;        strip_info->sx_size = sx_size;        strip_info->tx_size = tx_size;        strip_info->mtu     = dev->mtu;        return(1);    }    if (r) kfree(r);    if (s) kfree(s);    if (t) kfree(t);    return(0);}/* * MTU has been changed by the IP layer. Unfortunately we are not told * about this, but we spot it ourselves and fix things up. We could be in * an upcall from the tty driver, or in an ip packet queue. */static void strip_changedmtu(struct strip *strip_info){    int old_mtu           = strip_info->mtu;    struct net_device *dev    = &strip_info->dev;    unsigned char *orbuff = strip_info->rx_buff;    unsigned char *osbuff = strip_info->sx_buff;    unsigned char *otbuff = strip_info->tx_buff;    InterruptStatus intstat;    if (dev->mtu > MAX_SEND_MTU)    {        printk(KERN_ERR "%s: MTU exceeds maximum allowable (%d), MTU change cancelled.\n",            strip_info->dev.name, MAX_SEND_MTU);        dev->mtu = old_mtu;        return;    }    /*     * Have to disable interrupts here because we're reallocating and resizing     * the serial buffers, and we can't have data arriving in them while we're     * moving them around in memory. This may cause data to be lost on the serial     * port, but hopefully people won't change MTU that often.     * Also note, this may not work on a symmetric multi-processor system.     */    intstat = DisableInterrupts();    if (!allocate_buffers(strip_info))    {        RestoreInterrupts(intstat);        printk(KERN_ERR "%s: unable to grow strip buffers, MTU change cancelled.\n",            strip_info->dev.name);        dev->mtu = old_mtu;        return;    }    if (strip_info->sx_count)    {        if (strip_info->sx_count <= strip_info->sx_size)            memcpy(strip_info->sx_buff, osbuff, strip_info->sx_count);        else        {            strip_info->discard = strip_info->sx_count;            strip_info->rx_over_errors++;        }    }    if (strip_info->tx_left)    {        if (strip_info->tx_left <= strip_info->tx_size)            memcpy(strip_info->tx_buff, strip_info->tx_head, strip_info->tx_left);        else        {            strip_info->tx_left = 0;            strip_info->tx_dropped++;        }    }    strip_info->tx_head = strip_info->tx_buff;    RestoreInterrupts(intstat);    printk(KERN_NOTICE "%s: strip MTU changed fom %d to %d.\n",        strip_info->dev.name, old_mtu, strip_info->mtu);    if (orbuff) kfree(orbuff);    if (osbuff) kfree(osbuff);    if (otbuff) kfree(otbuff);}static void strip_unlock(struct strip *strip_info){    /*     * Set the timer to go off in one second.     */    strip_info->idle_timer.expires = jiffies + 1*HZ;    add_timer(&strip_info->idle_timer);    netif_wake_queue(&strip_info->dev);}/************************************************************************//* Callback routines for exporting information through /proc		*//* * This function updates the total amount of data printed so far. It then * determines if the amount of data printed into a buffer  has reached the * offset requested. If it hasn't, then the buffer is shifted over so that * the next bit of data can be printed over the old bit. If the total * amount printed so far exceeds the total amount requested, then this * function returns 1, otherwise 0. */static int shift_buffer(char *buffer, int requested_offset, int requested_len,             int *total, int *slop, char **buf){    int printed;    /* printk(KERN_DEBUG "shift: buffer: %d o: %d l: %d t: %d buf: %d\n",           (int) buffer, requested_offset, requested_len, *total,           (int) *buf); */    printed = *buf - buffer;    if (*total + printed <= requested_offset) {        *total += printed;        *buf = buffer;    }    else {        if (*total < requested_offset) {            *slop = requested_offset - *total;        }        *total = requested_offset + printed - *slop;    }    if (*total > requested_offset + requested_len) {        return 1;    }    else {        return 0;    }}/* * This function calculates the actual start of the requested data * in the buffer. It also calculates actual length of data returned, * which could be less that the amount of data requested. */static intcalc_start_len(char *buffer, char **start, int requested_offset,               int requested_len, int total, char *buf){    int return_len, buffer_len;    buffer_len = buf - buffer;    if (buffer_len >= 4095) { 	printk(KERN_ERR "STRIP: exceeded /proc buffer size\n");    }    /*     * There may be bytes before and after the     * chunk that was actually requested.     */    return_len = total - requested_offset;    if (return_len < 0) {        return_len = 0;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -