bit operations

Discussion in 'C Programming' started by Mark, Jun 28, 2010.

  1. Mark

    Mark Guest

    [Sorry if this is somewhat offtopic here, but I can't see another place with
    a number of C-gurus]

    I'm writing code for a communication processor with 25 port, where I need
    to set up VLAN (virtual LAN) parameters for every port (bit0 is for port 0
    be a member of group, bit1 is for port 2 and so on). It's fine, except that
    each port is represented with two 16-bit registers: one has 16 bits valid,
    and the second only 9.
    Each register has the meaning "the ports which p1~p25 can forward to", so
    for example if I want to set port {5, 6, 7, 8, 25} to be a in VLAN group A,
    I set registers:

    reg5-1 to 0x00f0, reg5-2 to 0x100 (for port 5)
    reg6-1 to 0x00f0, reg6-2 to 0x100 (for port 6)
    reg7-1 to 0x00f0, reg7-2 to 0x100 (for port 7)
    reg8-1 to 0x00f0, reg8-2 to 0x100 (for port 8)
    reg25-1 to 0x00f0, reg25-2 to 0x100 (for port 25)

    So, I'm writing a function with two arguments (VLAN id and port number) to
    set these registers, but I stuck with that the function should write values,
    at the same time considering

    int vlan_port_add(int unit, unsigned int vid, unsigned int port)
    {
    int p;
    long portmask;
    uint16_t val;

    portmask = getPortmask(vid); /* current bitmask stored in NVRAM */
    portmask |= 1 << (port - 1);
    savePortmask(vid, portmask);
    mask = portmask;

    for (p = 0; p < PORT_MAX; p++) {
    if (mask & 1) {
    addr = R_VLAN_ENTRY_BASE + (p * 2); /* evaluate register
    address */
    val = portmask & 0x0000ffff; /* take bit[0..15] */
    writeReg(unit, addr, val);
    /* XXX */
    }
    mask >>= 1;
    }
    ...
    }

    At XXX I can't find a way to write at both regs, because it appears that the
    value of one register depends on another, suppose, I need ports 1 and 19 be
    added the same group, which means when I begin running through 'portmask', I
    don't yet know about 19th bit, and when I arrive to bit 19, there is no way
    I can know about bit 1.

    Is there appropriate method to solve this?

    Would very much appreciate your suggestions!

    --
    Mark
    Mark, Jun 28, 2010
    #1
    1. Advertising

  2. Mark

    Eric Sosman Guest

    On 6/28/2010 6:13 AM, Mark wrote:
    > [Sorry if this is somewhat offtopic here, but I can't see another place
    > with a number of C-gurus]
    >
    > I'm writing code for a communication processor with 25 port, where I
    > need to set up VLAN (virtual LAN) parameters for every port (bit0 is for
    > port 0 be a member of group, bit1 is for port 2 and so on). It's fine,
    > except that each port is represented with two 16-bit registers: one has
    > 16 bits valid, and the second only 9.
    > Each register has the meaning "the ports which p1~p25 can forward to",


    Would that be "p0~p24," or should the correspondence of bits
    and ports be readjusted? Or is something subtler going on?

    > so for example if I want to set port {5, 6, 7, 8, 25} to be a in VLAN
    > group A, I set registers:
    >
    > reg5-1 to 0x00f0, reg5-2 to 0x100 (for port 5)
    > reg6-1 to 0x00f0, reg6-2 to 0x100 (for port 6)
    > reg7-1 to 0x00f0, reg7-2 to 0x100 (for port 7)
    > reg8-1 to 0x00f0, reg8-2 to 0x100 (for port 8)
    > reg25-1 to 0x00f0, reg25-2 to 0x100 (for port 25)
    >
    > So, I'm writing a function with two arguments (VLAN id and port number)
    > to set these registers, but I stuck with that the function should write
    > values, at the same time considering
    >
    > int vlan_port_add(int unit, unsigned int vid, unsigned int port)
    > {
    > int p;
    > long portmask;


    This might be better as a `uint32_t'.

    > uint16_t val;
    >
    > portmask = getPortmask(vid); /* current bitmask stored in NVRAM */
    > portmask |= 1 << (port - 1);


    How wide is an `int' on your system? If it's only sixteen bits,
    you could get into trouble trying to shift the 16-bit value `1' too
    far to the left. Try `1UL' instead.

    > savePortmask(vid, portmask);
    > mask = portmask;


    What is `mask'? I hope it's wide enough to hold all the important
    bits in `portmask' ...

    > for (p = 0; p < PORT_MAX; p++) {
    > if (mask & 1) {
    > addr = R_VLAN_ENTRY_BASE + (p * 2); /* evaluate register address */
    > val = portmask & 0x0000ffff; /* take bit[0..15] */


    Since `val' is only 16 bits wide, the `& 0x0000ffff' is unnecessary.
    Harmless, but unnecessary.

    > writeReg(unit, addr, val);
    > /* XXX */
    > }
    > mask >>= 1;
    > }
    > ...
    > }
    >
    > At XXX I can't find a way to write at both regs, because it appears that
    > the value of one register depends on another, suppose, I need ports 1
    > and 19 be added the same group, which means when I begin running through
    > 'portmask', I don't yet know about 19th bit, and when I arrive to bit
    > 19, there is no way I can know about bit 1.
    >
    > Is there appropriate method to solve this?
    >
    > Would very much appreciate your suggestions!


    I'm not sure I've understood your problem perfectly, but *if*
    I have, I think all you need at XXX is

    writeReg(unit, addr+1, (uint16_t)(portmask >> 16));

    --
    Eric Sosman
    lid
    Eric Sosman, Jun 28, 2010
    #2
    1. Advertising

  3. Mark

    Thad Smith Guest

    Mark wrote:
    > [Sorry if this is somewhat offtopic here, but I can't see another place
    > with a number of C-gurus]
    >
    > I'm writing code for a communication processor with 25 port, where I
    > need to set up VLAN (virtual LAN) parameters for every port (bit0 is for
    > port 0 be a member of group, bit1 is for port 2 and so on). It's fine,
    > except that each port is represented with two 16-bit registers: one has
    > 16 bits valid, and the second only 9.
    > Each register has the meaning "the ports which p1~p25 can forward to",
    > so for example if I want to set port {5, 6, 7, 8, 25} to be a in VLAN
    > group A, I set registers:
    >
    > reg5-1 to 0x00f0, reg5-2 to 0x100 (for port 5)
    > reg6-1 to 0x00f0, reg6-2 to 0x100 (for port 6)
    > reg7-1 to 0x00f0, reg7-2 to 0x100 (for port 7)
    > reg8-1 to 0x00f0, reg8-2 to 0x100 (for port 8)
    > reg25-1 to 0x00f0, reg25-2 to 0x100 (for port 25)
    >
    > So, I'm writing a function with two arguments (VLAN id and port number)
    > to set these registers, but I stuck with that the function should write
    > values, at the same time considering


    This problem is about programming, not C. comp.programming or
    comp.arch.embedded would be better places for this question.

    The problem is that the function definition is inadequate. You might define a
    function to accept a list of ports to construct a VLAN so that it has all the
    information needed.

    Alternatively, if you want to incrementally add a port to a VLAN, then create a
    structure (or maybe only a integer containing a bits for enabled ports) with all
    the necessary information about a VLAN, including the currently enabled ports
    and pass a reference of it to the function. The function then knows all
    existing ports. Either the caller of callee will update the list of ports to
    include the new port.

    You probably also want a similar function to remove a port from an existing VLAN.

    --
    Thad
    Thad Smith, Jun 28, 2010
    #3
  4. On 28/06/10 14:15, Thad Smith wrote:

    > You probably also want a similar function to remove a port from an
    > existing VLAN.


    Hmm, given that the vlan configuration should be represented by the data
    held in the nvram registers, I'd want basic functions to:

    a) Read all the nvram registers into a memory structure
    b) Write the memory structure back to nvram

    Then I'd decide that this would be more hardware friendly if my memory
    structure recorded when data was changed, so it only needs to write back
    updated port data (nvram can wear out)

    Other functions I can think of are:

    1) Create a vlan from a list of ports
    2) Delete a vlan given any port in the vlan
    3) Add a single port (or a group of ports) to a vlan
    4) Delete a single port (or a group of ports) from a vlan

    1 and 3 need to consider the case that one or more of the ports
    specified might be in an existing vlan.

    I might also want to

    5) list all the ports in a vlan given a port in that vlan
    6) list all vlans with ports

    Additional functions might include

    7) save the configuration to a file
    8) load the configuration from a file
    9) delete all vlans

    All these functions would operate on the memory structure, which would
    then be used to update the hardware nvram registers.

    Rgds

    Denis McMahon
    Denis McMahon, Jun 28, 2010
    #4
  5. Mark

    Mark Guest

    Eric Sosman wrote:
    [skip]
    >> At XXX I can't find a way to write at both regs, because it appears
    >> that the value of one register depends on another, suppose, I need
    >> ports 1 and 19 be added the same group, which means when I begin
    >> running through 'portmask', I don't yet know about 19th bit, and
    >> when I arrive to bit 19, there is no way I can know about bit 1.
    >>
    >> Is there appropriate method to solve this?
    >>
    >> Would very much appreciate your suggestions!

    >
    > I'm not sure I've understood your problem perfectly, but *if*
    > I have, I think all you need at XXX is
    >
    > writeReg(unit, addr+1, (uint16_t)(portmask >> 16));


    Thank you very much, Eric. I considered all your remarks.
    This solution is really obvious, don't know how I have not seen it before, I
    was rather thinking of running two loops through portmask: one from bit0 to
    bit15, and inner loop from bit24 to bit16, and if inner loop spots non-zero
    bit then write proper register... anyway stupid idea :)

    --
    Mark
    Mark, Jun 29, 2010
    #5
  6. Mark

    Mark Guest

    Denis McMahon wrote:
    [skip]
    > All these functions would operate on the memory structure, which would
    > then be used to update the hardware nvram registers.



    I'm actually thinking in a similar way (unless I completely misunderstood
    you), something about:

    typedef struct {
    uint32_t vlan_id;
    uint32_t portmask;
    /* may be some other fields ... */
    } vlan_cfg_t;

    struct hw_config {
    vlan_cfg_t vlan_cfg[VLAN_MAX];
    iface_cfg_t ifrace_cfg[IFACE_MAX];
    /* and so on whatever configuration params we need: routing, ARP, qos
    .... */
    };

    --
    Mark
    Mark, Jun 29, 2010
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sanket Suryawanshi

    bit operations in Java

    Sanket Suryawanshi, Jan 23, 2004, in forum: Java
    Replies:
    3
    Views:
    7,057
    Jon A. Cruz
    Jan 23, 2004
  2. Jesus M. Salvo Jr.
    Replies:
    2
    Views:
    4,009
    robert
    Feb 11, 2006
  3. Replies:
    3
    Views:
    1,714
    Timothy Bendfelt
    Jan 19, 2007
  4. Replies:
    9
    Views:
    938
    Juha Nieminen
    Aug 22, 2007
  5. Jeff.M
    Replies:
    6
    Views:
    162
    Lasse Reichstein Nielsen
    May 4, 2009
Loading...

Share This Page