Force speed negociation: The card seems unable to negociate link. I modified the
fa_select.c used under linux to fix that problem.
Here's the code for FreeBSD:
/* fa_select.c */
/* modified for FreeBSD 4.x */
/* */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <machine/sysarch.h>
#define BASE_ADDR 0x240 /* replace with the card base address */
inline unsigned char
inb (unsigned short port)
{
unsigned char _v;
__asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (port));
return _v;
}
inline void
outb (unsigned char value, unsigned short port)
{
__asm__ __volatile__ ("outb %b0,%w1"::"a" (value), "Nd" (port));
}
static int sockets_open(void)
{
int sock;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) != -1)
return sock;
else if ((sock = socket(AF_IPX, SOCK_DGRAM, 0)) != -1)
return sock;
else
return socket(AF_APPLETALK, SOCK_DGRAM, 0);
}
void write_bit(int port, int bit)
{
outb((bit << 6) + 0x20, port);
usleep(1);
outb((bit << 6) + 0xa0, port);
usleep(1);
outb((bit << 6) + 0x20, port);
}
int read_bit(int port)
{
int i;
outb(0, port);
usleep(1);
outb(0x80, port);
usleep(1);
i = inb(port);
outb(0, port);
return (i & 0x10) >> 4;
}
void reset(int port)
{
outb(0x08, port);
usleep(1);
outb(0x0C, port);
usleep(1);
outb(0x08, port);
usleep(1);
outb(0x0C, port);
outb(0x00, port);
}
int reada(int port, int adr)
{
int i,j;
for (i=0; i<0x20; i++)
write_bit(port, 1);
write_bit(port, 0);
write_bit(port, 1);
write_bit(port, 1);
write_bit(port, 0);
write_bit(port, 0);
write_bit(port, 0);
write_bit(port, 0);
write_bit(port, 0);
write_bit(port, 0);
write_bit(port, (adr & 0x10) >> 4);
write_bit(port, (adr & 0x08) >> 3);
write_bit(port, (adr & 0x04) >> 2);
write_bit(port, (adr & 0x02) >> 1);
write_bit(port, (adr & 0x01) >> 0);
j = read_bit(port);
if (j == 1)
j = read_bit(port);
for (i=0; i<16; i++) {
j = (j << 1) + read_bit(port);
}
write_bit(port, 1);
return j;
}
int writea(int port, int adr, int val)
{
int i;
outb(0x08, port);
usleep(1);
outb(0x0C, port);
usleep(1);
outb(0x08, port);
usleep(1);
outb(0x0C, port);
outb(0x00, port);
for (i=0; i<0x20; i++)
write_bit(port, 1);
write_bit(port, 0);
write_bit(port, 1);
write_bit(port, 0);
write_bit(port, 1);
write_bit(port, 0);
write_bit(port, 0);
write_bit(port, 0);
write_bit(port, 0);
write_bit(port, 0);
write_bit(port, (adr & 0x10) >> 4);
write_bit(port, (adr & 0x08) >> 3);
write_bit(port, (adr & 0x04) >> 2);
write_bit(port, (adr & 0x02) >> 1);
write_bit(port, (adr & 0x01) >> 0);
write_bit(port, 1);
write_bit(port, 0);
write_bit(port, (val & 0x8000) >> 15);
write_bit(port, (val & 0x4000) >> 14);
write_bit(port, (val & 0x2000) >> 13);
write_bit(port, (val & 0x1000) >> 12);
write_bit(port, (val & 0x0800) >> 11);
write_bit(port, (val & 0x0400) >> 10);
write_bit(port, (val & 0x0200) >> 9);
write_bit(port, (val & 0x0100) >> 8);
write_bit(port, (val & 0x0080) >> 7);
write_bit(port, (val & 0x0040) >> 6);
write_bit(port, (val & 0x0020) >> 5);
write_bit(port, (val & 0x0010) >> 4);
write_bit(port, (val & 0x0008) >> 3);
write_bit(port, (val & 0x0004) >> 2);
write_bit(port, (val & 0x0002) >> 1);
write_bit(port, (val & 0x0001) >> 0);
write_bit(port, 1);
return 0;
}
int
main(int argc, char **argv)
{
int skfd, i, sub;
struct ifreq ifr;
skfd = sockets_open();
if (skfd == -1) {
perror("socket");
exit(1);
}
strcpy(ifr.ifr_name, argv[1]);
/* if (ioctl(skfd, SIOCGIFMAP, &ifr) < 0) {
perror("ioctl");
exit(1);
}*/
i = atoi(argv[2]);
switch(i) {
case 0:
sub = 0x0000;
break;
case 1:
sub = 0x0100;
break;
case 2:
sub = 0x2000;
break;
default:
sub = 0x2100;
break;
}
i386_set_ioperm(BASE_ADDR+0x1c, 1, 1);
reset(BASE_ADDR+0x1c);
writea(BASE_ADDR+0x1c, 0, 0x8000);
writea(BASE_ADDR+0x1c, 0, sub);
close(skfd);
exit(0);
return 0;
}
You can find the source here: http://webperso.easynet.fr/fonvi/fa_select.c
Don't forget to change #define BASE_ADDR 0x240 with the card address.
To compile it: gcc -Wall fa_select.c -o fa_select
To use it:
fa_select device rate
where device is: ed0, ed1...
rate is: 0 for 10BaseT
1 for 10Base2 (full duplex)
2 for 100BaseT
3 for 100Mbit (full duplex)
I tried this with my adsl modem (Alcatel 1000 Adsl) with fa_select ed1 0 and
it runs fine without timeout. It runs fine also on my on Lan.