2014-06-08 10:51:01 +04:00
/* vim: tabstop=4 shiftwidth=4 noexpandtab
2014-06-08 10:58:31 +04:00
* This file is part of ToaruOS and is released under the terms
2014-06-08 10:13:29 +04:00
* of the NCSA / University of Illinois License - see LICENSE . md
* Copyright ( C ) 2014 Kevin Lange
*/
2014-05-07 09:14:05 +04:00
# include <module.h>
# include <logging.h>
# include <printf.h>
# include <pci.h>
# include <mem.h>
2014-05-08 10:08:34 +04:00
# include <list.h>
2014-06-08 00:25:28 +04:00
# include <pipe.h>
2014-05-07 09:14:05 +04:00
# include <ipv4.h>
# include <mod/shell.h>
static uint32_t rtl_device_pci = 0x00000000 ;
static void find_rtl ( uint32_t device , uint16_t vendorid , uint16_t deviceid , void * extra ) {
if ( ( vendorid = = 0x10ec ) & & ( deviceid = = 0x8139 ) ) {
* ( ( uint32_t * ) extra ) = device ;
}
}
# define RTL_PORT_MAC 0x00
# define RTL_PORT_MAR 0x08
# define RTL_PORT_TXSTAT 0x10
# define RTL_PORT_TXBUF 0x20
# define RTL_PORT_RBSTART 0x30
# define RTL_PORT_CMD 0x37
# define RTL_PORT_RXPTR 0x38
# define RTL_PORT_RXADDR 0x3A
# define RTL_PORT_IMR 0x3C
# define RTL_PORT_ISR 0x3E
# define RTL_PORT_TCR 0x40
# define RTL_PORT_RCR 0x44
# define RTL_PORT_RXMISS 0x4C
# define RTL_PORT_CONFIG 0x52
static int rtl_irq = 0 ;
static uint32_t rtl_iobase = 0 ;
static uint8_t * rtl_rx_buffer ;
2014-05-07 11:17:31 +04:00
static uint8_t * rtl_tx_buffer [ 5 ] ;
2014-05-14 09:09:15 +04:00
static uint8_t mac [ 6 ] ;
2014-05-07 09:14:05 +04:00
2014-05-08 10:08:34 +04:00
static uint8_t * last_packet = NULL ;
2014-05-07 09:14:05 +04:00
static uintptr_t rtl_rx_phys ;
2014-05-07 11:17:31 +04:00
static uintptr_t rtl_tx_phys [ 5 ] ;
2014-05-07 09:14:05 +04:00
static uint32_t cur_rx = 0 ;
2014-05-07 10:29:17 +04:00
static int dirty_tx = 0 ;
2014-05-15 10:24:43 +04:00
static int next_tx = 0 ;
2014-05-07 09:14:05 +04:00
2014-05-08 10:08:34 +04:00
static list_t * rx_wait ;
2014-06-08 00:25:28 +04:00
static fs_node_t * irc_socket ;
2014-05-15 08:02:10 +04:00
static uint32_t seq_no = 0xff0000 ;
2014-05-15 10:24:43 +04:00
static uint32_t ack_no = 0x0 ;
2014-05-18 10:16:30 +04:00
2014-05-19 07:23:21 +04:00
static volatile uint8_t _lock ;
static int next_tx_buf ( void ) {
int out ;
spin_lock ( & _lock ) ;
out = next_tx ;
next_tx + + ;
if ( next_tx = = 4 ) {
next_tx = 0 ;
}
spin_unlock ( & _lock ) ;
return out ;
}
2014-06-08 00:25:28 +04:00
struct netif {
void * extra ;
void ( * write_packet ) ( struct sized_blob * payload ) ;
uint8_t hwaddr [ 6 ] ;
uint32_t source ;
} ;
static size_t build_tcp_packet ( uint8_t * buffer , struct netif * netif , struct tcp_socket * socket , struct sized_blob * payload , uint16_t flags ) {
size_t offset = 0 ;
struct ethernet_packet eth_out = {
. source = { netif - > hwaddr [ 0 ] , netif - > hwaddr [ 1 ] , netif - > hwaddr [ 2 ] ,
netif - > hwaddr [ 3 ] , netif - > hwaddr [ 4 ] , netif - > hwaddr [ 5 ] } ,
. destination = { socket - > mac [ 0 ] , socket - > mac [ 1 ] , socket - > mac [ 2 ] ,
socket - > mac [ 3 ] , socket - > mac [ 4 ] , socket - > mac [ 5 ] } ,
. type = htons ( 0x0800 ) ,
} ;
memcpy ( & buffer [ offset ] , & eth_out , sizeof ( struct ethernet_packet ) ) ;
offset + = sizeof ( struct ethernet_packet ) ;
/* Prepare the IPv4 header */
uint16_t _length = htons ( sizeof ( struct ipv4_packet ) + sizeof ( struct tcp_header ) + payload - > size ) ;
uint16_t _ident = htons ( 1 ) ;
struct ipv4_packet ipv4_out = {
. version_ihl = ( ( 0x4 < < 4 ) | ( 0x5 < < 0 ) ) , /* 4 = ipv4, 5 = no options */
. dscp_ecn = 0 , /* not setting either of those */
. length = _length ,
. ident = _ident ,
. flags_fragment = 0 ,
. ttl = 0x40 , /* ... */
. protocol = IPV4_PROT_TCP ,
. checksum = 0 , /* fill this in later */
. source = htonl ( netif - > source ) ,
. destination = htonl ( socket - > ip ) ,
} ;
uint16_t checksum = calculate_ipv4_checksum ( & ipv4_out ) ;
ipv4_out . checksum = htons ( checksum ) ;
memcpy ( & buffer [ offset ] , & ipv4_out , sizeof ( struct ipv4_packet ) ) ;
offset + = sizeof ( struct ipv4_packet ) ;
struct tcp_header tcp = {
. source_port = htons ( socket - > port_recv ) , /* Ephemeral port */
. destination_port = htons ( socket - > port_dest ) , /* IRC */
. seq_number = htonl ( socket - > seq_no ) ,
. ack_number = flags & ( TCP_FLAGS_ACK ) ? htonl ( socket - > ack_no ) : 0 ,
. flags = htons ( flags ) ,
. window_size = htons ( 1800 ) ,
. checksum = 0 ,
. urgent = 0 ,
} ;
struct tcp_check_header check_hd = {
. source = ipv4_out . source ,
. destination = ipv4_out . destination ,
. zeros = 0 ,
. protocol = 6 ,
. tcp_len = htons ( sizeof ( tcp ) + payload - > size ) ,
} ;
uint16_t t = calculate_tcp_checksum ( & check_hd , & tcp , payload , payload - > size ) ;
tcp . checksum = htons ( t ) ;
memcpy ( & buffer [ offset ] , & tcp , sizeof ( struct tcp_header ) ) ;
offset + = sizeof ( struct tcp_header ) ;
memcpy ( & buffer [ offset ] , payload , payload - > size ) ;
offset + = payload - > size ;
return offset ;
}
2014-05-15 08:02:10 +04:00
static size_t write_tcp_packet ( uint8_t * buffer , uint8_t * payload , size_t payload_size , uint16_t flags ) {
2014-05-15 03:34:05 +04:00
size_t offset = 0 ;
/* Then, let's write an ethernet frame */
struct ethernet_packet eth_out = {
. source = { mac [ 0 ] , mac [ 1 ] , mac [ 2 ] , mac [ 3 ] , mac [ 4 ] , mac [ 5 ] } ,
. destination = BROADCAST_MAC ,
. type = htons ( 0x0800 ) ,
} ;
memcpy ( & buffer [ offset ] , & eth_out , sizeof ( struct ethernet_packet ) ) ;
offset + = sizeof ( struct ethernet_packet ) ;
/* Prepare the IPv4 header */
uint16_t _length = htons ( sizeof ( struct ipv4_packet ) + sizeof ( struct tcp_header ) + payload_size ) ;
uint16_t _ident = htons ( 1 ) ;
struct ipv4_packet ipv4_out = {
. version_ihl = ( ( 0x4 < < 4 ) | ( 0x5 < < 0 ) ) , /* 4 = ipv4, 5 = no options */
. dscp_ecn = 0 , /* not setting either of those */
. length = _length ,
. ident = _ident ,
. flags_fragment = 0 ,
. ttl = 0x40 ,
. protocol = IPV4_PROT_TCP ,
. checksum = 0 , /* fill this in later */
. source = htonl ( ip_aton ( " 10.0.2.15 " ) ) ,
2014-05-17 23:26:14 +04:00
. destination = htonl ( ip_aton ( " 37.48.83.75 " ) ) ,
//.destination = htonl(ip_aton("204.28.125.145")),
2014-05-16 07:45:14 +04:00
//.destination = htonl(ip_aton("192.168.1.145")),
2014-05-18 05:50:52 +04:00
//.destination = htonl(ip_aton("107.170.207.248")),
2014-05-15 03:34:05 +04:00
} ;
uint16_t checksum = calculate_ipv4_checksum ( & ipv4_out ) ;
ipv4_out . checksum = htons ( checksum ) ;
memcpy ( & buffer [ offset ] , & ipv4_out , sizeof ( struct ipv4_packet ) ) ;
offset + = sizeof ( struct ipv4_packet ) ;
struct tcp_header tcp = {
. source_port = htons ( 56667 ) , /* Ephemeral port */
. destination_port = htons ( 6667 ) , /* IRC */
2014-05-18 05:50:52 +04:00
//.destination_port = htons(23),
2014-05-15 08:02:10 +04:00
. seq_number = htonl ( seq_no ) ,
2014-05-15 10:24:43 +04:00
. ack_number = flags & ( TCP_FLAGS_ACK ) ? htonl ( ack_no ) : 0 ,
2014-05-15 08:02:10 +04:00
. flags = htons ( flags ) ,
2014-05-18 05:50:52 +04:00
. window_size = htons ( 1800 ) ,
2014-05-15 03:34:05 +04:00
. checksum = 0 ,
. urgent = 0 ,
} ;
struct tcp_check_header check_hd = {
. source = ipv4_out . source ,
. destination = ipv4_out . destination ,
. zeros = 0 ,
. protocol = 6 ,
2014-05-15 10:24:43 +04:00
. tcp_len = htons ( sizeof ( tcp ) + payload_size ) ,
2014-05-15 03:34:05 +04:00
} ;
2014-06-08 00:25:28 +04:00
uint16_t t = calculate_tcp_checksum ( & check_hd , & tcp , payload , payload_size ) ;
2014-05-15 03:34:05 +04:00
tcp . checksum = htons ( t ) ;
memcpy ( & buffer [ offset ] , & tcp , sizeof ( struct tcp_header ) ) ;
offset + = sizeof ( struct tcp_header ) ;
2014-05-15 10:24:43 +04:00
memcpy ( & buffer [ offset ] , payload , payload_size ) ;
offset + = payload_size ;
2014-05-15 03:34:05 +04:00
return offset ;
}
2014-05-14 09:09:15 +04:00
static size_t write_dhcp_packet ( uint8_t * buffer ) {
size_t offset = 0 ;
size_t payload_size = sizeof ( struct dhcp_packet ) ;
/* First, let's figure out how big this is supposed to be... */
uint8_t dhcp_options [ ] = {
53 , /* Message type */
1 , /* Length: 1 */
1 , /* Discover */
255 , /* END */
} ;
payload_size + = sizeof ( dhcp_options ) ;
/* Then, let's write an ethernet frame */
struct ethernet_packet eth_out = {
. source = { mac [ 0 ] , mac [ 1 ] , mac [ 2 ] , mac [ 3 ] , mac [ 4 ] , mac [ 5 ] } ,
. destination = BROADCAST_MAC ,
. type = htons ( 0x0800 ) ,
} ;
memcpy ( & buffer [ offset ] , & eth_out , sizeof ( struct ethernet_packet ) ) ;
offset + = sizeof ( struct ethernet_packet ) ;
/* Prepare the IPv4 header */
uint16_t _length = htons ( sizeof ( struct ipv4_packet ) + sizeof ( struct udp_packet ) + payload_size ) ;
uint16_t _ident = htons ( 1 ) ;
struct ipv4_packet ipv4_out = {
. version_ihl = ( ( 0x4 < < 4 ) | ( 0x5 < < 0 ) ) , /* 4 = ipv4, 5 = no options */
. dscp_ecn = 0 , /* not setting either of those */
. length = _length ,
. ident = _ident ,
. flags_fragment = 0 ,
. ttl = 0x40 ,
. protocol = IPV4_PROT_UDP ,
. checksum = 0 , /* fill this in later */
2014-05-14 09:59:36 +04:00
. source = htonl ( ip_aton ( " 0.0.0.0 " ) ) ,
2014-05-18 10:16:30 +04:00
. destination = htonl ( ip_aton ( " 255.255.255.255 " ) ) ,
2014-05-14 09:09:15 +04:00
} ;
uint16_t checksum = calculate_ipv4_checksum ( & ipv4_out ) ;
ipv4_out . checksum = htons ( checksum ) ;
memcpy ( & buffer [ offset ] , & ipv4_out , sizeof ( struct ipv4_packet ) ) ;
offset + = sizeof ( struct ipv4_packet ) ;
uint16_t _udp_source = htons ( 68 ) ;
uint16_t _udp_destination = htons ( 67 ) ;
uint16_t _udp_length = htons ( sizeof ( struct udp_packet ) + payload_size ) ;
/* Now let's build a UDP packet */
struct udp_packet udp_out = {
. source_port = _udp_source ,
. destination_port = _udp_destination ,
. length = _udp_length ,
. checksum = 0 ,
} ;
/* XXX calculate checksum here */
memcpy ( & buffer [ offset ] , & udp_out , sizeof ( struct udp_packet ) ) ;
offset + = sizeof ( struct udp_packet ) ;
/* BOOTP headers */
struct dhcp_packet bootp_out = {
. op = 1 ,
. htype = 1 ,
. hlen = 6 , /* mac address... */
. hops = 0 ,
. xid = htonl ( 0x1337 ) , /* transaction id */
. secs = 0 ,
. flags = 0 ,
. ciaddr = 0x000000 ,
. yiaddr = 0x000000 ,
. siaddr = 0x000000 ,
. giaddr = 0x000000 ,
. chaddr = { mac [ 0 ] , mac [ 1 ] , mac [ 2 ] , mac [ 3 ] , mac [ 4 ] , mac [ 5 ] , 0x00 } ,
. sname = { 0 } ,
. file = { 0 } ,
. magic = htonl ( DHCP_MAGIC ) ,
} ;
memcpy ( & buffer [ offset ] , & bootp_out , sizeof ( struct dhcp_packet ) ) ;
offset + = sizeof ( struct dhcp_packet ) ;
memcpy ( & buffer [ offset ] , & dhcp_options , sizeof ( dhcp_options ) ) ;
offset + = sizeof ( dhcp_options ) ;
return offset ;
}
2014-05-14 12:44:31 +04:00
static size_t write_dns_packet ( uint8_t * buffer , size_t queries_len , uint8_t * queries ) {
2014-05-14 09:09:15 +04:00
size_t offset = 0 ;
2014-05-14 12:44:31 +04:00
size_t payload_size = sizeof ( struct dns_packet ) + queries_len ;
2014-05-14 09:09:15 +04:00
/* Then, let's write an ethernet frame */
struct ethernet_packet eth_out = {
. source = { mac [ 0 ] , mac [ 1 ] , mac [ 2 ] , mac [ 3 ] , mac [ 4 ] , mac [ 5 ] } ,
. destination = BROADCAST_MAC ,
. type = htons ( 0x0800 ) ,
} ;
memcpy ( & buffer [ offset ] , & eth_out , sizeof ( struct ethernet_packet ) ) ;
offset + = sizeof ( struct ethernet_packet ) ;
/* Prepare the IPv4 header */
uint16_t _length = htons ( sizeof ( struct ipv4_packet ) + sizeof ( struct udp_packet ) + payload_size ) ;
uint16_t _ident = htons ( 1 ) ;
struct ipv4_packet ipv4_out = {
. version_ihl = ( ( 0x4 < < 4 ) | ( 0x5 < < 0 ) ) , /* 4 = ipv4, 5 = no options */
. dscp_ecn = 0 , /* not setting either of those */
. length = _length ,
. ident = _ident ,
. flags_fragment = 0 ,
. ttl = 0x40 ,
. protocol = IPV4_PROT_UDP ,
. checksum = 0 , /* fill this in later */
2014-05-14 09:59:36 +04:00
. source = htonl ( ip_aton ( " 10.0.2.15 " ) ) ,
. destination = htonl ( ip_aton ( " 10.0.2.3 " ) ) ,
2014-05-14 09:09:15 +04:00
} ;
uint16_t checksum = calculate_ipv4_checksum ( & ipv4_out ) ;
ipv4_out . checksum = htons ( checksum ) ;
memcpy ( & buffer [ offset ] , & ipv4_out , sizeof ( struct ipv4_packet ) ) ;
offset + = sizeof ( struct ipv4_packet ) ;
uint16_t _udp_source = htons ( 50053 ) ; /* Use an ephemeral port */
uint16_t _udp_destination = htons ( 53 ) ;
uint16_t _udp_length = htons ( sizeof ( struct udp_packet ) + payload_size ) ;
/* Now let's build a UDP packet */
struct udp_packet udp_out = {
. source_port = _udp_source ,
. destination_port = _udp_destination ,
. length = _udp_length ,
. checksum = 0 ,
} ;
/* XXX calculate checksum here */
memcpy ( & buffer [ offset ] , & udp_out , sizeof ( struct udp_packet ) ) ;
offset + = sizeof ( struct udp_packet ) ;
/* DNS header */
struct dns_packet dns_out = {
. qid = htons ( 0 ) ,
. flags = htons ( 0x0100 ) , /* Standard query */
. questions = htons ( 1 ) , /* 1 question */
. answers = htons ( 0 ) ,
. authorities = htons ( 0 ) ,
. additional = htons ( 0 ) ,
} ;
memcpy ( & buffer [ offset ] , & dns_out , sizeof ( struct dns_packet ) ) ;
offset + = sizeof ( struct dns_packet ) ;
2014-05-14 12:44:31 +04:00
memcpy ( & buffer [ offset ] , queries , queries_len ) ;
offset + = queries_len ;
2014-05-14 09:09:15 +04:00
return offset ;
}
2014-05-08 10:08:34 +04:00
2014-05-19 07:23:21 +04:00
static char irc_input [ 400 ] = { ' \0 ' } ;
static char irc_prompt [ 100 ] = { ' \0 ' } ;
static char irc_nick [ 32 ] = { ' \0 ' } ;
static char irc_payload [ 512 ] ;
2014-05-20 06:39:04 +04:00
static volatile uint8_t irc_tty_lock = 0 ;
2014-06-08 00:25:28 +04:00
//static struct netif rtl_netif;
2014-05-19 07:23:21 +04:00
static void irc_send ( char * payload ) {
int my_tx = next_tx_buf ( ) ;
int l = strlen ( payload ) ;
size_t packet_size = write_tcp_packet ( rtl_tx_buffer [ my_tx ] , ( uint8_t * ) payload , l , ( TCP_FLAGS_ACK | DATA_OFFSET_5 ) ) ;
outportl ( rtl_iobase + RTL_PORT_TXBUF + 4 * my_tx , rtl_tx_phys [ my_tx ] ) ;
outportl ( rtl_iobase + RTL_PORT_TXSTAT + 4 * my_tx , packet_size ) ;
}
static void handle_irc_packet ( fs_node_t * tty , size_t size , uint8_t * packet ) {
char * c = ( char * ) packet ;
while ( ( uintptr_t ) c < ( uintptr_t ) packet + size ) {
char * e = strstr ( c , " \r \n " ) ;
if ( ( uintptr_t ) e > ( uintptr_t ) packet + size ) {
break ;
}
2014-05-20 06:39:04 +04:00
spin_lock ( & irc_tty_lock ) ;
2014-05-19 07:23:21 +04:00
if ( ! e ) {
/* XXX */
c [ size - 1 ] = ' \0 ' ;
fprintf ( tty , " \r \033 [36m%s \033 [0m \033 [K \n " , c ) ;
goto prompt_ ;
}
e [ 0 ] = ' \0 ' ;
if ( startswith ( c , " PING " ) ) {
char tmp [ 100 ] ;
char * t = strstr ( c , " : " ) ;
sprintf ( tmp , " PONG %s \r \n " , t ) ;
irc_send ( tmp ) ;
goto prompt_ ;
}
char * user ;
char * command ;
char * channel ;
char * message ;
user = c ;
command = strstr ( user , " " ) ;
if ( ! command ) {
fprintf ( tty , " \r \033 [36m%s \033 [0m \033 [K \n " , user ) ;
goto prompt_ ;
}
command [ 0 ] = ' \0 ' ;
command + + ;
channel = strstr ( command , " " ) ;
if ( ! channel ) {
fprintf ( tty , " \r \033 [36m%s %s \033 [0m \033 [K \n " , user , command ) ;
goto prompt_ ;
}
channel [ 0 ] = ' \0 ' ;
channel + + ;
if ( ! strcmp ( command , " PRIVMSG " ) ) {
message = strstr ( channel , " " ) ;
if ( ! message ) {
2014-05-24 00:26:03 +04:00
fprintf ( tty , " \r \033 [36m%s %s %s \033 [0m \033 [K \n " , user , command , channel ) ;
2014-05-19 07:23:21 +04:00
goto prompt_ ;
}
message [ 0 ] = ' \0 ' ;
message + + ;
if ( message [ 0 ] = = ' : ' ) { message + + ; }
if ( user [ 0 ] = = ' : ' ) { user + + ; }
char * t = strstr ( user , " ! " ) ;
if ( t ) { t [ 0 ] = ' \0 ' ; }
t = strstr ( user , " @ " ) ;
if ( t ) { t [ 0 ] = ' \0 ' ; }
2014-05-20 06:39:04 +04:00
uint16_t hr , min , sec ;
get_time ( & hr , & min , & sec ) ;
if ( startswith ( message , " \001 ACTION " ) ) {
message = message + 8 ;
char * x = strstr ( message , " \001 " ) ;
if ( x ) * x = ' \0 ' ;
fprintf ( tty , " \r %2d:%2d:%2d * \033 [32m%s \033 [0m: \033 [34m%s \033 [0m %s \033 [K \n " , hr , min , sec , user , channel , message ) ;
} else {
fprintf ( tty , " \r %2d:%2d:%2d \033 [90m< \033 [32m%s \033 [0m: \033 [34m%s \033 [90m> \033 [0m %s \033 [K \n " , hr , min , sec , user , channel , message ) ;
}
2014-05-19 07:23:21 +04:00
} else {
fprintf ( tty , " \r \033 [36m%s %s %s \033 [0m \033 [K \n " , user , command , channel ) ;
}
prompt_ :
/* Redraw prompt */
fprintf ( tty , " %s " , irc_prompt ) ;
fprintf ( tty , " %s " , irc_input ) ;
2014-05-20 06:39:04 +04:00
spin_unlock ( & irc_tty_lock ) ;
2014-05-19 07:23:21 +04:00
if ( ! e ) break ;
c = e + 2 ;
}
2014-06-08 00:25:28 +04:00
}
static char * fgets ( char * buf , int size , fs_node_t * stream ) {
char * x = buf ;
int collected = 0 ;
while ( collected < size ) {
int r = read_fs ( stream , 0 , 1 , ( unsigned char * ) x ) ;
collected + = r ;
if ( r = = - 1 ) return NULL ;
if ( ! r ) break ;
if ( * x = = ' \n ' ) break ;
x + = r ;
}
x + + ;
* x = ' \0 ' ;
return buf ;
}
static void rtl_ircd ( void * data , char * name ) {
fs_node_t * tty = data ;
char * buf = malloc ( 4096 ) ;
while ( 1 ) {
2014-08-06 09:33:56 +04:00
char * result = fgets ( buf , 4095 , irc_socket ) ;
if ( ! result ) continue ;
2014-06-08 00:25:28 +04:00
size_t len = strlen ( buf ) ;
2014-08-06 09:33:56 +04:00
if ( ! len ) continue ;
2014-06-08 00:25:28 +04:00
handle_irc_packet ( tty , len , ( unsigned char * ) buf ) ;
}
2014-05-19 07:23:21 +04:00
}
2014-05-14 12:23:12 +04:00
static size_t print_dns_name ( fs_node_t * tty , struct dns_packet * dns , size_t offset ) {
uint8_t * bytes = ( uint8_t * ) dns ;
while ( 1 ) {
uint8_t c = bytes [ offset ] ;
if ( c = = 0 ) {
offset + + ;
return offset ;
} else if ( c > = 0xC0 ) {
uint16_t ref = ( ( c - 0xC0 ) < < 8 ) + bytes [ offset + 1 ] ;
print_dns_name ( tty , dns , ref ) ;
offset + + ;
offset + + ;
return offset ;
} else {
for ( int i = 0 ; i < c ; + + i ) {
fprintf ( tty , " %c " , bytes [ offset + 1 + i ] ) ;
}
fprintf ( tty , " . " ) ;
offset + = c + 1 ;
}
}
}
2014-05-14 12:44:31 +04:00
static void parse_dns_response ( fs_node_t * tty , void * last_packet ) {
struct ethernet_packet * eth = ( struct ethernet_packet * ) last_packet ;
uint16_t eth_type = ntohs ( eth - > type ) ;
fprintf ( tty , " Ethernet II, Src: (%2x:%2x:%2x:%2x:%2x:%2x), Dst: (%2x:%2x:%2x:%2x:%2x:%2x) [type=%4x) \n " ,
eth - > source [ 0 ] , eth - > source [ 1 ] , eth - > source [ 2 ] ,
eth - > source [ 3 ] , eth - > source [ 4 ] , eth - > source [ 5 ] ,
eth - > destination [ 0 ] , eth - > destination [ 1 ] , eth - > destination [ 2 ] ,
eth - > destination [ 3 ] , eth - > destination [ 4 ] , eth - > destination [ 5 ] ,
eth_type ) ;
struct ipv4_packet * ipv4 = ( struct ipv4_packet * ) eth - > payload ;
uint32_t src_addr = ntohl ( ipv4 - > source ) ;
uint32_t dst_addr = ntohl ( ipv4 - > destination ) ;
uint16_t length = ntohs ( ipv4 - > length ) ;
char src_ip [ 16 ] ;
char dst_ip [ 16 ] ;
ip_ntoa ( src_addr , src_ip ) ;
ip_ntoa ( dst_addr , dst_ip ) ;
fprintf ( tty , " IP packet [%s → %s] length=%d bytes \n " ,
src_ip , dst_ip , length ) ;
struct udp_packet * udp = ( struct udp_packet * ) ipv4 - > payload ;
uint16_t src_port = ntohs ( udp - > source_port ) ;
uint16_t dst_port = ntohs ( udp - > destination_port ) ;
uint16_t udp_len = ntohs ( udp - > length ) ;
fprintf ( tty , " UDP [%d → %d] length=%d bytes \n " ,
src_port , dst_port , udp_len ) ;
struct dns_packet * dns = ( struct dns_packet * ) udp - > payload ;
uint16_t dns_questions = ntohs ( dns - > questions ) ;
uint16_t dns_answers = ntohs ( dns - > answers ) ;
fprintf ( tty , " DNS - %d queries, %d answers \n " ,
dns_questions , dns_answers ) ;
fprintf ( tty , " Queries: \n " ) ;
int offset = sizeof ( struct dns_packet ) ;
int queries = 0 ;
uint8_t * bytes = ( uint8_t * ) dns ;
while ( queries < dns_questions ) {
offset = print_dns_name ( tty , dns , offset ) ;
uint16_t * d = ( uint16_t * ) & bytes [ offset ] ;
fprintf ( tty , " - Type: %4x %4x \n " , ntohs ( d [ 0 ] ) , ntohs ( d [ 1 ] ) ) ;
offset + = 4 ;
queries + + ;
}
fprintf ( tty , " Answers: \n " ) ;
int answers = 0 ;
while ( answers < dns_answers ) {
offset = print_dns_name ( tty , dns , offset ) ;
uint16_t * d = ( uint16_t * ) & bytes [ offset ] ;
fprintf ( tty , " - Type: %4x %4x; " , ntohs ( d [ 0 ] ) , ntohs ( d [ 1 ] ) ) ;
offset + = 4 ;
uint32_t * t = ( uint32_t * ) & bytes [ offset ] ;
fprintf ( tty , " TTL: %d; " , ntohl ( t [ 0 ] ) ) ;
offset + = 4 ;
uint16_t * l = ( uint16_t * ) & bytes [ offset ] ;
int _l = ntohs ( l [ 0 ] ) ;
fprintf ( tty , " len: %d; " , _l ) ;
offset + = 2 ;
if ( _l = = 4 ) {
uint32_t * i = ( uint32_t * ) & bytes [ offset ] ;
char ip [ 16 ] ;
ip_ntoa ( ntohl ( i [ 0 ] ) , ip ) ;
fprintf ( tty , " Address: %s \n " , ip ) ;
} else {
if ( ntohs ( d [ 0 ] ) = = 5 ) {
fprintf ( tty , " CNAME: " ) ;
print_dns_name ( tty , dns , offset ) ;
fprintf ( tty , " \n " ) ;
} else {
fprintf ( tty , " dunno \n " ) ;
}
}
offset + = _l ;
answers + + ;
}
}
2014-05-07 09:14:05 +04:00
static void rtl_irq_handler ( struct regs * r ) {
uint16_t status = inports ( rtl_iobase + RTL_PORT_ISR ) ;
outports ( rtl_iobase + RTL_PORT_ISR , status ) ;
irq_ack ( rtl_irq ) ;
if ( status & 0x01 | | status & 0x02 ) {
/* Receive */
while ( ( inportb ( rtl_iobase + RTL_PORT_CMD ) & 0x01 ) = = 0 ) {
int offset = cur_rx % 0x2000 ;
#if 0
uint16_t buf_addr = inports ( rtl_iobase + RTL_PORT_RXADDR ) ;
uint16_t buf_ptr = inports ( rtl_iobase + RTL_PORT_RXPTR ) ;
uint8_t cmd = inportb ( rtl_iobase + RTL_PORT_CMD ) ;
# endif
uint32_t * buf_start = ( uint32_t * ) ( ( uintptr_t ) rtl_rx_buffer + offset ) ;
uint32_t rx_status = buf_start [ 0 ] ;
int rx_size = rx_status > > 16 ;
if ( rx_status & ( 0x0020 | 0x0010 | 0x0004 | 0x0002 ) ) {
debug_print ( WARNING , " rx error :( " ) ;
} else {
uint8_t * buf_8 = ( uint8_t * ) & ( buf_start [ 1 ] ) ;
2014-05-08 10:08:34 +04:00
last_packet = buf_8 ;
2014-05-07 09:14:05 +04:00
}
cur_rx = ( cur_rx + rx_size + 4 + 3 ) & ~ 3 ;
outports ( rtl_iobase + RTL_PORT_RXPTR , cur_rx - 16 ) ;
}
2014-05-08 10:08:34 +04:00
wakeup_queue ( rx_wait ) ;
2014-05-07 09:14:05 +04:00
}
if ( status & 0x08 | | status & 0x04 ) {
2014-05-07 10:29:17 +04:00
unsigned int i = inportl ( rtl_iobase + RTL_PORT_TXSTAT + 4 * dirty_tx ) ;
2014-05-09 06:29:23 +04:00
( void ) i ;
2014-05-07 10:29:17 +04:00
dirty_tx + + ;
if ( dirty_tx = = 5 ) dirty_tx = 0 ;
2014-05-07 09:14:05 +04:00
}
}
2014-05-15 10:24:43 +04:00
static void rtl_netd ( void * data , char * name ) {
fs_node_t * tty = data ;
{
fprintf ( tty , " Sending DNS query... \n " ) ;
uint8_t queries [ ] = {
3 , ' i ' , ' r ' , ' c ' ,
8 , ' f ' , ' r ' , ' e ' , ' e ' , ' n ' , ' o ' , ' d ' , ' e ' ,
3 , ' n ' , ' e ' , ' t ' ,
0 ,
0x00 , 0x01 , /* A */
0x00 , 0x01 , /* IN */
} ;
2014-05-16 07:45:14 +04:00
int my_tx = next_tx_buf ( ) ;
size_t packet_size = write_dns_packet ( rtl_tx_buffer [ my_tx ] , sizeof ( queries ) , queries ) ;
2014-05-15 10:24:43 +04:00
2014-05-16 07:45:14 +04:00
outportl ( rtl_iobase + RTL_PORT_TXBUF + 4 * my_tx , rtl_tx_phys [ my_tx ] ) ;
outportl ( rtl_iobase + RTL_PORT_TXSTAT + 4 * my_tx , packet_size ) ;
2014-05-15 10:24:43 +04:00
}
sleep_on ( rx_wait ) ;
parse_dns_response ( tty , last_packet ) ;
{
fprintf ( tty , " Sending DNS query... \n " ) ;
uint8_t queries [ ] = {
7 , ' n ' , ' y ' , ' a ' , ' n ' , ' c ' , ' a ' , ' t ' ,
5 , ' d ' , ' a ' , ' k ' , ' k ' , ' o ' ,
2 , ' u ' , ' s ' ,
0 ,
0x00 , 0x01 , /* A */
0x00 , 0x01 , /* IN */
} ;
2014-05-16 07:45:14 +04:00
int my_tx = next_tx_buf ( ) ;
size_t packet_size = write_dns_packet ( rtl_tx_buffer [ my_tx ] , sizeof ( queries ) , queries ) ;
2014-05-15 10:24:43 +04:00
2014-05-16 07:45:14 +04:00
outportl ( rtl_iobase + RTL_PORT_TXBUF + 4 * my_tx , rtl_tx_phys [ my_tx ] ) ;
outportl ( rtl_iobase + RTL_PORT_TXSTAT + 4 * my_tx , packet_size ) ;
2014-05-15 10:24:43 +04:00
}
sleep_on ( rx_wait ) ;
parse_dns_response ( tty , last_packet ) ;
{
fprintf ( tty , " Sending TCP syn \n " ) ;
2014-05-16 07:45:14 +04:00
int my_tx = next_tx_buf ( ) ;
2014-05-15 10:24:43 +04:00
uint8_t payload [ ] = { 0 } ;
2014-05-16 07:45:14 +04:00
size_t packet_size = write_tcp_packet ( rtl_tx_buffer [ my_tx ] , payload , 0 , ( TCP_FLAGS_SYN | DATA_OFFSET_5 ) ) ;
2014-05-15 10:24:43 +04:00
2014-05-16 07:45:14 +04:00
outportl ( rtl_iobase + RTL_PORT_TXBUF + 4 * my_tx , rtl_tx_phys [ my_tx ] ) ;
outportl ( rtl_iobase + RTL_PORT_TXSTAT + 4 * my_tx , packet_size ) ;
2014-05-15 10:24:43 +04:00
}
sleep_on ( rx_wait ) ;
{
struct ethernet_packet * eth = ( struct ethernet_packet * ) last_packet ;
uint16_t eth_type = ntohs ( eth - > type ) ;
fprintf ( tty , " Ethernet II, Src: (%2x:%2x:%2x:%2x:%2x:%2x), Dst: (%2x:%2x:%2x:%2x:%2x:%2x) [type=%4x) \n " ,
eth - > source [ 0 ] , eth - > source [ 1 ] , eth - > source [ 2 ] ,
eth - > source [ 3 ] , eth - > source [ 4 ] , eth - > source [ 5 ] ,
eth - > destination [ 0 ] , eth - > destination [ 1 ] , eth - > destination [ 2 ] ,
eth - > destination [ 3 ] , eth - > destination [ 4 ] , eth - > destination [ 5 ] ,
eth_type ) ;
struct ipv4_packet * ipv4 = ( struct ipv4_packet * ) eth - > payload ;
uint32_t src_addr = ntohl ( ipv4 - > source ) ;
uint32_t dst_addr = ntohl ( ipv4 - > destination ) ;
uint16_t length = ntohs ( ipv4 - > length ) ;
char src_ip [ 16 ] ;
char dst_ip [ 16 ] ;
ip_ntoa ( src_addr , src_ip ) ;
ip_ntoa ( dst_addr , dst_ip ) ;
fprintf ( tty , " IP packet [%s → %s] length=%d bytes \n " ,
src_ip , dst_ip , length ) ;
struct tcp_header * tcp = ( struct tcp_header * ) ipv4 - > payload ;
ack_no = ntohl ( tcp - > seq_number ) + 1 ;
seq_no = ntohl ( tcp - > ack_number ) ;
}
{
fprintf ( tty , " Sending TCP ack \n " ) ;
2014-05-16 07:45:14 +04:00
int my_tx = next_tx_buf ( ) ;
2014-05-15 10:24:43 +04:00
uint8_t payload [ ] = { 0 } ;
2014-05-16 07:45:14 +04:00
size_t packet_size = write_tcp_packet ( rtl_tx_buffer [ my_tx ] , payload , 0 , ( TCP_FLAGS_ACK | DATA_OFFSET_5 ) ) ;
2014-05-15 10:24:43 +04:00
2014-05-16 07:45:14 +04:00
outportl ( rtl_iobase + RTL_PORT_TXBUF + 4 * my_tx , rtl_tx_phys [ my_tx ] ) ;
outportl ( rtl_iobase + RTL_PORT_TXSTAT + 4 * my_tx , packet_size ) ;
2014-05-15 10:24:43 +04:00
}
2014-06-08 00:25:28 +04:00
irc_socket = make_pipe ( 4096 ) ;
vfs_mount ( " /dev/net_irc " , irc_socket ) ;
2014-05-15 10:24:43 +04:00
2014-08-06 09:33:56 +04:00
create_kernel_tasklet ( rtl_ircd , " [ircd] " , tty ) ;
2014-05-15 10:24:43 +04:00
while ( 1 ) {
sleep_on ( rx_wait ) ;
2014-05-07 09:14:05 +04:00
2014-05-15 10:24:43 +04:00
{
struct ethernet_packet * eth = ( struct ethernet_packet * ) last_packet ;
struct ipv4_packet * ipv4 = ( struct ipv4_packet * ) eth - > payload ;
struct tcp_header * tcp = ( struct tcp_header * ) ipv4 - > payload ;
uint32_t l__ = ntohs ( ipv4 - > length ) - sizeof ( struct tcp_header ) - sizeof ( struct ipv4_packet ) ;
2014-05-18 05:50:52 +04:00
if ( ntohs ( tcp - > flags ) & TCP_FLAGS_ACK ) {
seq_no = ntohl ( tcp - > ack_number ) ;
}
2014-05-15 10:24:43 +04:00
ack_no = ntohl ( tcp - > seq_number ) + l__ ;
2014-05-18 05:50:52 +04:00
if ( l__ < 0xFFFF ) {
2014-06-08 00:25:28 +04:00
/* Look up source port in table of sockets */
2014-05-19 07:23:21 +04:00
if ( ntohs ( tcp - > source_port ) = = 6667 ) {
2014-06-08 00:25:28 +04:00
write_fs ( irc_socket , 0 , l__ , tcp - > payload ) ;
2014-05-19 07:23:21 +04:00
} else {
write_fs ( tty , 0 , l__ , tcp - > payload ) ;
}
2014-05-18 05:50:52 +04:00
}
2014-05-15 10:24:43 +04:00
}
{
2014-05-16 07:45:14 +04:00
int my_tx = next_tx_buf ( ) ;
2014-05-15 10:24:43 +04:00
uint8_t payload [ ] = { 0 } ;
2014-05-16 07:45:14 +04:00
size_t packet_size = write_tcp_packet ( rtl_tx_buffer [ my_tx ] , payload , 0 , ( TCP_FLAGS_ACK | DATA_OFFSET_5 ) ) ;
2014-05-15 10:24:43 +04:00
2014-05-16 07:45:14 +04:00
outportl ( rtl_iobase + RTL_PORT_TXBUF + 4 * my_tx , rtl_tx_phys [ my_tx ] ) ;
outportl ( rtl_iobase + RTL_PORT_TXSTAT + 4 * my_tx , packet_size ) ;
2014-05-15 10:24:43 +04:00
}
}
}
2014-05-20 06:39:04 +04:00
static int irc_readline ( fs_node_t * dev , char * linebuf , int max ) {
int read = 0 ;
tty_set_unbuffered ( dev ) ;
while ( read < max ) {
uint8_t buf [ 1 ] ;
int r = read_fs ( dev , 0 , 1 , ( unsigned char * ) buf ) ;
if ( ! r ) {
debug_print ( WARNING , " Read nothing? " ) ;
continue ;
}
spin_lock ( & irc_tty_lock ) ;
linebuf [ read ] = buf [ 0 ] ;
if ( buf [ 0 ] = = ' \n ' ) {
linebuf [ read ] = 0 ;
spin_unlock ( & irc_tty_lock ) ;
break ;
} else if ( buf [ 0 ] = = 0x08 ) {
if ( read > 0 ) {
fprintf ( dev , " \010 \010 " ) ;
read - - ;
linebuf [ read ] = 0 ;
}
} else if ( buf [ 0 ] < ' ' ) {
switch ( buf [ 0 ] ) {
case 0x0C : /* ^L */
/* Should reset display here */
spin_unlock ( & irc_tty_lock ) ;
break ;
default :
/* do nothing */
spin_unlock ( & irc_tty_lock ) ;
break ;
}
} else {
fprintf ( dev , " %c " , buf [ 0 ] ) ;
read + = r ;
}
spin_unlock ( & irc_tty_lock ) ;
}
tty_set_buffered ( dev ) ;
return read ;
}
2014-05-17 23:26:14 +04:00
DEFINE_SHELL_FUNCTION ( irc_test , " irc test " ) {
2014-05-16 07:45:14 +04:00
char * payloads [ ] = {
" NICK toarutest \r \n USER toaru 0 * :Toaru Test \r \n JOIN #levchins \r \n \0 \0 \0 " ,
" PRIVMSG #levchins :99 bottles of beer on the wall \r \n \0 \0 " ,
" PRIVMSG #levchins :99 bottles of beer \r \n \0 \0 " ,
" PRIVMSG #levchins :Take one down \r \n \0 \0 " ,
" PRIVMSG #levchins :pass it around \r \n \0 \0 " ,
" PRIVMSG #levchins :98 bottles of beer on the wall \r \n \0 \0 " ,
" PART #levchins :Thank you, and good night! \r \n \0 \0 " ,
" QUIT \r \n \0 \0 " ,
} ;
for ( unsigned int i = 0 ; i < sizeof ( payloads ) / sizeof ( uint8_t * ) ; + + i ) {
int my_tx = next_tx_buf ( ) ;
int l = strlen ( payloads [ i ] ) ;
size_t packet_size = write_tcp_packet ( rtl_tx_buffer [ my_tx ] , ( uint8_t * ) payloads [ i ] , l , ( TCP_FLAGS_ACK | DATA_OFFSET_5 ) ) ;
outportl ( rtl_iobase + RTL_PORT_TXBUF + 4 * my_tx , rtl_tx_phys [ my_tx ] ) ;
outportl ( rtl_iobase + RTL_PORT_TXSTAT + 4 * my_tx , packet_size ) ;
unsigned long s , ss ;
relative_time ( 0 , 500 , & s , & ss ) ;
sleep_until ( ( process_t * ) current_process , s , ss ) ;
switch_task ( 0 ) ;
2014-05-15 10:24:43 +04:00
}
2014-05-16 07:45:14 +04:00
return 0 ;
2014-05-15 10:24:43 +04:00
}
2014-05-17 23:26:14 +04:00
2014-05-18 02:08:50 +04:00
DEFINE_SHELL_FUNCTION ( irc_init , " irc connector " ) {
if ( argc < 2 ) {
fprintf ( tty , " Specify a username \n " ) ;
return 1 ;
}
2014-05-17 23:26:14 +04:00
2014-05-19 07:23:21 +04:00
memcpy ( irc_nick , argv [ 1 ] , strlen ( argv [ 1 ] ) + 1 ) ;
2014-05-17 23:26:14 +04:00
2014-05-19 07:23:21 +04:00
sprintf ( irc_payload , " NICK %s \r \n USER %s * 0 :%s \r \n " , irc_nick , irc_nick , irc_nick ) ;
2014-05-18 02:08:50 +04:00
irc_send ( irc_payload ) ;
2014-05-17 23:26:14 +04:00
2014-05-18 02:08:50 +04:00
return 0 ;
}
DEFINE_SHELL_FUNCTION ( irc_join , " irc channel tool " ) {
if ( argc < 2 ) {
fprintf ( tty , " Specify a channel. \n " ) ;
return 1 ;
}
char * channel = argv [ 1 ] ;
sprintf ( irc_payload , " JOIN %s \r \n " , channel ) ;
irc_send ( irc_payload ) ;
2014-05-23 23:44:14 +04:00
sprintf ( irc_prompt , " \r [%s] " , channel ) ;
2014-05-19 07:23:21 +04:00
2014-05-18 02:08:50 +04:00
while ( 1 ) {
2014-05-19 07:23:21 +04:00
fprintf ( tty , irc_prompt ) ;
2014-05-20 06:39:04 +04:00
int c = irc_readline ( tty , irc_input , 400 ) ;
spin_lock ( & irc_tty_lock ) ;
2014-05-19 07:23:21 +04:00
irc_input [ c ] = ' \0 ' ;
2014-05-18 02:08:50 +04:00
2014-05-19 07:23:21 +04:00
if ( startswith ( irc_input , " /part " ) ) {
2014-05-20 06:39:04 +04:00
fprintf ( tty , " \n " ) ;
2014-05-18 02:08:50 +04:00
sprintf ( irc_payload , " PART %s \r \n " , channel ) ;
irc_send ( irc_payload ) ;
2014-05-20 06:39:04 +04:00
spin_unlock ( & irc_tty_lock ) ;
2014-05-18 02:08:50 +04:00
break ;
}
2014-05-19 07:23:21 +04:00
if ( startswith ( irc_input , " /me " ) ) {
char * m = strstr ( irc_input , " " ) ;
m + + ;
2014-05-20 06:39:04 +04:00
uint16_t hr , min , sec ;
get_time ( & hr , & min , & sec ) ;
fprintf ( tty , " \r %2d:%2d:%2d * \033 [35m%s \033 [0m: \033 [34m%s \033 [0m %s \n \033 [K " , hr , min , sec , irc_nick , channel , m ) ;
2014-05-19 07:23:21 +04:00
sprintf ( irc_payload , " PRIVMSG %s : \1 ACTION %s \1 \r \n " , channel , m ) ;
irc_send ( irc_payload ) ;
} else {
2014-05-20 06:39:04 +04:00
uint16_t hr , min , sec ;
get_time ( & hr , & min , & sec ) ;
fprintf ( tty , " \r %2d:%2d:%2d \033 [90m< \033 [35m%s \033 [0m: \033 [34m%s \033 [90m> \033 [0m %s \n \033 [K " , hr , min , sec , irc_nick , channel , irc_input ) ;
2014-05-19 07:23:21 +04:00
sprintf ( irc_payload , " PRIVMSG %s :%s \r \n " , channel , irc_input ) ;
irc_send ( irc_payload ) ;
}
memset ( irc_input , 0x00 , sizeof ( irc_input ) ) ;
2014-05-20 06:39:04 +04:00
spin_unlock ( & irc_tty_lock ) ;
2014-05-17 23:26:14 +04:00
}
2014-05-19 07:23:21 +04:00
memset ( irc_prompt , 0x00 , sizeof ( irc_prompt ) ) ;
memset ( irc_input , 0x00 , sizeof ( irc_input ) ) ;
2014-05-17 23:26:14 +04:00
return 0 ;
}
2014-05-07 09:14:05 +04:00
DEFINE_SHELL_FUNCTION ( rtl , " rtl8139 experiments " ) {
if ( rtl_device_pci ) {
fprintf ( tty , " Located an RTL 8139: 0x%x \n " , rtl_device_pci ) ;
uint16_t command_reg = pci_read_field ( rtl_device_pci , PCI_COMMAND , 4 ) ;
fprintf ( tty , " COMMAND register before: 0x%4x \n " , command_reg ) ;
if ( command_reg & ( 1 < < 2 ) ) {
fprintf ( tty , " Bus mastering already enabled. \n " ) ;
} else {
command_reg | = ( 1 < < 2 ) ; /* bit 2 */
fprintf ( tty , " COMMAND register after: 0x%4x \n " , command_reg ) ;
pci_write_field ( rtl_device_pci , PCI_COMMAND , 4 , command_reg ) ;
command_reg = pci_read_field ( rtl_device_pci , PCI_COMMAND , 4 ) ;
fprintf ( tty , " COMMAND register after: 0x%4x \n " , command_reg ) ;
}
rtl_irq = pci_read_field ( rtl_device_pci , PCI_INTERRUPT_LINE , 1 ) ;
fprintf ( tty , " Interrupt Line: %x \n " , rtl_irq ) ;
irq_install_handler ( rtl_irq , rtl_irq_handler ) ;
uint32_t rtl_bar0 = pci_read_field ( rtl_device_pci , PCI_BAR0 , 4 ) ;
uint32_t rtl_bar1 = pci_read_field ( rtl_device_pci , PCI_BAR1 , 4 ) ;
fprintf ( tty , " BAR0: 0x%8x \n " , rtl_bar0 ) ;
fprintf ( tty , " BAR1: 0x%8x \n " , rtl_bar1 ) ;
rtl_iobase = 0x00000000 ;
if ( rtl_bar0 & 0x00000001 ) {
rtl_iobase = rtl_bar0 & 0xFFFFFFFC ;
} else {
fprintf ( tty , " This doesn't seem right! RTL8139 should be using an I/O BAR; this looks like a memory bar. " ) ;
}
fprintf ( tty , " RTL iobase: 0x%x \n " , rtl_iobase ) ;
2014-05-08 10:08:34 +04:00
rx_wait = list_create ( ) ;
2014-05-07 09:14:05 +04:00
fprintf ( tty , " Determining mac address... \n " ) ;
2014-05-14 11:13:36 +04:00
for ( int i = 0 ; i < 6 ; + + i ) {
mac [ i ] = inports ( rtl_iobase + RTL_PORT_MAC + i ) ;
}
2014-05-07 09:14:05 +04:00
fprintf ( tty , " %2x:%2x:%2x:%2x:%2x:%2x \n " , mac [ 0 ] , mac [ 1 ] , mac [ 2 ] , mac [ 3 ] , mac [ 4 ] , mac [ 5 ] ) ;
fprintf ( tty , " Enabling RTL8139. \n " ) ;
outportb ( rtl_iobase + RTL_PORT_CONFIG , 0x0 ) ;
fprintf ( tty , " Resetting RTL8139. \n " ) ;
outportb ( rtl_iobase + RTL_PORT_CMD , 0x10 ) ;
while ( ( inportb ( rtl_iobase + 0x37 ) & 0x10 ) ! = 0 ) { }
fprintf ( tty , " Done resetting RTL8139. \n " ) ;
2014-05-07 11:17:31 +04:00
for ( int i = 0 ; i < 5 ; + + i ) {
2014-05-07 09:14:05 +04:00
rtl_tx_buffer [ i ] = ( void * ) kvmalloc_p ( 0x1000 , & rtl_tx_phys [ i ] ) ;
for ( int j = 0 ; j < 60 ; + + j ) {
rtl_tx_buffer [ i ] [ j ] = 0xF0 ;
}
}
2014-05-07 09:38:21 +04:00
rtl_rx_buffer = ( uint8_t * ) kvmalloc_p ( 0x3000 , & rtl_rx_phys ) ;
2014-05-07 09:14:05 +04:00
memset ( rtl_rx_buffer , 0x00 , 0x3000 ) ;
fprintf ( tty , " Buffers: \n " ) ;
2014-05-07 09:38:21 +04:00
fprintf ( tty , " rx 0x%x [phys 0x%x and 0x%x and 0x%x] \n " , rtl_rx_buffer , rtl_rx_phys , map_to_physical ( ( uintptr_t ) rtl_rx_buffer + 0x1000 ) , map_to_physical ( ( uintptr_t ) rtl_rx_buffer + 0x2000 ) ) ;
2014-05-07 09:14:05 +04:00
2014-05-07 11:17:31 +04:00
for ( int i = 0 ; i < 5 ; + + i ) {
2014-05-07 09:38:21 +04:00
fprintf ( tty , " tx 0x%x [phys 0x%x] \n " , rtl_tx_buffer [ i ] , rtl_tx_phys [ i ] ) ;
2014-05-07 09:14:05 +04:00
}
fprintf ( tty , " Initializing receive buffer. \n " ) ;
outportl ( rtl_iobase + RTL_PORT_RBSTART , rtl_rx_phys ) ;
fprintf ( tty , " Enabling IRQs. \n " ) ;
outports ( rtl_iobase + RTL_PORT_IMR ,
0x8000 | /* PCI error */
0x4000 | /* PCS timeout */
0x40 | /* Rx FIFO over */
0x20 | /* Rx underrun */
0x10 | /* Rx overflow */
0x08 | /* Tx error */
2014-05-07 10:29:17 +04:00
0x04 | /* Tx okay */
2014-05-07 09:14:05 +04:00
0x02 | /* Rx error */
0x01 /* Rx okay */
) ; /* TOK, ROK */
fprintf ( tty , " Configuring transmit \n " ) ;
outportl ( rtl_iobase + RTL_PORT_TCR ,
0
) ;
fprintf ( tty , " Configuring receive buffer. \n " ) ;
outportl ( rtl_iobase + RTL_PORT_RCR ,
( 0 ) | /* 8K receive */
0x08 | /* broadcast */
0x01 /* all physical */
) ;
fprintf ( tty , " Enabling receive and transmit. \n " ) ;
outportb ( rtl_iobase + RTL_PORT_CMD , 0x08 | 0x04 ) ;
fprintf ( tty , " Resetting rx stats \n " ) ;
outportl ( rtl_iobase + RTL_PORT_RXMISS , 0 ) ;
2014-05-14 09:09:15 +04:00
{
fprintf ( tty , " Sending DHCP discover \n " ) ;
2014-05-14 12:23:12 +04:00
size_t packet_size = write_dhcp_packet ( rtl_tx_buffer [ next_tx ] ) ;
outportl ( rtl_iobase + RTL_PORT_TXBUF + 4 * next_tx , rtl_tx_phys [ next_tx ] ) ;
outportl ( rtl_iobase + RTL_PORT_TXSTAT + 4 * next_tx , packet_size ) ;
2014-05-07 09:14:05 +04:00
2014-05-14 12:23:12 +04:00
next_tx + + ;
if ( next_tx = = 4 ) {
next_tx = 0 ;
}
2014-05-14 09:09:15 +04:00
}
2014-05-07 09:14:05 +04:00
2014-05-14 09:09:15 +04:00
sleep_on ( rx_wait ) ;
2014-05-07 09:14:05 +04:00
2014-05-09 06:29:23 +04:00
{
2014-05-14 09:09:15 +04:00
struct ethernet_packet * eth = ( struct ethernet_packet * ) last_packet ;
uint16_t eth_type = ntohs ( eth - > type ) ;
fprintf ( tty , " Ethernet II, Src: (%2x:%2x:%2x:%2x:%2x:%2x), Dst: (%2x:%2x:%2x:%2x:%2x:%2x) [type=%4x) \n " ,
eth - > source [ 0 ] , eth - > source [ 1 ] , eth - > source [ 2 ] ,
eth - > source [ 3 ] , eth - > source [ 4 ] , eth - > source [ 5 ] ,
eth - > destination [ 0 ] , eth - > destination [ 1 ] , eth - > destination [ 2 ] ,
eth - > destination [ 3 ] , eth - > destination [ 4 ] , eth - > destination [ 5 ] ,
eth_type ) ;
struct ipv4_packet * ipv4 = ( struct ipv4_packet * ) eth - > payload ;
2014-05-09 06:29:23 +04:00
uint32_t src_addr = ntohl ( ipv4 - > source ) ;
uint32_t dst_addr = ntohl ( ipv4 - > destination ) ;
uint16_t length = ntohs ( ipv4 - > length ) ;
2014-05-14 09:59:36 +04:00
char src_ip [ 16 ] ;
char dst_ip [ 16 ] ;
ip_ntoa ( src_addr , src_ip ) ;
ip_ntoa ( dst_addr , dst_ip ) ;
fprintf ( tty , " IP packet [%s → %s] length=%d bytes \n " ,
src_ip , dst_ip , length ) ;
2014-05-09 06:29:23 +04:00
2014-05-14 09:09:15 +04:00
struct udp_packet * udp = ( struct udp_packet * ) ipv4 - > payload ; ;
2014-05-09 06:29:23 +04:00
uint16_t src_port = ntohs ( udp - > source_port ) ;
uint16_t dst_port = ntohs ( udp - > destination_port ) ;
uint16_t udp_len = ntohs ( udp - > length ) ;
fprintf ( tty , " UDP [%d → %d] length=%d bytes \n " ,
src_port , dst_port , udp_len ) ;
2014-05-14 09:09:15 +04:00
struct dhcp_packet * dhcp = ( struct dhcp_packet * ) udp - > payload ;
2014-05-09 06:29:23 +04:00
uint32_t yiaddr = ntohl ( dhcp - > yiaddr ) ;
2014-05-14 09:59:36 +04:00
char yiaddr_ip [ 16 ] ;
ip_ntoa ( yiaddr , yiaddr_ip ) ;
fprintf ( tty , " DHCP Offer: %s \n " , yiaddr_ip ) ;
2014-05-09 06:29:23 +04:00
}
2014-05-07 09:14:05 +04:00
2014-05-15 10:24:43 +04:00
fprintf ( tty , " Card is configured, going to start worker thread now. \n " ) ;
2014-05-07 10:29:17 +04:00
2014-05-16 07:45:14 +04:00
create_kernel_tasklet ( rtl_netd , " [netd] " , tty ) ;
2014-05-15 03:34:05 +04:00
2014-05-07 09:14:05 +04:00
} else {
return - 1 ;
}
return 0 ;
}
static int init ( void ) {
BIND_SHELL_FUNCTION ( rtl ) ;
2014-05-17 23:26:14 +04:00
BIND_SHELL_FUNCTION ( irc_test ) ;
2014-05-18 02:08:50 +04:00
BIND_SHELL_FUNCTION ( irc_init ) ;
BIND_SHELL_FUNCTION ( irc_join ) ;
2014-05-07 09:14:05 +04:00
pci_scan ( & find_rtl , - 1 , & rtl_device_pci ) ;
if ( ! rtl_device_pci ) {
debug_print ( ERROR , " No RTL 8139 found? " ) ;
return 1 ;
}
return 0 ;
}
static int fini ( void ) {
return 0 ;
}
MODULE_DEF ( rtl , init , fini ) ;
MODULE_DEPENDS ( debugshell ) ;
2014-05-18 10:16:30 +04:00
MODULE_DEPENDS ( net ) ;