You are not logged in.


### Our Homepage is down at the in progress !! ###
highlight_code($code); unset($syn);//free unused object ?>

#1 2006-06-02 20:55:44

Registered: 2006-02-15
Last visit: 2007-03-12
Posts: 103

Strange /proc entry

When my router boots with the vendor's firmware there is something called /proc/linkstatus.  Several of the vendor's scripts for controlling the network and interfaces read this pseudo-file.  It has the form:


The ports correspond to the ethernet ports on the back of the router.  When a cable is plugged into a port its value is 1, and when there's no cable the value is 0.  I have experimented and found this to be true and it updates dynamically when cables are plugged and unplugged into the back.

This is a vendor-specific non-standard /proc file and no other implementation of router firmware seems to have it (i.e. Edimax source, Amilda and Midge).  Hawking has it and so does Planet probably.  No GPL source code, of course.

The values seem to be taken directly from the PHY_St switch control register's (offset 0x14) bits 0:4.  I just noticed for the first time that there are "broken cable" status bits in the registers too.  I think I will look into writing an interrupt service routine for this.

UPDATE: It only took a few hours to get this to work.  My first Linux Kernel Module (LKM).  Yay!  big_smile

I decided to post the code here.  You will have to figure out how to compile it.  I put it in drivers/net/adm5120 and fooled with the Makefiles until "make modules" worked.  After that, "insmod adm5120_lstat" created the /proc/net/linkstatus file, and "rmmod adm5120_lstat" removed it.  The output is exactly the same as what I reported earlier today.  These kernel modules look really cool for testing.  They make it super easy to experiment with the ADM5120 control and status registers.

Code: c:

/*      ADM5120 linkstatus module
                This module-only code will create a /proc/linkstatus
                pseudo-file that can be read to determine the status
                of ports 0 through 4 on the router.
        AUTHOR:         HH
        DATE:           2 JUNE 2006
        LICENSE:        GPL VERSION 2 */


MODULE_DESCRIPTION("ADM5120 Switch Port Status module controls /proc/linkstatus");

static struct proc_dir_entry *proc_entry_linkstat = NULL;
static char adm5120_lstat_file[] = "linkstatus";

int procfile_read(char *buffer, char **buffer_loc, off_t offset, int buffer_len, int *eof, void *data)
        int p0, p1, p2, p3, p4;                 /* 1 if port active, 0 otherwise */
        int len;                                                /* Number of bytes actually used */
        unsigned long status;                   /* Read from switch control register PHY_St (offset 0x14) */

        /* All information is given in one go so if we're asked for more, well... we don't have any */
        if (offset > 0) {
                *eof = 1;
                return 0;

        /* Read the register and set the status of the ports */
        status = ADM5120_SW_REG(PHY_st_REG);
        p0 = (status & (0x1 << 0)) ? 1 : 0;
        p1 = (status & (0x1 << 1)) ? 1 : 0;
        p2 = (status & (0x1 << 2)) ? 1 : 0;
        p3 = (status & (0x1 << 3)) ? 1 : 0;
        p4 = (status & (0x1 << 4)) ? 1 : 0;

        /* Fill the buffer and get its length */
        len = sprintf(buffer, "PORT0=%d\nPORT1=%d\nPORT2=%d\nPORT3=%d\nPORT4=%d\n", p0, p1, p2, p3, p4);

        /* set eof and return the length */
        *eof = 1;

        return len;

int adm_ls_init(void)
        /* Don't do anything if we already obtained a proc file entry */
        if (proc_entry_linkstat != NULL)
                return -1;      /* is this correct? */

        /* Get a new proc dir entry */
        proc_entry_linkstat = create_proc_entry(adm5120_lstat_file, S_IFREG | S_IRUGO, proc_net);

        /* Bail out if that failed */
        if (proc_entry_linkstat == NULL)
                return -ENOMEM;

        proc_entry_linkstat->read_proc = procfile_read;
        proc_entry_linkstat->owner = THIS_MODULE;
        proc_entry_linkstat->uid = 0;
        proc_entry_linkstat->gid = 0;
        proc_entry_linkstat->size = 40;

        return 0;

void adm_ls_cleanup(void)
        remove_proc_entry(adm5120_lstat_file, proc_net);
        proc_entry_linkstat = NULL;


I didn't have to write a device driver after all  lol .  The page that helped me the most was this one from IBM.  Even though the page is for a 2.6 kernel, the code worked fine for 2.4.18.

Last edited by HH (2006-06-03 05:18:07)



Board footer

Powered by PunBB
© Copyright 2002–2008 PunBB