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

📄 strip.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
    *start = buf - return_len;    if (return_len > requested_len) {        return_len = requested_len;    }    /* printk(KERN_DEBUG "return_len: %d\n", return_len); */    return return_len;}/* * If the time is in the near future, time_delta prints the number of * seconds to go into the buffer and returns the address of the buffer. * If the time is not in the near future, it returns the address of the * string "Not scheduled" The buffer must be long enough to contain the * ascii representation of the number plus 9 charactes for the " seconds" * and the null character. */static char *time_delta(char buffer[], long time){    time -= jiffies;    if (time > LongTime / 2) return("Not scheduled");    if(time < 0) time = 0;  /* Don't print negative times */    sprintf(buffer, "%ld seconds", time / HZ);    return(buffer);}static int sprintf_neighbours(char *buffer, MetricomNodeTable *table, char *title){    /* We wrap this in a do/while loop, so if the table changes */    /* while we're reading it, we just go around and try again. */    struct timeval t;    char *ptr;    do        {        int i;        t = table->timestamp;        ptr = buffer;        if (table->num_nodes) ptr += sprintf(ptr, "\n %s\n", title);        for (i=0; i<table->num_nodes; i++)            {            InterruptStatus intstat = DisableInterrupts();            MetricomNode node = table->node[i];            RestoreInterrupts(intstat);            ptr += sprintf(ptr, "  %s\n", node.c);            }        } while (table->timestamp.tv_sec != t.tv_sec || table->timestamp.tv_usec != t.tv_usec);    return ptr - buffer;}/* * This function prints radio status information into the specified buffer. * I think the buffer size is 4K, so this routine should never print more * than 4K of data into it. With the maximum of 32 portables and 32 poletops * reported, the routine outputs 3107 bytes into the buffer. */static intsprintf_status_info(char *buffer, struct strip *strip_info){    char temp[32];    char *p = buffer;    MetricomAddressString addr_string;    /* First, we must copy all of our data to a safe place, */    /* in case a serial interrupt comes in and changes it.  */    InterruptStatus intstat = DisableInterrupts();    int                tx_left             = strip_info->tx_left;    unsigned long      rx_average_pps      = strip_info->rx_average_pps;    unsigned long      tx_average_pps      = strip_info->tx_average_pps;    unsigned long      sx_average_pps      = strip_info->sx_average_pps;    int                working             = strip_info->working;    int                firmware_level      = strip_info->firmware_level;    long               watchdog_doprobe    = strip_info->watchdog_doprobe;    long               watchdog_doreset    = strip_info->watchdog_doreset;    long               gratuitous_arp      = strip_info->gratuitous_arp;    long               arp_interval        = strip_info->arp_interval;    FirmwareVersion    firmware_version    = strip_info->firmware_version;    SerialNumber       serial_number       = strip_info->serial_number;    BatteryVoltage     battery_voltage     = strip_info->battery_voltage;    char*              if_name             = strip_info->dev.name;    MetricomAddress    true_dev_addr       = strip_info->true_dev_addr;    MetricomAddress    dev_dev_addr        = *(MetricomAddress*)strip_info->dev.dev_addr;    int                manual_dev_addr     = strip_info->manual_dev_addr;#ifdef EXT_COUNTERS    unsigned long      rx_bytes            = strip_info->rx_bytes;    unsigned long      tx_bytes            = strip_info->tx_bytes;    unsigned long      rx_rbytes           = strip_info->rx_rbytes;    unsigned long      tx_rbytes           = strip_info->tx_rbytes;    unsigned long      rx_sbytes           = strip_info->rx_sbytes;    unsigned long      tx_sbytes           = strip_info->tx_sbytes;    unsigned long      rx_ebytes           = strip_info->rx_ebytes;    unsigned long      tx_ebytes           = strip_info->tx_ebytes;#endif    RestoreInterrupts(intstat);    p += sprintf(p, "\nInterface name\t\t%s\n", if_name);    p += sprintf(p, " Radio working:\t\t%s\n", working ? "Yes" : "No");    radio_address_to_string(&true_dev_addr, &addr_string);    p += sprintf(p, " Radio address:\t\t%s\n", addr_string.c);    if (manual_dev_addr)    {        radio_address_to_string(&dev_dev_addr, &addr_string);        p += sprintf(p, " Device address:\t%s\n", addr_string.c);    }    p += sprintf(p, " Firmware version:\t%s", !working        ? "Unknown" :                                              !firmware_level ? "Should be upgraded" :                                              firmware_version.c);    if (firmware_level >= ChecksummedMessages) p += sprintf(p, " (Checksums Enabled)");    p += sprintf(p, "\n");    p += sprintf(p, " Serial number:\t\t%s\n", serial_number.c);    p += sprintf(p, " Battery voltage:\t%s\n", battery_voltage.c);    p += sprintf(p, " Transmit queue (bytes):%d\n", tx_left);    p += sprintf(p, " Receive packet rate:   %ld packets per second\n", rx_average_pps / 8);    p += sprintf(p, " Transmit packet rate:  %ld packets per second\n", tx_average_pps / 8);    p += sprintf(p, " Sent packet rate:      %ld packets per second\n", sx_average_pps / 8);    p += sprintf(p, " Next watchdog probe:\t%s\n", time_delta(temp, watchdog_doprobe));    p += sprintf(p, " Next watchdog reset:\t%s\n", time_delta(temp, watchdog_doreset));    p += sprintf(p, " Next gratuitous ARP:\t");    if (!memcmp(strip_info->dev.dev_addr, zero_address.c, sizeof(zero_address)))        p += sprintf(p, "Disabled\n");    else    {        p += sprintf(p, "%s\n", time_delta(temp, gratuitous_arp));        p += sprintf(p, " Next ARP interval:\t%ld seconds\n", JIFFIE_TO_SEC(arp_interval));    }    if (working)        {#ifdef EXT_COUNTERS          p += sprintf(p, "\n");          p += sprintf(p, " Total bytes:         \trx:\t%lu\ttx:\t%lu\n", rx_bytes, tx_bytes);          p += sprintf(p, "  thru radio:         \trx:\t%lu\ttx:\t%lu\n", rx_rbytes, tx_rbytes);          p += sprintf(p, "  thru serial port:   \trx:\t%lu\ttx:\t%lu\n", rx_sbytes, tx_sbytes);          p += sprintf(p, " Total stat/err bytes:\trx:\t%lu\ttx:\t%lu\n", rx_ebytes, tx_ebytes);#endif        p += sprintf_neighbours(p, &strip_info->poletops, "Poletops:");        p += sprintf_neighbours(p, &strip_info->portables, "Portables:");        }    return p - buffer;}/* * This function is exports status information from the STRIP driver through * the /proc file system. */static int get_status_info(char *buffer, char **start, off_t req_offset, int req_len){    int           total = 0, slop = 0;    struct strip *strip_info = struct_strip_list;    char         *buf = buffer;    buf += sprintf(buf, "strip_version: %s\n", StripVersion);    if (shift_buffer(buffer, req_offset, req_len, &total, &slop, &buf)) goto exit;    while (strip_info != NULL)        {        buf += sprintf_status_info(buf, strip_info);        if (shift_buffer(buffer, req_offset, req_len, &total, &slop, &buf)) break;        strip_info = strip_info->next;        }    exit:    return(calc_start_len(buffer, start, req_offset, req_len, total, buf));}/************************************************************************//* Sending routines							*/static void ResetRadio(struct strip *strip_info){    struct tty_struct *tty = strip_info->tty;    static const char init[] = "ate0q1dt**starmode\r**";    StringDescriptor s = { init, sizeof(init)-1 };    /*      * If the radio isn't working anymore,     * we should clear the old status information.     */    if (strip_info->working)    {        printk(KERN_INFO "%s: No response: Resetting radio.\n", strip_info->dev.name);        strip_info->firmware_version.c[0] = '\0';        strip_info->serial_number.c[0] = '\0';        strip_info->battery_voltage.c[0] = '\0';        strip_info->portables.num_nodes = 0;        do_gettimeofday(&strip_info->portables.timestamp);        strip_info->poletops.num_nodes = 0;        do_gettimeofday(&strip_info->poletops.timestamp);    }    strip_info->pps_timer      = jiffies;    strip_info->rx_pps_count   = 0;    strip_info->tx_pps_count   = 0;    strip_info->sx_pps_count   = 0;    strip_info->rx_average_pps = 0;    strip_info->tx_average_pps = 0;    strip_info->sx_average_pps = 0;    /* Mark radio address as unknown */    *(MetricomAddress*)&strip_info->true_dev_addr = zero_address;    if (!strip_info->manual_dev_addr)        *(MetricomAddress*)strip_info->dev.dev_addr = zero_address;    strip_info->working = FALSE;    strip_info->firmware_level = NoStructure;    strip_info->next_command   = CompatibilityCommand;    strip_info->watchdog_doprobe = jiffies + 10 * HZ;    strip_info->watchdog_doreset = jiffies + 1 * HZ;    /* If the user has selected a baud rate above 38.4 see what magic we have to do */    if (strip_info->user_baud > B38400)        {        /*         * Subtle stuff: Pay attention :-)         * If the serial port is currently at the user's selected (>38.4) rate,         * then we temporarily switch to 19.2 and issue the ATS304 command         * to tell the radio to switch to the user's selected rate.         * If the serial port is not currently at that rate, that means we just         * issued the ATS304 command last time through, so this time we restore         * the user's selected rate and issue the normal starmode reset string.         */        if (strip_info->user_baud == get_baud(tty))	    {	    static const char b0[] = "ate0q1s304=57600\r";	    static const char b1[] = "ate0q1s304=115200\r";	    static const StringDescriptor baudstring[2] =                { { b0, sizeof(b0)-1 }, { b1, sizeof(b1)-1 } };	    set_baud(tty, B19200);	    if      (strip_info->user_baud == B57600 ) s = baudstring[0];	    else if (strip_info->user_baud == B115200) s = baudstring[1];	    else s = baudstring[1]; /* For now */	    }        else set_baud(tty, strip_info->user_baud);        }    tty->driver.write(tty, 0, s.string, s.length);#ifdef EXT_COUNTERS    strip_info->tx_ebytes += s.length;#endif}/* * Called by the driver when there's room for more data.  If we have * more packets to send, we send them here. */static void strip_write_some_more(struct tty_struct *tty){    struct strip *strip_info = (struct strip *) tty->disc_data;    /* First make sure we're connected. */    if (!strip_info || strip_info->magic != STRIP_MAGIC ||     	!netif_running(&strip_info->dev))        return;    if (strip_info->tx_left > 0)    {        /*         * If some data left, send it         * Note: There's a kernel design bug here. The write_wakeup routine has to         * know how many bytes were written in the previous call, but the number of         * bytes written is returned as the result of the tty->driver.write call,         * and there's no guarantee that the tty->driver.write routine will have         * returned before the write_wakeup routine is invoked. If the PC has fast         * Serial DMA hardware, then it's quite possible that the write could complete         * almost instantaneously, meaning that my write_wakeup routine could be         * called immediately, before tty->driver.write has had a chance to return         * the number of bytes that it wrote. In an attempt to guard against this,         * I disable interrupts around the call to tty->driver.write, although even         * this might not work on a symmetric multi-processor system.         */        InterruptStatus intstat = DisableInterrupts();        int num_written = tty->driver.write(tty, 0, strip_info->tx_head, strip_info->tx_left);        strip_info->tx_left -= num_written;        strip_info->tx_head += num_written;#ifdef EXT_COUNTERS        strip_info->tx_sbytes += num_written;#endif        RestoreInterrupts(intstat);    }    else            /* Else start transmission of another packet */    {        tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);        strip_unlock(strip_info);    }}static __u8 *add_checksum(__u8 *buffer, __u8 *end){    __u16 sum = 0;    __u8 *p = buffer;    while (p < end) sum += *p++;    end[3] = hextable[sum & 0xF]; sum >>= 4;    end[2] = hextable[sum & 0xF]; sum >>= 4;    end[1] = hextable[sum & 0xF]; sum >>= 4;    end[0] = hextable[sum & 0xF];    return(end+4);}static unsigned char *strip_make_packet(unsigned char *buffer, struct strip *strip_info, struct sk_buff *skb){    __u8           *ptr = buffer;    __u8           *stuffstate = NULL;    STRIP_Header   *header     = (STRIP_Header *)skb->data;    MetricomAddress haddr      = header->dst_addr;    int             len        = skb->len - sizeof(STRIP_Header);    MetricomKey     key;    /*HexDump("strip_make_packet", strip_info, skb->data, skb->data + skb->len);*/    if      (header->protocol == htons(ETH_P_IP))  key = SIP0Key;    else if (header->protocol == htons(ETH_P_ARP)) key = ARP0Key;    else    {        printk(KERN_ERR "%s: strip_make_packet: Unknown packet type 0x%04X\n",            strip_info->dev.name, ntohs(header->protocol));        return(NULL);    }    if (len > strip_info->mtu)    {        printk(KERN_ERR "%s: Dropping oversized transmit packet: %d bytes\n",            strip_info->dev.name, len);        return(NULL);    }    /*     * If we're sending to ourselves, discard the packet.     * (Metricom radios choke if they try to send a packet to their own address.)     */    if (!memcmp(haddr.c, strip_info->true_dev_addr.c, sizeof(haddr)))    {        printk(KERN_ERR "%s: Dropping packet addressed to self\n", strip_info->dev.name);        return(NULL);    }    /*     * If this is a broadcast packet, send it to our designated Metricom     * 'broadcast hub' radio (First byte of address being 0xFF means broadcast)     */    if (haddr.c[0] == 0xFF)    {	u32 brd = 0; 	struct in_device *in_dev = in_dev_get(&strip_info->dev);	if (in_dev == NULL)		return NULL;	read_lock(&in_dev->lock);	if (in_dev->ifa_list)		brd = in_dev->ifa_list->ifa_broadcast;	read_unlock(&in_dev->lock);	in_dev_put(in_dev);	/* arp_query returns 1 if it succeeds in looking up the address, 0 if it fails */        if (!arp_query(haddr.c, brd, &strip_info->dev))        {            printk(KERN_ERR "%s: Unable to send packet (no broadcast hub configured)\n",                strip_info->dev.name);            return(NULL);        }	/*	 * If we are the broadcast hub, don't bother sending to ourselves.	 * (Metricom radios choke if they try to send a packet to their own address.)	 */        if (!memcmp(haddr.c, strip_info->true_dev_addr.c, sizeof(haddr))) return(NULL);    }    *ptr++ = 0x0D;    *ptr++ = '*';    *ptr++ = hextable[haddr.c[2] >> 4];

⌨️ 快捷键说明

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