mirror of
https://github.com/DigitalDevices/octonet.git
synced 2023-10-10 13:36:52 +02:00
210 lines
4.5 KiB
C
210 lines
4.5 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <unistd.h>
|
|
#include <getopt.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <string.h>
|
|
#include <sys/ioctl.h>
|
|
#include <linux/types.h>
|
|
#include "octoserve.h"
|
|
|
|
extern uint32_t debug;
|
|
|
|
int readreg(int fd, uint32_t reg, uint32_t *val)
|
|
{
|
|
struct ddb_reg ddbreg = { .reg = reg };
|
|
int ret;
|
|
|
|
ret = ioctl(fd, IOCTL_DDB_READ_REG, &ddbreg);
|
|
if (ret < 0)
|
|
return ret;
|
|
if (val)
|
|
*val = ddbreg.val;
|
|
return 0;
|
|
}
|
|
|
|
int writereg(int fd, uint32_t reg, uint32_t val)
|
|
{
|
|
struct ddb_reg ddbreg = { .reg = reg, .val = val};
|
|
|
|
return ioctl(fd, IOCTL_DDB_WRITE_REG, &ddbreg);
|
|
}
|
|
|
|
uint16_t mdio_readreg(int fd, uint8_t adr, uint8_t reg, uint16_t *val)
|
|
{
|
|
#if 0
|
|
uint32_t tmp;
|
|
|
|
writereg(fd, 0x24, adr);
|
|
writereg(fd, 0x28, reg);
|
|
writereg(fd, 0x20, 0x07);
|
|
do {
|
|
readreg(fd, 0x20, &tmp);
|
|
} while (tmp & 0x02);
|
|
readreg(fd, 0x2c, &tmp);
|
|
*val = tmp;
|
|
#else
|
|
struct ddb_mdio mdio = { .adr = adr, .reg = reg};
|
|
ioctl(fd, IOCTL_DDB_READ_MDIO, &mdio);
|
|
*val = mdio.val;
|
|
#endif
|
|
return *val;
|
|
}
|
|
|
|
int mdio_writereg(int fd, uint8_t adr, uint8_t reg, uint16_t val)
|
|
{
|
|
#if 0
|
|
uint32_t tmp = val;
|
|
|
|
writereg(fd, 0x24, adr);
|
|
writereg(fd, 0x28, reg);
|
|
writereg(fd, 0x2c, tmp);
|
|
writereg(fd, 0x20, 0x03);
|
|
do {
|
|
readreg(fd, 0x20, &tmp);
|
|
} while (tmp & 0x02);
|
|
return 0;
|
|
#else
|
|
struct ddb_mdio mdio = { .adr = adr, .reg = reg, .val = val};
|
|
return ioctl(fd, IOCTL_DDB_WRITE_MDIO, &mdio);
|
|
#endif
|
|
}
|
|
|
|
int mdio_wait_switch(int fd, uint8_t adr, uint8_t reg)
|
|
{
|
|
uint16_t val;
|
|
|
|
do {
|
|
mdio_readreg(fd, adr, reg, &val);
|
|
} while (val & 0x8000);
|
|
}
|
|
|
|
int mdio_open()
|
|
{
|
|
int i, r;
|
|
|
|
for (i = 0; i < 100; i++) {
|
|
r = open("/dev/ddbridge/card0", O_RDWR);
|
|
if (r >= 0)
|
|
return r;
|
|
if (r < 0)
|
|
if (errno != EBUSY)
|
|
return r;
|
|
else
|
|
usleep(100000);
|
|
}
|
|
dbgprintf(DEBUG_SWITCH, "MDIO BUSY\n");
|
|
return r;
|
|
}
|
|
|
|
int mdio_close(int fd)
|
|
{
|
|
close(fd);
|
|
}
|
|
|
|
int switch_get_port(uint8_t mac[6])
|
|
{
|
|
int fd = mdio_open();
|
|
uint16_t vector, state;
|
|
uint16_t r0c, aw1, aw2, aw3;
|
|
uint16_t w1, w2, w3;
|
|
uint64_t m = ((uint64_t) mac[0] << 40) | ((uint64_t) mac[1] << 32) | ((uint64_t) mac[2] << 24) |
|
|
((uint64_t) mac[3] << 16) | ((uint64_t) mac[4] << 8) | (uint64_t) mac[5];
|
|
w1 = (mac[0] << 8) | mac[1];
|
|
w2 = (mac[2] << 8) | mac[3];
|
|
w3 = (mac[4] << 8) | mac[5];
|
|
|
|
m--;
|
|
mdio_writereg(fd, 0x1b, 0x0d, (m >> 32) & 0xffff);
|
|
mdio_writereg(fd, 0x1b, 0x0e, (m >> 16) & 0xffff);
|
|
mdio_writereg(fd, 0x1b, 0x0f, (m >> 0) & 0xffff);
|
|
mdio_writereg(fd, 0x1b, 0x0b, 0xc000);
|
|
mdio_wait_switch(fd, 0x1b, 0x0b);
|
|
mdio_readreg(fd, 0x1b, 0x0c, &r0c);
|
|
|
|
if (!(r0c & 0x0f)) {
|
|
mdio_close(fd);
|
|
return -1;
|
|
}
|
|
vector = (r0c >> 4) & 0x7f;
|
|
state = r0c & 0x0f;
|
|
|
|
mdio_readreg(fd, 0x1b, 0x0d, &aw1);
|
|
mdio_readreg(fd, 0x1b, 0x0e, &aw2);
|
|
mdio_readreg(fd, 0x1b, 0x0f, &aw3);
|
|
mdio_close(fd);
|
|
|
|
if (w1 == aw1 && w2 == aw2 && w3 == aw3) {
|
|
dbgprintf(DEBUG_SWITCH, "%02x: %02x:%02x:%02x:%02x:%02x:%02x %d\n",
|
|
vector,
|
|
aw1 >> 8, aw1 & 0xff,
|
|
aw2 >> 8, aw2 & 0xff,
|
|
aw3 >> 8, aw3 & 0xff,
|
|
state);
|
|
return vector;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int switch_set_multicast(uint8_t mac[6], uint8_t vec)
|
|
{
|
|
int fd = mdio_open();
|
|
|
|
dbgprintf(DEBUG_SWITCH, "switch_set_multicast %02x:%02x:%02x:%02x:%02x:%02x = %02x\n",
|
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], vec);
|
|
if (fd < 0)
|
|
return -1;
|
|
if (vec)
|
|
mdio_writereg(fd, 0x1b, 0x0c, (vec << 4) | 7);
|
|
else
|
|
mdio_writereg(fd, 0x1b, 0x0c, 0);
|
|
mdio_writereg(fd, 0x1b, 0x0d, ((uint16_t) mac[0] << 8) | mac[1]);
|
|
mdio_writereg(fd, 0x1b, 0x0e, ((uint16_t) mac[2] << 8) | mac[3]);
|
|
mdio_writereg(fd, 0x1b, 0x0f, ((uint16_t) mac[4] << 8) | mac[5]);
|
|
mdio_writereg(fd, 0x1b, 0x0b, 0xb000);
|
|
mdio_wait_switch(fd, 0x1b, 0x0b);
|
|
mdio_close(fd);
|
|
return 0;
|
|
}
|
|
|
|
int switch_test(void)
|
|
{
|
|
int fd = mdio_open();
|
|
int res;
|
|
|
|
res = mdio_writereg(fd, 0x1b, 0x0d, 0xffff);
|
|
if (res < 0)
|
|
return 0;
|
|
mdio_writereg(fd, 0x1b, 0x0e, 0xffff);
|
|
mdio_writereg(fd, 0x1b, 0x0f, 0xffff);
|
|
|
|
while (1) {
|
|
uint16_t r0c, aw1, aw2, aw3;
|
|
uint16_t vector, state;
|
|
|
|
mdio_writereg(fd, 0x1b, 0x0b, 0xc000);
|
|
mdio_wait_switch(fd, 0x1b, 0x0b);
|
|
mdio_readreg(fd, 0x1b, 0x0c, &r0c);
|
|
if (!(r0c & 0x0f))
|
|
break;
|
|
vector = (r0c >> 4) & 0x7f;
|
|
state = r0c & 0x0f;
|
|
|
|
mdio_readreg(fd, 0x1b, 0x0d, &aw1);
|
|
mdio_readreg(fd, 0x1b, 0x0e, &aw2);
|
|
mdio_readreg(fd, 0x1b, 0x0f, &aw3);
|
|
|
|
dbgprintf(DEBUG_SWITCH, "%02x: %02x:%02x:%02x:%02x:%02x:%02x %d\n",
|
|
vector,
|
|
aw1 >> 8, aw1 & 0xff,
|
|
aw2 >> 8, aw2 & 0xff,
|
|
aw3 >> 8, aw3 & 0xff,
|
|
state);
|
|
}
|
|
mdio_close(fd);
|
|
return 1;
|
|
}
|