bit operations

M

Mark

[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!
 
E

Eric Sosman

[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));
 
T

Thad Smith

Mark said:
[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.
 
D

Denis McMahon

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
 
M

Mark

Eric Sosman wrote:
[skip]
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 :)
 
M

Mark

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
.... */
};
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top