📄 dev_nm_16esw.c
字号:
} printf("\n"); } printf("\n"); return(0);}/* Dump the "trunk" ports */static int bcm5600_dump_trunks(struct nm_16esw_data *d){ struct bcm5600_table *table; struct bcm5600_port *port; m_uint32_t *entry; int i,j; if (!(table = bcm5600_table_find(d,BCM5600_ADDR_TBMAP0))) return(-1); printf("%s: trunk ports:\n",d->name); for(i=table->min_index;i<=table->max_index;i++) { if (!(entry = bcm5600_table_get_entry(d,table,i))) break; if (!entry[0]) continue; printf(" Trunk %d: ",i); for(j=0;j<d->nr_port;j++) { if (entry[0] & (1 << j)) { port = &d->ports[j]; printf("%s ",port->name); } } printf("\n"); } printf("\n"); return(0);}/* Dump the physical port info */static int bcm5600_dump_ports(struct nm_16esw_data *d){ struct bcm5600_table *table; struct bcm5600_port *port; m_uint32_t *entry; u_int vlan,tgid; int i; if (!(table = bcm5600_table_find(d,BCM5600_ADDR_PTABLE0))) return(-1); printf("%s: physical ports:\n",d->name); for(i=0;i<d->nr_port;i++) { if (!(entry = bcm5600_table_get_entry(d,table,i))) break; port = &d->ports[i]; vlan = entry[0] & BCM5600_PTABLE_VLAN_TAG_MASK; printf(" %-10s: VLAN %u",port->name,vlan); if (entry[0] & BCM5600_PTABLE_TRUNK_FLAG) { tgid = entry[0] & BCM5600_PTABLE_TGID_MASK; tgid >>= BCM5600_PTABLE_TGID_SHIFT; printf(", Trunk Group %u ",tgid); } printf("\n"); } printf("\n"); return(0);}/* Dump the physical port bitmaps */static int bcm5600_dump_port_bitmaps(struct nm_16esw_data *d){ struct bcm5600_table *table; struct bcm5600_port *port; m_uint32_t *entry,tbmp,ubmp; int i,j; if (!(table = bcm5600_table_find(d,BCM5600_ADDR_PTABLE0))) return(-1); printf("%s: dumping bitmaps of the port table:\n",d->name); for(i=0;i<d->nr_port;i++) { if (!(entry = bcm5600_table_get_entry(d,table,i))) break; port = &d->ports[i]; printf(" %-10s: ",port->name); for(j=0;j<d->nr_port;j++) { tbmp = entry[1] & (1 << j); ubmp = entry[2] & (1 << j); if (tbmp || ubmp) { printf("%s (",d->ports[j].name); if (tbmp) printf("T%s",ubmp ? "/" : ") "); if (ubmp) printf("UT) "); } } printf("\n"); } printf("\n"); return(0);}/* Dump main tables */static void bcm5600_dump_main_tables(struct nm_16esw_data *d){ bcm5600_dump_ports(d); bcm5600_dump_port_bitmaps(d); bcm5600_dump_vtable(d); bcm5600_dump_trunks(d);}/* Find a free ARL entry */static int bcm5600_find_free_arl_entry(struct nm_16esw_data *d){ struct bcm5600_table *table = d->t_arl; if (d->arl_cnt[0] == table->max_index) return(-1); return(d->arl_cnt[0] - 1);}/* ARL Lookup. TODO: this must be optimized in the future. */static inline int bcm5600_gen_arl_lookup(struct nm_16esw_data *d, struct bcm5600_table *table, u_int index_start,u_int index_end, n_eth_addr_t *mac_addr, u_int vlan){ m_uint32_t *entry,tmp[2],mask; int i; tmp[0] = mac_addr->eth_addr_byte[2] << 24; tmp[0] |= mac_addr->eth_addr_byte[3] << 16; tmp[0] |= mac_addr->eth_addr_byte[4] << 8; tmp[0] |= mac_addr->eth_addr_byte[5]; tmp[1] = (mac_addr->eth_addr_byte[0] << 8) | mac_addr->eth_addr_byte[1]; tmp[1] |= vlan << BCM5600_ARL_VLAN_TAG_SHIFT; mask = BCM5600_ARL_VLAN_TAG_MASK | BCM5600_ARL_MAC_MSB_MASK; for(i=index_start;i<index_end;i++) { entry = bcm5600_table_get_entry(d,table,i); if ((entry[0] == tmp[0]) && ((entry[1] & mask) == tmp[1])) return(i); } return(-1);}/* ARL Lookup */static inline int bcm5600_arl_lookup(struct nm_16esw_data *d, n_eth_addr_t *mac_addr, u_int vlan){ struct bcm5600_table *table = d->t_arl; return(bcm5600_gen_arl_lookup(d,table,1,d->arl_cnt[0]-1,mac_addr,vlan));}/* MARL Lookup */static inline int bcm5600_marl_lookup(struct nm_16esw_data *d, n_eth_addr_t *mac_addr, u_int vlan){ struct bcm5600_table *table = d->t_marl; return(bcm5600_gen_arl_lookup(d,table,table->min_index,table->max_index+1, mac_addr,vlan));}/* Invalidate an ARL entry */static void bcm5600_invalidate_arl_entry(m_uint32_t *entry){ entry[0] = entry[1] = entry[2] = 0;}/* Insert an entry into the ARL table */static int bcm5600_insert_arl_entry(struct nm_16esw_data *d){ struct bcm5600_table *table = d->t_arl; m_uint32_t *entry,mask; int i,index; mask = BCM5600_ARL_VLAN_TAG_MASK | BCM5600_ARL_MAC_MSB_MASK; for(i=0;i<d->arl_cnt[0]-1;i++) { entry = bcm5600_table_get_entry(d,table,i); /* If entry already exists, just modify it */ if ((entry[0] == d->dw[1]) && ((entry[1] & mask) == (d->dw[2] & mask))) { entry[0] = d->dw[1]; entry[1] = d->dw[2]; entry[2] = d->dw[3]; d->dw[1] = i; return(0); } } index = d->arl_cnt[0] - 1; entry = bcm5600_table_get_entry(d,table,index); entry[0] = d->dw[1]; entry[1] = d->dw[2]; entry[2] = d->dw[3]; d->dw[1] = index; d->arl_cnt[0]++; return(0);}/* Delete an entry from the ARL table */static int bcm5600_delete_arl_entry(struct nm_16esw_data *d){ struct bcm5600_table *table; m_uint32_t *entry,*last_entry,mac_msb; u_int cvlan,vlan; int i; if (!(table = bcm5600_table_find(d,BCM5600_ADDR_ARL0))) return(-1); vlan = d->dw[2] & BCM5600_ARL_VLAN_TAG_MASK; vlan >>= BCM5600_ARL_VLAN_TAG_SHIFT; mac_msb = d->dw[2] & BCM5600_ARL_MAC_MSB_MASK; for(i=table->min_index;i<=table->max_index;i++) { entry = bcm5600_table_get_entry(d,table,i); /* compare VLANs and MAC addresses */ cvlan = (entry[1] & BCM5600_ARL_VLAN_TAG_MASK); cvlan >>= BCM5600_ARL_VLAN_TAG_SHIFT; if ((cvlan == vlan) && (entry[0] == d->dw[1]) && ((entry[1] & BCM5600_ARL_MAC_MSB_MASK) == mac_msb)) { d->dw[1] = i; last_entry = bcm5600_table_get_entry(d,d->t_arl,d->arl_cnt[0]-2); entry[0] = last_entry[0]; entry[1] = last_entry[1]; entry[2] = last_entry[2]; d->arl_cnt[0]--; return(i); } } return(0);}/* Reset the ARL tables */static int bcm5600_reset_arl(struct nm_16esw_data *d){ struct bcm5600_table *table; m_uint32_t *entry; int i; if (!(table = bcm5600_table_find(d,BCM5600_ADDR_ARL0))) return(-1); for(i=table->min_index;i<=table->max_index;i++) { entry = bcm5600_table_get_entry(d,table,i); bcm5600_invalidate_arl_entry(entry); } return(0);}/* MAC Address Ager */static int bcm5600_arl_ager(struct nm_16esw_data *d){ m_uint32_t *entry,*last_entry; int i; BCM_LOCK(d); for(i=1;i<d->arl_cnt[0]-1;i++) { entry = bcm5600_table_get_entry(d,d->t_arl,i); assert(entry); if (entry[2] & BCM5600_ARL_ST_FLAG) continue; /* The entry has expired, purge it */ if (!(entry[2] & BCM5600_ARL_HIT_FLAG)) { last_entry = bcm5600_table_get_entry(d,d->t_arl,d->arl_cnt[0]-2); entry[0] = last_entry[0]; entry[1] = last_entry[1]; entry[2] = last_entry[2]; d->arl_cnt[0]--; i--; } else { entry[2] &= ~BCM5600_ARL_HIT_FLAG; } } BCM_UNLOCK(d); return(TRUE);}/* Get the VTABLE entry matching the specified VLAN */static m_uint32_t *bcm5600_vtable_get_entry_by_vlan(struct nm_16esw_data *d, u_int vlan){ struct bcm5600_table *table = d->t_vtable; m_uint32_t *entry; int i; for(i=table->min_index;i<=table->max_index;i++) { if (!(entry = bcm5600_table_get_entry(d,table,i))) break; if ((entry[0] & BCM5600_VTABLE_VLAN_TAG_MASK) == vlan) return entry; } return NULL;}/* Read memory command */static void bcm5600_handle_read_mem_cmd(struct nm_16esw_data *d){ int i; if (bcm5600_table_read_entry(d) != 0) { for(i=1;i<BCM5600_DW_MAX;i++) d->dw[i] = 0; } d->dw[0] = BCM5600_OP_READ_MEM_ACK << BCM5600_CMD_OP_SHIFT;}/* Write memory command */static void bcm5600_handle_write_mem_cmd(struct nm_16esw_data *d){ bcm5600_table_write_entry(d); d->dw[0] = BCM5600_OP_WRITE_MEM_ACK << BCM5600_CMD_OP_SHIFT;}/* Handle a "general" command */static void bcm5600_handle_gen_cmd(struct nm_16esw_data *d){ m_uint32_t op,src,dst,len; /* Extract the opcode */ op = (d->dw[0] & BCM5600_CMD_OP_MASK) >> BCM5600_CMD_OP_SHIFT; src = (d->dw[0] & BCM5600_CMD_SRC_MASK) >> BCM5600_CMD_SRC_SHIFT; dst = (d->dw[0] & BCM5600_CMD_DST_MASK) >> BCM5600_CMD_DST_SHIFT; len = (d->dw[0] & BCM5600_CMD_LEN_MASK) >> BCM5600_CMD_LEN_SHIFT;#if DEBUG_ACCESS BCM_LOG(d,"gen_cmd: opcode 0x%2.2x [src=0x%2.2x,dst=0x%2.2x,len=0x%2.2x] " "(dw[0]=0x%8.8x, dw[1]=0x%8.8x, dw[2]=0x%8.8x, dw[3]=0x%8.8x)\n", op,src,dst,len,d->dw[0],d->dw[1],d->dw[2],d->dw[3]);#endif switch(op) { case BCM5600_OP_READ_MEM_CMD: bcm5600_handle_read_mem_cmd(d); break; case BCM5600_OP_WRITE_MEM_CMD: bcm5600_handle_write_mem_cmd(d); break; case BCM5600_OP_READ_REG_CMD: d->dw[0] = BCM5600_OP_READ_REG_ACK << BCM5600_CMD_OP_SHIFT;#if DEBUG_REG BCM_LOG(d,"READ_REG: reg_addr=0x%8.8x\n",d->dw[1]);#endif d->dw[1] = bcm5600_reg_read(d,d->dw[1]); break; case BCM5600_OP_WRITE_REG_CMD: d->dw[0] = BCM5600_OP_WRITE_REG_ACK << BCM5600_CMD_OP_SHIFT;#if DEBUG_REG BCM_LOG(d,"WRITE_REG: reg_addr=0x%8.8x val=0x%8.8x\n", d->dw[1],d->dw[2]);#endif bcm5600_reg_write(d,d->dw[1],d->dw[2]); bcm5600_reg_write_special(d,d->dw[1],d->dw[2]); break; case BCM5600_OP_ARL_INSERT_CMD: d->dw[0] = BCM5600_OP_ARL_INSERT_DONE << BCM5600_CMD_OP_SHIFT;#if DEBUG_ARL BCM_LOG(d,"ARL_INSERT_CMD " "(dw[1]=0x%8.8x,dw[2]=0x%8.8x,dw[3]=0x%8.8x)\n", d->dw[1],d->dw[2],d->dw[3]);#endif bcm5600_insert_arl_entry(d); break; case BCM5600_OP_ARL_DELETE_CMD: d->dw[0] = BCM5600_OP_ARL_DELETE_DONE << BCM5600_CMD_OP_SHIFT;#if DEBUG_ARL BCM_LOG(d,"ARL_DELETE_CMD (dw[1]=0x%8.8x,dw[2]=0x%8.8x)\n", d->dw[1],d->dw[2]);#endif bcm5600_delete_arl_entry(d); break; case BCM5600_OP_ARL_LOOKUP_CMD: d->dw[0] = BCM5600_OP_READ_MEM_ACK << BCM5600_CMD_OP_SHIFT; break; default: BCM_LOG(d,"unknown opcode 0x%8.8x (cmd=0x%8.8x)\n",op,d->dw[0]); }}/* Handle a s-channel command */static void bcm5600_handle_schan_cmd(struct nm_16esw_data *d,m_uint32_t cmd){ d->schan_cmd = cmd;#if DEBUG_ACCESS BCM_LOG(d,"s-chan command 0x%8.8x\n",cmd);#endif switch(cmd) { case BCM5600_SCHAN_CMD_EXEC: bcm5600_handle_gen_cmd(d); d->schan_cmd_res = 0xFFFFFFFF; break; case BCM5600_SCHAN_CMD_READ_MII: bcm5600_mii_read(d); d->schan_cmd_res = 0xFFFFFFFF; break; case BCM5600_SCHAN_CMD_WRITE_MII: bcm5600_mii_write(d); d->schan_cmd_res = 0xFFFFFFFF; break; case BCM5600_SCHAN_CMD_LINKSCAN: d->schan_cmd_res = 0x0; break; default:#if DEBUG_UNKNOWN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -