Max OS 0.3
Loading...
Searching...
No Matches
intel_i217.cpp
Go to the documentation of this file.
1
10
11using namespace MaxOS;
12using namespace MaxOS::common;
13using namespace MaxOS::drivers;
14using namespace MaxOS::drivers::ethernet;
15using namespace MaxOS::hardwarecommunication;
16using namespace memory;
17
23
24// Buffer Sizes
25#define buffer8192 ((2 << 16) | (1 << 25))
26
27
34 : InterruptHandler(0x20 + device_descriptor->interrupt) {
35
36 //Set the registers
37 control_register = 0x0000;
38 status_register = 0x0008;
39 eprom_register = 0x0014;
40 control_ext_register = 0x0018;
41 interrupt_mask_register = 0x00D0;
42
43 receive_control_register = 0x0100;
44 receive_descriptor_low_register = 0x2800;
45 receive_descriptor_high_register = 0x2804;
46 receive_descriptor_length_register = 0x2808;
47 receive_descriptor_head_register = 0x2810;
48 receive_descriptor_tail_register = 0x2818;
49
50 send_control_register = 0x0400;
51 send_descriptor_low_register = 0x3800;
52 send_descriptor_high_register = 0x3804;
53 send_descriptor_length_register = 0x3808;
54 send_descriptor_head_register = 0x3810;
55 send_descriptor_tail_register = 0x3818;
56
57 // Get BAR0 type, io_base address and MMIO base address
58 bar_type = 1; // deviceDescriptor -> has_memory_base ? 0 : 1; @todo Fix memory mapping from PCI as it is unable to get MAC from memory
59 port_base = device_descriptor->port_base;
60 //TODO: memBase = deviceDescriptor -> memory_base;
61
62 init_done = false;
63 active = false;
64
65 // Clear eprom
66 eprom_present = detect_ee_prom();
67
68
69 if (read_mac_address()) {
70 own_mac = create_media_access_control_address(mac_address[0], mac_address[1], mac_address[2], mac_address[3],
71 mac_address[4], mac_address[5]);
72
73 } else {
74 ASSERT(false, "ERROR, INIT FAILED, MAC ADDRESS NOT FOUND");
75 }
76
77 for (int i = 0; i < 0x80; i++) //Loop through all the registers
78 write(0x5200 + i * 4, 0); //Clear the receive descriptor array
79
80
81
82
83}
84
85IntelI217::~IntelI217() = default;
86
87
88void IntelI217::write(uint16_t address, uint32_t data) const {
89
90 //Note: These Ports/MemIO cant be init in the constructor like they normally would as it depends on wether the device is using IO or MemIO, and checking that in every function would be messy
91
92 if (bar_type == 0) { // If the base address register is memory mapped
93
94 MemIO32Bit data_mem(mem_base + address); // Create a 32-bit memory class at the address
95 data_mem.write(data); // write the data to the memory address
96
97 } else {
98
99 Port32Bit command_port(port_base); // Create a 32 bit port at the address
100 Port32Bit data_port(port_base + 4); // Create a 32 bit port at the address + 4
101
102 command_port.write(address); // write the address to the command port
103 data_port.write(data); // write the data to the data port
104
105
106 }
107
108}
109
110uint32_t IntelI217::read(uint16_t address) const {
111
112 //Note: These Ports/MemIO cant be init in the constructor like they normally would as it depends on wether the device is using IO or MemIO, and checking that in every function would be messy
113 if (bar_type == 0) { // If the base address register is memory mapped
114
115 MemIO32Bit data_mem(mem_base + address); // Create a 32-bit memory class at the address
116 return data_mem.read(); // read the data from the memory address
117
118 } else {
119
120 Port32Bit command_port(port_base); // Create a 32 bit port at the address
121 Port32Bit data_port(port_base + 4); // Create a 32 bit port at the address + 4
122
123 command_port.write(address); // write the address to the command port
124 return data_port.read(); // read the data from the data port
125
126 }
127
128}
129
130bool IntelI217::detect_ee_prom() {
131
132 uint32_t val = 0; // The value to be returned
133 write(eprom_register, 0x1); // Set the register to read the EEProm
134
135 for (int i = 0; i < 1000; i++) //Loop 1000 times or until the EEProm is detected
136 {
137 val = read(0x0014); // read the register
138
139 if (val & 0x10)
140 return true;
141
142 }
143 return false;
144}
145
146uint32_t IntelI217::eeprom_read(uint8_t addr) {
147 uint16_t data = 0; // The data to be returned
148 uint32_t tmp = 0; // A temporary variable
149 if (eprom_present) // If the EEProm is detected
150 {
151 write(eprom_register, (1) | ((uint32_t) (addr) << 8)); // write the address to the register
152 while (!((tmp = read(eprom_register)) & (1 << 4))); // Wait for the EEProm to be ready
153 } else {
154 write(eprom_register, (1) | ((uint32_t) (addr) << 2)); // write the address to the register
155 while (!((tmp = read(eprom_register)) & (1 << 1))); // Wait for the EEProm to be ready
156 }
157 data = (uint16_t) ((tmp >> 16) & 0xFFFF); // Get the data from the register
158 return data; // Return the data
159}
160
161bool IntelI217::read_mac_address() {
162 if (eprom_present) //If the EPROM exists
163 {
165
166 temp = eeprom_read(
167 0); //read the m_first_memory_chunk 16 bits of the MAC address
168 mac_address[0] = temp &
169 0xff; //Get the m_first_memory_chunk 8 bits of the MAC address
170 mac_address[1] =
171 temp >> 8; //Get the second 8 bits of the MAC address
172
173 temp = eeprom_read(
174 1); //read the second 16 bits of the MAC address
175 mac_address[2] =
176 temp & 0xff; //Get the third 8 bits of the MAC address
177 mac_address[3] =
178 temp >> 8; //Get the fourth 8 bits of the MAC address
179
180 temp = eeprom_read(
181 2); //read the third 16 bits of the MAC address
182 mac_address[4] =
183 temp & 0xff; //Get the fifth 8 bits of the MAC address
184 mac_address[5] =
185 temp >> 8; //Get the sixth 8 bits of the MAC address
186 } else //If there is no eprom then read from memory
187 {
188
189
190 auto* mem_base_mac_8 = (uint8_t*) (mem_base +
191 0x5400); //Get the base address of the MAC address
192 auto* mem_base_mac_32 = (uint32_t*) (mem_base + 0x5400); //Get the base address of the MAC address
193
194 if (mem_base_mac_32[0] != 0) {
195 for (int i = 0; i < 6; i++) //Loop through the MAC address
196 mac_address[i] = mem_base_mac_8[i]; //Get the MAC address
197
198 } else return false;
199 }
200 return true;
201}
202
203void IntelI217::receive_init() {
204
205 uint8_t* ptr; //A pointer to the memory
206 receive_descriptor_t* descs; //A pointer to the receive descriptors
208 sizeof(receive_descriptor_t) * 32 + 16)); //Allocate memory for the receive descriptors
209 descs = (receive_descriptor_t*) ptr; //Set the pointer to the receive descriptors
210
211 for (int i = 0; i < 32; i++) {
212 receive_dsrctrs[i] = (receive_descriptor_t*) ((uint8_t*) descs + i * 16);
213 receive_dsrctrs[i]->buffer_address = (uint64_t) (uint8_t*) (MemoryManager::kmalloc(8192 + 16));
214 receive_dsrctrs[i]->status = 0;
215 }
216
217 //write the send descriptor list address to the register
218 write(send_descriptor_low_register, (uint32_t) ((uint64_t) ptr >> 32));
219 write(send_descriptor_high_register, (uint32_t) ((uint64_t) ptr & 0xFFFFFFFF));
220
221 //write the receive descriptor list address to the register
222 write(receive_descriptor_low_register, (uint64_t) ptr);
223 write(receive_descriptor_high_register, 0);
224
225 //Set the receive descriptor list length
226 write(receive_descriptor_length_register, 32 * 16);
227
228
229 write(receive_descriptor_head_register,
230 0); //Set the head to 0
231 write(receive_descriptor_tail_register,
232 32 - 1); //Set the tail to 32-1
233
234 current_receive_buffer = 0; //Set the current receive buffer to 0
235
236 write(receive_control_register, (1 << 1) // Receiver Enable
237 | (1 << 2) // Store Bad Packets
238 | (1 << 3) // Uni cast Promiscuous Enabled
239 | (1 << 4) // Multicast Promiscuous Enabled
240 | (0 << 6) // No Loop back
241 | (0 << 8) // Free Buffer Threshold is 1/2 of RDLEN
242 | (1 << 15) // Broadcast Accept Mode
243 | (1 << 26) // Strip Ethernet CRC
244 | buffer8192
245 );
246
247 delete ptr;
248
249}
250
251void IntelI217::send_init() {
252
253 uint8_t* ptr; //A pointer to the memory
254 send_descriptor_t* descs; //A pointer to the send descriptors
256 sizeof(send_descriptor_t) * 8 + 16)); //Allocate memory for the send descriptors
257 descs = (send_descriptor_t*) ptr; //Set the pointer to the send descriptors
258
259
260 for (int i = 0; i < 8; i++) {
261 send_dsrctrs[i] = (send_descriptor_t*) ((uint8_t*) descs + i * 16);
262 send_dsrctrs[i]->buffer_address = 0;
263 send_dsrctrs[i]->cmd = 0;
264 send_dsrctrs[i]->status = (1 << 0); // Descriptor Done
265 }
266
267 //write the send descriptor list address to the register
268 write(send_descriptor_high_register, (uint32_t) ((uint64_t) ptr >> 32));
269 write(send_descriptor_low_register, (uint32_t) ((uint64_t) ptr & 0xFFFFFFFF));
270
271
272 //now setup total length of descriptors
273 write(send_descriptor_length_register, 8 * 16);
274
275
276 //setup numbers
277 write(send_descriptor_head_register, 0);
278 write(send_descriptor_tail_register, 0);
279
280 current_send_buffer = 0;
281
282 write(send_control_register, (1 << 1) // Transmit Enable
283 | (1 << 3) // Pad Short Packets
284 | (15 << 4) // Collision Threshold
285 | (64 << 12) // Collision Distance
286 | (1 << 24) // Re-transmit on Late Collision
287 );
288
289
290 // In the case of I217 (id = 0x0410) and 82577LM (id = 0x10EA) packets will not be sent if the TCTRL is not configured using the following bits.
291 // write(sendControlRegister, 0b0110000000000111111000011111010);
292 //write(0x0410, 0x0060200A);
293
294 delete ptr;
295
296}
297
299
300
301 //Enable interrupts
302 write(interrupt_mask_register, 0x1F6DC); //Enable all interrupts
303 write(interrupt_mask_register, 0xff & ~4); //Enable all interrupts except link status change
304 read(0xc0); //Clear all interrupts
305
306 //while (!initDone); //Wait for the init to be done
307
308 //Initialise the send and receive descriptors
309 receive_init();
310 send_init();
311
312 active = true; // Set active to true
313
314}
315
317
318 write(interrupt_mask_register, 0x1); //Clear the interrupt or it will hang
319 uint32_t temp = read(0xc0); //read the interrupt status register
320
321 // if(temp & 0x04)
322 // m_driver_message_stream-> write("INTEL i217 START LINK");//initDone = true;
323 //
324 // if(temp & 0x10)
325 // m_driver_message_stream-> write("INTEL i217 GOOD THRESHOLD");
326
327 if (temp & 0x80) fetch_data_received();
328}
329
330void IntelI217::fetch_data_received() {
331
332
334
335 while ((receive_dsrctrs[current_receive_buffer]->status & 0x1)) {
336 auto* buffer = (uint8_t*) receive_dsrctrs[current_receive_buffer]->buffer_address;
337 uint16_t size = receive_dsrctrs[current_receive_buffer]->length;
338
339 if (size > 64) { // If the size is the size of ethernet 2 frame
340 size -= 4; // remove the checksum
341 }
342
343 fire_data_received(buffer, size); //Pass data to handler
344
345
346 receive_dsrctrs[current_receive_buffer]->status = 0;
347
348 old_cur = current_receive_buffer; //Save the current receive buffer
349 current_receive_buffer = (current_receive_buffer + 1) % 32; //Increment the current receive buffer
350
351 write(receive_descriptor_tail_register, old_cur); //write the old current receive buffer to the tail register
352 }
353
354}
355
357
358 while (!active);
359
360 //Put params into send buffer
361 send_dsrctrs[current_send_buffer]->buffer_address = (uint64_t) buffer;
362 send_dsrctrs[current_send_buffer]->length = size;
363
364 //Set the commands
365 send_dsrctrs[current_send_buffer]->cmd = (1 << 0) // End of Packet
366 | (1 << 1) // Insert FCS
367 | (1 << 3) // Report Status
368 ;
369
370 send_dsrctrs[current_send_buffer]->status = 0;
371
372 uint8_t old_cur = current_send_buffer; //Save the current send buffer
373 current_send_buffer = (current_send_buffer + 1) % 8; //Increment the current send buffer
374 write(send_descriptor_tail_register, current_send_buffer); //write the current send buffer to the tail register
375
376 //Wait for the packet to be sent
377 while (!(send_dsrctrs[old_cur]->status & 0xff));
378
379}
380
382 while (own_mac == 0);
383 return own_mac;
384
385}
386
390
394
396 return "Intel";
397}
398
400 return "E1000 (i217)";
401}
402
403
Stores the left, top, width and height of a rectangle.
Definition rectangle.h:22
virtual uint32_t reset()
Reset the driver.
Definition driver.cpp:48
virtual void deactivate()
Deactivate the driver.
Definition driver.cpp:32
static MediaAccessControlAddress create_media_access_control_address(uint8_t digit1, uint8_t digit2, uint8_t digit3, uint8_t digit4, uint8_t digit5, uint8_t digit6)
Create a Media Access Control Address.
Definition ethernet.cpp:165
void fire_data_received(uint8_t *buffer, uint32_t size)
Handle the recieved data.
Definition ethernet.cpp:122
void deactivate() final
Deactivate the driver.
void do_send(uint8_t *buffer, uint32_t size) final
(Device Side) send the data
uint64_t get_media_access_control_address() final
Get the MAC address.
void activate() final
Activate the driver.
uint32_t reset() final
Reset the driver.
string device_name() final
Get the device name of the driver.
string vendor_name() final
Get who created the device.
IntelI217(hardwarecommunication::PCIDeviceDescriptor *device_descriptor)
Constructs a new Intel I217 Ethernet driver. Gets the MAC address and clears the receive descriptor a...
void handle_interrupt() final
Handles an interrupt.
Handles a certain interrupt number.
Definition interrupts.h:30
Stores information about a PCI device.
Definition pci.h:54
Handles 32 bit ports.
Definition port.h:70
Handles 32 bit memory IO.
Definition memoryIO.h:62
static void * kmalloc(size_t size)
Allocates a block of memory in the KERNEL space.
#define buffer8192
Driver for the Intel I217 Ethernet Controller.
struct PACKED MaxOS::drivers::ethernet::SendDescriptor send_descriptor_t
Alias for SendDescriptor struct.
struct PACKED MaxOS::drivers::ethernet::ReceiveDescriptor receive_descriptor_t
Alias for ReceiveDescriptor struct.
#define ASSERT(condition, format,...)
If the specified condition is not met then the kernel will crash with the specified message.
Definition logger.h:100