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>
2015-07-31 08:40:21 +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 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 ;
2015-05-21 11:28:14 +03:00
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 ;
}
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
}
2015-08-04 06:57:50 +03:00
#if 0
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 [ ] = {
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 ) ;
{
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-08-04 06:57:50 +03:00
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 ) ;
2014-05-15 10:24:43 +04:00
}
2015-08-04 06:57:50 +03:00
# endif
2014-05-15 10:24:43 +04:00
2015-08-19 04:29:40 +03:00
int init_rtl ( void ) {
2014-05-07 09:14:05 +04:00
if ( rtl_device_pci ) {
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Located an RTL 8139: 0x%x \n " , rtl_device_pci ) ;
2014-05-07 09:14:05 +04:00
uint16_t command_reg = pci_read_field ( rtl_device_pci , PCI_COMMAND , 4 ) ;
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " COMMAND register before: 0x%4x \n " , command_reg ) ;
2014-05-07 09:14:05 +04:00
if ( command_reg & ( 1 < < 2 ) ) {
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Bus mastering already enabled. \n " ) ;
2014-05-07 09:14:05 +04:00
} else {
command_reg | = ( 1 < < 2 ) ; /* bit 2 */
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " COMMAND register after: 0x%4x \n " , command_reg ) ;
2014-05-07 09:14:05 +04:00
pci_write_field ( rtl_device_pci , PCI_COMMAND , 4 , command_reg ) ;
command_reg = pci_read_field ( rtl_device_pci , PCI_COMMAND , 4 ) ;
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " COMMAND register after: 0x%4x \n " , command_reg ) ;
2014-05-07 09:14:05 +04:00
}
rtl_irq = pci_read_field ( rtl_device_pci , PCI_INTERRUPT_LINE , 1 ) ;
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Interrupt Line: %x \n " , rtl_irq ) ;
2014-05-07 09:14:05 +04:00
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 ) ;
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " BAR0: 0x%8x \n " , rtl_bar0 ) ;
debug_print ( NOTICE , " BAR1: 0x%8x \n " , rtl_bar1 ) ;
2014-05-07 09:14:05 +04:00
rtl_iobase = 0x00000000 ;
if ( rtl_bar0 & 0x00000001 ) {
rtl_iobase = rtl_bar0 & 0xFFFFFFFC ;
} else {
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " This doesn't seem right! RTL8139 should be using an I/O BAR; this looks like a memory bar. " ) ;
2014-05-07 09:14:05 +04:00
}
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " RTL iobase: 0x%x \n " , rtl_iobase ) ;
2014-05-07 09:14:05 +04:00
2014-05-08 10:08:34 +04:00
rx_wait = list_create ( ) ;
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " 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
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " %2x:%2x:%2x:%2x:%2x:%2x \n " , mac [ 0 ] , mac [ 1 ] , mac [ 2 ] , mac [ 3 ] , mac [ 4 ] , mac [ 5 ] ) ;
2014-05-07 09:14:05 +04:00
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Enabling RTL8139. \n " ) ;
2014-05-07 09:14:05 +04:00
outportb ( rtl_iobase + RTL_PORT_CONFIG , 0x0 ) ;
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Resetting RTL8139. \n " ) ;
2014-05-07 09:14:05 +04:00
outportb ( rtl_iobase + RTL_PORT_CMD , 0x10 ) ;
while ( ( inportb ( rtl_iobase + 0x37 ) & 0x10 ) ! = 0 ) { }
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Done resetting RTL8139. \n " ) ;
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: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 ) ;
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Buffers: \n " ) ;
debug_print ( NOTICE , " 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 ) {
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " tx 0x%x [phys 0x%x] \n " , rtl_tx_buffer [ i ] , rtl_tx_phys [ i ] ) ;
2014-05-07 09:14:05 +04:00
}
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Initializing receive buffer. \n " ) ;
2014-05-07 09:14:05 +04:00
outportl ( rtl_iobase + RTL_PORT_RBSTART , rtl_rx_phys ) ;
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Enabling IRQs. \n " ) ;
2014-05-07 09:14:05 +04:00
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 */
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Configuring transmit \n " ) ;
2014-05-07 09:14:05 +04:00
outportl ( rtl_iobase + RTL_PORT_TCR ,
0
) ;
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Configuring receive buffer. \n " ) ;
2014-05-07 09:14:05 +04:00
outportl ( rtl_iobase + RTL_PORT_RCR ,
( 0 ) | /* 8K receive */
0x08 | /* broadcast */
0x01 /* all physical */
) ;
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Enabling receive and transmit. \n " ) ;
2014-05-07 09:14:05 +04:00
outportb ( rtl_iobase + RTL_PORT_CMD , 0x08 | 0x04 ) ;
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Resetting rx stats \n " ) ;
2014-05-07 09:14:05 +04:00
outportl ( rtl_iobase + RTL_PORT_RXMISS , 0 ) ;
2015-04-04 22:19:10 +03:00
net_queue = list_create ( ) ;
2016-09-04 07:32:29 +03:00
debug_print ( NOTICE , " Initializing netif functions \n " ) ;
init_netif_funcs ( rtl_get_mac , rtl_get_packet , rtl_send_packet ) ;
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Card is configured, going to start worker thread now. \n " ) ;
create_kernel_tasklet ( net_handler , " [eth] " , NULL ) ;
2015-07-31 22:39:13 +03:00
2015-08-19 04:29:40 +03:00
debug_print ( NOTICE , " Back from starting the worker thread. \n " ) ;
2014-05-07 09:14:05 +04:00
} else {
return - 1 ;
}
return 0 ;
}
static int init ( void ) {
pci_scan ( & find_rtl , - 1 , & rtl_device_pci ) ;
if ( ! rtl_device_pci ) {
debug_print ( ERROR , " No RTL 8139 found? " ) ;
return 1 ;
}
2015-08-19 04:29:40 +03:00
init_rtl ( ) ;
2014-05-07 09:14:05 +04:00
return 0 ;
}
static int fini ( void ) {
return 0 ;
}
MODULE_DEF ( rtl , init , fini ) ;
2014-05-18 10:16:30 +04:00
MODULE_DEPENDS ( net ) ;