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>
2015-07-31 01:48:31 +03:00
# include <mod/net.h>
2014-05-07 09:14:05 +04:00
2015-05-22 00:23:18 +03:00
/* XXX move this to ipv4? */
extern size_t print_dns_name ( fs_node_t * tty , struct dns_packet * dns , size_t offset ) ;
2014-05-07 09:14:05 +04:00
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
2015-04-04 22:19:10 +03:00
static list_t * net_queue = NULL ;
2015-05-21 11:28:14 +03:00
//static volatile uint8_t net_queue_lock = 0;
static spin_lock_t net_queue_lock = { 0 } ;
2015-04-04 22:19:10 +03:00
2014-05-07 09:14:05 +04:00
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 ;
2015-07-31 01:48:31 +03:00
static spin_lock_t irc_tty_lock = { 0 } ;
//static volatile uint8_t irc_tty_lock = 0;
//static struct netif rtl_netif;
static fs_node_t * _atty = NULL ;
static char irc_input [ 400 ] = { ' \0 ' } ;
static char irc_prompt [ 100 ] = { ' \0 ' } ;
static char irc_nick [ 32 ] = { ' \0 ' } ;
static char irc_payload [ 512 ] ;
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 ;
}
2014-05-18 10:16:30 +04:00
2015-05-21 11:28:14 +03:00
//static volatile uint8_t _lock;
static spin_lock_t _lock ;
2014-05-19 07:23:21 +04:00
static int next_tx_buf ( void ) {
int out ;
2015-05-21 11:28:14 +03:00
spin_lock ( _lock ) ;
2014-05-19 07:23:21 +04:00
out = next_tx ;
next_tx + + ;
if ( next_tx = = 4 ) {
next_tx = 0 ;
}
2015-05-21 11:28:14 +03:00
spin_unlock ( _lock ) ;
2014-05-19 07:23:21 +04:00
return out ;
}
static void irc_send ( char * payload ) {
2015-07-31 01:48:31 +03:00
// 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));
// seq_no += l;
2014-05-19 07:23:21 +04:00
2015-07-31 01:48:31 +03: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-19 07:23:21 +04:00
}
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 ;
}
2015-05-21 11:28:14 +03: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 ;
2015-05-21 11:28:14 +03:00
2014-05-19 07:23:21 +04:00
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 ) ;
2015-05-21 11:28:14 +03:00
spin_unlock ( irc_tty_lock ) ;
2014-05-20 06:39:04 +04:00
2014-05-19 07:23:21 +04:00
if ( ! e ) break ;
c = e + 2 ;
}
2014-06-08 00:25:28 +04:00
}
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 ) ;
}
2015-04-04 22:19:10 +03:00
}
2015-07-31 01:48:31 +03:00
void * rtl_dequeue ( ) {
2015-04-04 22:19:10 +03:00
while ( ! net_queue - > length ) {
sleep_on ( rx_wait ) ;
}
2015-07-31 01:48:31 +03:00
2015-05-21 11:28:14 +03:00
spin_lock ( net_queue_lock ) ;
2015-04-04 22:19:10 +03:00
node_t * n = list_dequeue ( net_queue ) ;
2015-07-31 01:48:31 +03:00
void * value = ( struct ethernet_packet * ) n - > value ;
2015-04-04 22:19:10 +03:00
free ( n ) ;
2015-05-21 11:28:14 +03:00
spin_unlock ( net_queue_lock ) ;
2015-04-04 22:19:10 +03:00
2015-07-31 01:48:31 +03:00
return value ;
2015-04-04 22:19:10 +03:00
}
2015-07-31 01:48:31 +03:00
void rtl_enqueue ( void * buffer ) {
2015-04-04 22:19:10 +03:00
/* XXX size? source? */
2015-05-21 11:28:14 +03:00
spin_lock ( net_queue_lock ) ;
2015-04-04 22:19:10 +03:00
list_insert ( net_queue , buffer ) ;
2015-05-21 11:28:14 +03:00
spin_unlock ( net_queue_lock ) ;
2015-04-04 22:19:10 +03:00
}
2015-07-31 02:46:08 +03:00
uint8_t * rtl_get_mac ( ) {
return mac ;
}
void rtl_send_packet ( uint8_t * payload , size_t payload_size ) {
int my_tx = next_tx_buf ( ) ;
memcpy ( rtl_tx_buffer [ my_tx ] , payload , payload_size ) ;
outportl ( rtl_iobase + RTL_PORT_TXBUF + 4 * my_tx , rtl_tx_phys [ my_tx ] ) ;
outportl ( rtl_iobase + RTL_PORT_TXSTAT + 4 * my_tx , payload_size ) ;
}
2015-07-31 02:54:07 +03:00
struct ethernet_packet * rtl_get_packet ( void ) {
return ( struct ethernet_packet * ) rtl_dequeue ( ) ;
2015-07-31 02:46:08 +03:00
}
2015-05-19 07:07:06 +03:00
static int rtl_irq_handler ( struct regs * r ) {
2014-05-07 09:14:05 +04:00
uint16_t status = inports ( rtl_iobase + RTL_PORT_ISR ) ;
2015-05-19 07:07:06 +03:00
if ( ! status ) {
return 0 ;
}
2014-05-07 09:14:05 +04:00
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 ] ) ;
2015-04-04 22:19:10 +03:00
last_packet = malloc ( rx_size ) ;
uintptr_t packet_end = ( uintptr_t ) buf_8 + rx_size ;
if ( packet_end > ( uintptr_t ) rtl_rx_buffer + 0x2000 ) {
size_t s = ( ( uintptr_t ) rtl_rx_buffer + 0x2000 ) - ( uintptr_t ) buf_8 ;
memcpy ( last_packet , buf_8 , s ) ;
memcpy ( ( void * ) ( ( uintptr_t ) last_packet + s ) , rtl_rx_buffer , rx_size - s ) ;
} else {
memcpy ( last_packet , buf_8 , rx_size ) ;
}
2015-07-31 01:48:31 +03:00
rtl_enqueue ( last_packet ) ;
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
}
2015-05-19 07:07:06 +03:00
return 1 ;
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 ;
2015-04-04 22:19:10 +03:00
#if 0
2014-05-15 10:24:43 +04:00
{
fprintf ( tty , " Sending DNS query... \n " ) ;
uint8_t queries [ ] = {
2015-05-19 07:07:06 +03:00
3 , ' i ' , ' r ' , ' c ' ,
8 , ' f ' , ' r ' , ' e ' , ' e ' , ' n ' , ' o ' , ' d ' , ' e ' ,
3 , ' n ' , ' e ' , ' t ' ,
2014-05-15 10:24:43 +04:00
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 ) ;
2015-05-19 07:07:06 +03:00
# endif
#if 0
2014-05-15 10:24:43 +04:00
{
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 ) ;
2015-04-04 22:19:10 +03:00
# endif
2015-07-31 01:48:31 +03:00
#if 0
2015-04-04 22:19:10 +03:00
seq_no = krand ( ) ;
2014-05-15 10:24:43 +04:00
{
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
2015-04-04 22:19:10 +03:00
seq_no + = 1 ;
ack_no = 0 ;
}
2014-05-15 10:24:43 +04:00
{
2015-04-04 22:19:10 +03:00
struct ethernet_packet * eth = net_receive ( ) ;
2014-05-15 10:24:43 +04:00
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 ;
2015-04-04 22:19:10 +03:00
if ( seq_no ! = ntohl ( tcp - > ack_number ) ) {
fprintf ( tty , " [eth] Expected ack number of 0x%x, got 0x%x \n " ,
seq_no ,
ntohl ( tcp - > ack_number ) ) ;
fprintf ( tty , " [eth] Bailing... \n " ) ;
return ;
}
2014-05-15 10:24:43 +04:00
ack_no = ntohl ( tcp - > seq_number ) + 1 ;
2015-04-04 22:19:10 +03:00
free ( eth ) ;
2014-05-15 10:24:43 +04:00
}
2015-04-04 22:19:10 +03:00
2014-05-15 10:24:43 +04:00
{
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
}
2015-04-04 22:19:10 +03:00
fprintf ( tty , " [eth] s-next=0x%x, r-next=0x%x \n " , seq_no , ack_no ) ;
2015-07-31 01:48:31 +03:00
# endif
2015-04-04 22:19:10 +03:00
#if 0
2014-05-15 10:24:43 +04:00
2015-04-04 22:19:10 +03:00
{
irc_send (
" GET / HTTP/1.1 \r \n "
" Host: forum.osdev.org \r \n "
" Cookie: phpbb3_9i66l_u=11616; phpbb3_9i66l_k=ebe8e4f9892d97ab; phpbb3_9i66l_sid=d99d2e26e2a503fdfbe13e9b794dae23 \r \n "
" \r \n " ) ;
}
# endif
2014-05-15 10:24:43 +04:00
2015-04-04 22:19:10 +03:00
irc_socket = make_pipe ( 4096 ) ;
vfs_mount ( " /dev/net_irc " , irc_socket ) ;
2014-05-15 10:24:43 +04:00
2015-04-04 22:19:10 +03:00
create_kernel_tasklet ( rtl_ircd , " [ircd] " , tty ) ;
2014-05-15 10:24:43 +04:00
2015-04-04 22:19:10 +03:00
_atty = tty ;
2014-05-15 10:24:43 +04:00
2015-07-31 01:48:31 +03:00
create_kernel_tasklet ( net_handler , " [eth] " , tty ) ;
2015-07-31 02:46:08 +03:00
init_netif_funcs ( rtl_get_mac , rtl_get_packet , rtl_send_packet ) ;
2014-05-15 10:24:43 +04:00
}
2015-04-04 22:19:10 +03:00
static int tty_readline ( fs_node_t * dev , char * linebuf , int max ) {
2014-05-20 06:39:04 +04:00
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 ;
}
2015-05-21 11:28:14 +03:00
spin_lock ( irc_tty_lock ) ;
2014-05-20 06:39:04 +04:00
linebuf [ read ] = buf [ 0 ] ;
if ( buf [ 0 ] = = ' \n ' ) {
linebuf [ read ] = 0 ;
2015-05-21 11:28:14 +03:00
spin_unlock ( irc_tty_lock ) ;
2014-05-20 06:39:04 +04:00
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 */
2015-05-21 11:28:14 +03:00
spin_unlock ( irc_tty_lock ) ;
2014-05-20 06:39:04 +04:00
break ;
default :
/* do nothing */
2015-05-21 11:28:14 +03:00
spin_unlock ( irc_tty_lock ) ;
2014-05-20 06:39:04 +04:00
break ;
}
} else {
fprintf ( dev , " %c " , buf [ 0 ] ) ;
read + = r ;
}
2015-05-21 11:28:14 +03:00
spin_unlock ( irc_tty_lock ) ;
2014-05-20 06:39:04 +04:00
}
tty_set_buffered ( dev ) ;
return read ;
}
2014-05-17 23:26:14 +04:00
DEFINE_SHELL_FUNCTION ( irc_test , " irc test " ) {
2015-07-31 01:48:31 +03:00
// char * payloads[] = {
// "NICK toarutest\r\nUSER toaru 0 * :Toaru Test\r\nJOIN #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));
// seq_no += l;
// 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-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 ) ;
2015-05-19 07:07:06 +03:00
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 ;
}
2015-05-22 00:23:18 +03:00
static char * log_channel = NULL ;
static uint32_t irc_write ( fs_node_t * node , uint32_t offset , uint32_t size , uint8_t * buffer ) {
sprintf ( irc_payload , " PRIVMSG %s :%s \r \n " , log_channel , buffer ) ;
irc_send ( irc_payload ) ;
return size ;
}
static fs_node_t _irc_log_fnode = {
. name = " irc_log " ,
. write = irc_write ,
} ;
DEFINE_SHELL_FUNCTION ( irc_log , " spew debug log to irc " ) {
if ( argc < 2 ) {
fprintf ( tty , " Need a channel to log to. \n " ) ;
return 1 ;
}
if ( ! strlen ( irc_nick ) ) {
fprintf ( tty , " Did you run irc_init? \n " ) ;
return 1 ;
}
fprintf ( tty , " May the gods have mercy on your soul. \n " ) ;
log_channel = strdup ( argv [ 1 ] ) ;
sprintf ( irc_payload , " JOIN %s \r \n " , log_channel ) ;
irc_send ( irc_payload ) ;
debug_file = & _irc_log_fnode ;
if ( argc > 2 ) {
debug_level = atoi ( argv [ 2 ] ) ;
}
return 0 ;
}
2014-05-18 02:08:50 +04:00
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 ) ;
2015-04-04 22:19:10 +03:00
int c = tty_readline ( tty , irc_input , 400 ) ;
2014-05-20 06:39:04 +04:00
2015-05-21 11:28:14 +03:00
spin_lock ( irc_tty_lock ) ;
2014-05-20 06:39:04 +04:00
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 ) ;
2015-05-21 11:28:14 +03: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 ) ) ;
2015-05-21 11:28:14 +03: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 ;
}
2015-04-04 22:19:10 +03:00
DEFINE_SHELL_FUNCTION ( http , " Open a prompt to send HTTP commands. " ) {
char tmp [ 100 ] ;
char * payload = malloc ( 10000 ) ;
while ( 1 ) {
fprintf ( tty , " http> " ) ;
2015-05-19 07:07:06 +03:00
tty_readline ( tty , tmp , 100 ) ;
2015-04-04 22:19:10 +03:00
if ( startswith ( tmp , " /quit " ) ) {
break ;
} else if ( startswith ( tmp , " get " ) ) {
char * m = strstr ( tmp , " " ) ;
m + + ;
sprintf ( payload ,
" GET %s HTTP/1.1 \r \n "
" Host: %s \r \n "
" Cookie: phpbb3_9i66l_u=11616; phpbb3_9i66l_k=ebe8e4f9892d97ab; phpbb3_9i66l_sid=d99d2e26e2a503fdfbe13e9b794dae23 \r \n "
" \r \n " , m , " forum.osdev.org " ) ;
irc_send ( payload ) ;
} else if ( startswith ( tmp , " post " ) ) {
/* /posting.php?mode=post&f=7 */
2015-05-21 11:28:14 +03:00
char * content =
2015-04-04 22:19:10 +03:00
" -----------------------------2611311029845263341299213952 \r \n "
" Content-Disposition: form-data; name= \" subject \" \r \n "
" \r \n "
" test post please ignore \r \n "
" -----------------------------2611311029845263341299213952 \r \n "
" Content-Disposition: form-data; name= \" addbbcode20 \" \r \n "
" \r \n "
" 100 \r \n "
" -----------------------------2611311029845263341299213952 \r \n "
" Content-Disposition: form-data; name= \" helpbox \" \r \n "
" \r \n "
" Tip: Styles can be applied quickly to selected text. \r \n "
" -----------------------------2611311029845263341299213952 \r \n "
" Content-Disposition: form-data; name= \" message \" \r \n "
" \r \n "
" test post please ignore \r \n "
" -----------------------------2611311029845263341299213952 \r \n "
" Content-Disposition: form-data; name= \" attach_sig \" \r \n "
" \r \n "
" on \r \n "
" -----------------------------2611311029845263341299213952 \r \n "
" Content-Disposition: form-data; name= \" post \" \r \n "
" \r \n "
" Submit \r \n "
" -----------------------------2611311029845263341299213952 \r \n "
" Content-Disposition: form-data; name= \" fileupload \" ; filename= \" \" \r \n "
" Content-Type: application/octet-stream \r \n "
" \r \n "
" \r \n "
" -----------------------------2611311029845263341299213952 \r \n "
" Content-Disposition: form-data; name= \" filecomment \" \r \n "
" \r \n "
" \r \n "
" -----------------------------2611311029845263341299213952 \r \n "
" Content-Disposition: form-data; name= \" lastclick \" \r \n "
" \r \n "
" 1424062664 \r \n "
" -----------------------------2611311029845263341299213952 \r \n "
" Content-Disposition: form-data; name= \" creation_time \" \r \n "
" \r \n "
" 1424062664 \r \n "
" -----------------------------2611311029845263341299213952 \r \n "
" Content-Disposition: form-data; name= \" form_token \" \r \n "
" \r \n "
" 3fdbc52648cb6f50b72df5bbd5e145bc333cfc0e \r \n "
" -----------------------------2611311029845263341299213952-- \r \n " ;
sprintf ( payload ,
" POST %s HTTP/1.1 \r \n "
" Host: %s \r \n "
" Cookie: phpbb3_9i66l_u=11616; phpbb3_9i66l_k=ebe8e4f9892d97ab; phpbb3_9i66l_sid=d99d2e26e2a503fdfbe13e9b794dae23 \r \n "
" Referer: http://forum.osdev.org/posting.php?mode=post&f=7 \r \n "
" User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:35.0) Gecko/20100101 Firefox/35.0 \r \n "
" Content-Type: multipart/form-data; boundary=---------------------------2611311029845263341299213952 \r \n "
" Content-Length: %d \r \n "
" \r \n "
" %s " ,
" /posting.php?mode=post&f=7&sid=d99d2e26e2a503fdfbe13e9b794dae23 " ,
" forum.osdev.org " ,
strlen ( content ) ,
content ) ;
irc_send ( payload ) ;
}
}
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 ) ;
2015-04-04 22:19:10 +03:00
net_queue = list_create ( ) ;
# if 1
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-09 06:29:23 +04:00
{
2015-07-31 01:48:31 +03:00
struct ethernet_packet * eth = ( struct ethernet_packet * ) rtl_dequeue ( ) ;
2014-05-14 09:09:15 +04:00
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 ) ;
2015-04-04 22:19:10 +03:00
free ( eth ) ;
2014-05-09 06:29:23 +04:00
}
2014-05-07 09:14:05 +04:00
2015-04-04 22:19:10 +03:00
# endif
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-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 ) ;
2015-05-22 00:23:18 +03:00
BIND_SHELL_FUNCTION ( irc_log ) ;
2015-04-04 22:19:10 +03:00
BIND_SHELL_FUNCTION ( http ) ;
2015-07-31 01:48:31 +03:00
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 ) ;