summaryrefslogtreecommitdiff
path: root/src/drivers/net/rtl8139.c
blob: 297f89dc8bec0c8179d168116fd01379aae6ec25 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#include "rtl8139.h"

#include "string.h"
#include "stdio.h"

#define DEBUG

/*
Offset (from IO base) 	Size 	Name
0x08 	8 	MAR0-7
0x30 	4 	RBSTART
0x37 	1 	CMD
0x3C 	2 	IMR
0x3E 	2 	ISR 
*/

static rtl8139_vtable_t const rtl8139_vtable = {
	{
	rtl8139_activate,
	rtl8139_deactivate,
	rtl8139_deinit,
	rtl8139_print_info
	}
};

// registers
#define REG_MAC0 0x00
#define REG_CMD 0x37
#define REG_TCR 0x40
#define REG_RCR 0x44

// commands for REG_CMD register
#define CMD_RESET 0x10
#define CMD_RECEIVER_ENABLE 0x08
#define CMD_TRANSMITTER_ENABLE 0x04

#define TCR_MODEL_VERSION_AM 0x7C000000
#define TCR_MODEL_VERSION_BM 0x00C00000

#define	TCR_MODEL_VERSION_RTL8139 0x60000000
#define	TCR_MODEL_VERSION_RTL8139A 0x70000000
#define	TCR_MODEL_VERSION_RTL8139B 0x78000000
#define	TCR_MODEL_VERSION_RTL8130 0x78000000
#define	TCR_MODEL_VERSION_RTL8139AG 0x74000000
#define	TCR_MODEL_VERSION_RTL8139C 0x74000000
#define	TCR_MODEL_VERSION_RTL8100 0x78800000
#define	TCR_MODEL_VERSION_RTL8100B 0x74400000
#define	TCR_MODEL_VERSION_RTL8139CP 0x74800000
#define	TCR_MODEL_VERSION_RTL8101 0x74C00000

#define TCR_IFG_STANDARD 0x03000000

/*
#define TCR_IFG_STANDARD        (3 << 24)
#define TCR_MXDMA_512           (5 << 8)
#define TCR_MXDMA_1024          (6 << 8)
#define TCR_MXDMA_2048          (7 << 8)

#define RCR_MXDMA_512           (5 << 8)
#define RCR_MXDMA_1024          (6 << 8)
#define RCR_MXDMA_UNLIMITED     (7 << 8)
#define RCR_ACCEPT_BROADCAST    (1 << 3)
#define RCR_ACCEPT_MULTICAST    (1 << 2)
#define RCR_ACCEPT_PHYS_MATCH   (1 << 1)
*/

void rtl8139_init( rtl8139_t *rtl8139, pci_device_descriptor_t *descriptor, interrupt_t *interrupt, void *context )
{
	memset( rtl8139, 0, sizeof( rtl8139_t ) );

	network_init( (network_t *)rtl8139, interrupt, context );

	puts( "Initializing driver for Realtek 8139 network card.." );

	for( int i = 0; i < NOF_MAC_REGISTERS; i++ ) {
		port8_init( &rtl8139->MAC_port[i], descriptor->port_base + REG_MAC0 + i );
	}
	port8_init( &rtl8139->CMD_port, descriptor->port_base + REG_CMD );
	port32_init( &rtl8139->TCR_port, descriptor->port_base + REG_TCR );
	port32_init( &rtl8139->RCR_port, descriptor->port_base + REG_RCR );

	// software reset, the CR_RESET bit remains high till the
	// reset is finished
	port8_write( &rtl8139->CMD_port, CMD_RESET );
	while( ( port8_read( &rtl8139->CMD_port ) & CMD_RESET ) == CMD_RESET );

	// get MAC
	for( int i = 0; i < NOF_MAC_REGISTERS; i++ ) {
		rtl8139->base.mac_address.byte[i] = port8_read( &rtl8139->MAC_port[i] );
	}

	// enable receiver and transmitter early
	port8_write( &rtl8139->CMD_port, CMD_RECEIVER_ENABLE | CMD_TRANSMITTER_ENABLE );

	// get model
	uint32_t model_id = port32_read( &rtl8139->TCR_port ) & ( TCR_MODEL_VERSION_AM | TCR_MODEL_VERSION_BM );
	switch( model_id ) {

		case TCR_MODEL_VERSION_RTL8139:
			rtl8139->model = "RTL8139";
			break;

		case TCR_MODEL_VERSION_RTL8139A:
			rtl8139->model = "RTL8139A";
			break;

		//case TCR_MODEL_VERSION_RTL8139B:
		case TCR_MODEL_VERSION_RTL8130:
			rtl8139->model = "RTL8130/RTL8130B";
			break;

		// case TCR_MODEL_VERSION_RTL8139AG:
		case TCR_MODEL_VERSION_RTL8139C:
			rtl8139->model = "RTL8139A-G/RTL8139C";
			break;

		case TCR_MODEL_VERSION_RTL8100:
			rtl8139->model = "RTL8100";
			break;

		case TCR_MODEL_VERSION_RTL8100B:
			rtl8139->model = "RTL8100B";
			break;

		case TCR_MODEL_VERSION_RTL8139CP:
			rtl8139->model = "RTL8139C+";
			break;

		case TCR_MODEL_VERSION_RTL8101:
			rtl8139->model = "RTL8101";
			break;

		default:
			rtl8139->model = NULL;
			break;
	}

/* TODO:
	port32_write( &rtl8139->TCR_port, TCR_IFG_STANDARD );

	port32_write( &rtl8139->RCR_port, );

	TCR RCR

    DEBUG_MSG("Inititalisiere RCR/TCR");
    write_register_dword(netcard, REG_RECEIVE_CONFIGURATION,
        RCR_MXDMA_UNLIMITED | RCR_ACCEPT_BROADCAST | RCR_ACCEPT_PHYS_MATCH);

    // DMA burst, 2k is max, what are other operating systems doing?
    write_register_dword(netcard, REG_TRANSMIT_CONFIGURATION,
        TCR_IFG_STANDARD | TCR_MXDMA_2048);

*/

#ifdef DEBUG
	char buf[20];
	char buf2[30];
	snprintf( buf2, 30, "unknown submodel 0x%X", model_id );
	network_mac_to_string( rtl8139->base.mac_address, buf, 20 );
	printf( "rtl8139 NIC type %s\n  at I/O base 0x%X, interrupt 0x%X, MAC: %s\n",
		( rtl8139->model != NULL ) ? rtl8139->model : buf2,
		descriptor->port_base, descriptor->interrupt, buf );
#endif

	interrupt_handler_init( &rtl8139->interrupt_handler, IRQ_BASE + descriptor->interrupt, interrupt, rtl8139_handle_interrupt, rtl8139 );
	interrupts_register_interrupt_handler( rtl8139->interrupt_handler );

	((driver_t *)rtl8139)->vtable = (driver_vtable_t *)&rtl8139_vtable;
}

void rtl8139_activate( void *obj )
{
	puts( "Activating driver for Realtek 8139 network card.." );

	rtl8139_t *rtl8139 = obj;
}

void rtl8139_deactivate( void *obj )
{
	puts( "Dectivating driver for Realtek 8139 network card.." );

	rtl8139_t *rtl8139 = obj;
}

void rtl8139_deinit( void *obj )
{
	// nothing to do
}

uint32_t rtl8139_handle_interrupt( interrupt_handler_t *handler, uint32_t esp )
{
	rtl8139_t *rtl8139 = (rtl8139_t *)handler->driver;

#ifdef DEBUG
	printf( "RTL INTERRUPT\n" );
#endif

	return esp;
}

void rtl8139_print_info( void *obj )
{
	puts( "Realtek 8139 network card driver" );
}