diff options
-rw-r--r-- | kernel/drivers/rtl8139.c | 95 | ||||
-rw-r--r-- | kernel/network/arp.c | 1 | ||||
-rw-r--r-- | kernel/network/ipv4.c | 6 | ||||
-rw-r--r-- | kernel/network/tcp.c | 18 | ||||
-rw-r--r-- | kernel/socket.c | 3 | ||||
-rw-r--r-- | kernel/socket.h | 1 |
6 files changed, 72 insertions, 52 deletions
diff --git a/kernel/drivers/rtl8139.c b/kernel/drivers/rtl8139.c index 0ed562e..4b53ef4 100644 --- a/kernel/drivers/rtl8139.c +++ b/kernel/drivers/rtl8139.c @@ -11,6 +11,8 @@ #define CMD 0x37 #define IMR 0x3C +#define RTL8139_RXBUFFER_SIZE (8192 + 16) + #define TSD0 0x10 // transmit status #define TSAD0 0x20 // transmit start address @@ -18,6 +20,7 @@ struct PCI_DEVICE rtl8139; u8 *device_buffer; u8 *send_buffers[4]; +int send_buffers_loop = 0; struct _INT_PACKET_HEADER { u8 ROK : 1; @@ -39,49 +42,63 @@ struct PACKET_HEADER { }; }; -u16 current_packet_read = 0; +u32 current_packet_read = 0; void handle_packet(void) { assert(sizeof(struct _INT_PACKET_HEADER) == sizeof(u16)); - u16 *buf = (u16 *)(device_buffer + current_packet_read); - struct PACKET_HEADER packet_header; - packet_header.raw = *buf; - assert(packet_header.data.ROK); - u16 packet_length = *(buf + 1); - - u8 packet_buffer[8192 + 16]; - if (current_packet_read + packet_length >= 8192 + 16) { - u32 first_run = ((u8 *)buf + (8192 + 16)) - device_buffer; - memcpy(packet_buffer, buf, first_run); - memcpy(packet_buffer, device_buffer, packet_length - first_run); - } else { - memcpy(packet_buffer, buf, packet_length); + for (int i = 0; 0 == (inb(rtl8139.gen.base_mem_io + 0x37) & 1); i++) { + u16 *buf = (u16 *)(device_buffer + current_packet_read); + struct PACKET_HEADER packet_header; + packet_header.raw = *buf; + if (packet_header.data.FAE) { + return; + } + if (packet_header.data.CRC) { + return; + } + if (!packet_header.data.ROK) { + return; + } + u16 packet_length = *(buf + 1); + assert(packet_length <= 2048); + + u8 packet_buffer[RTL8139_RXBUFFER_SIZE]; + if (current_packet_read + packet_length >= RTL8139_RXBUFFER_SIZE) { + u32 end = RTL8139_RXBUFFER_SIZE - current_packet_read; + memcpy(packet_buffer, buf, end); + u32 rest = packet_length - end; + memcpy(packet_buffer + end, device_buffer, rest); + } else { + memcpy(packet_buffer, buf, packet_length); + } + + // I have no documentation backing this implementation of updating + // the CBR. It is just a (somewhat)uneducated guess. But it does + // seem to work. + u32 old = current_packet_read; + current_packet_read = (current_packet_read + packet_length + 4 + 3) & (~3); + current_packet_read %= RTL8139_RXBUFFER_SIZE; + outw(rtl8139.gen.base_mem_io + 0x38, current_packet_read - 0x10); + current_packet_read = inw(rtl8139.gen.base_mem_io + 0x3A); + outw(rtl8139.gen.base_mem_io + 0x38, current_packet_read - 0x10); + + assert(current_packet_read != old); + + handle_ethernet((u8 *)packet_buffer + 4, packet_length); } - - handle_ethernet((u8 *)packet_buffer + 4, packet_length); - - // Thanks to exscape - // https://github.com/exscape/exscapeOS/blob/master/src/kernel/net/rtl8139.c - // and the programmers guide - // https://www.cs.usfca.edu/~cruse/cs326f04/RTL8139_ProgrammersGuide.pdf I - // have no clue what this calculation, I can't find anything possibly relating - // to this in the manual, but it does work I guess. - current_packet_read = (current_packet_read + packet_length + 4 + 3) & (~3); - current_packet_read %= 8192 + 16; - outw(rtl8139.gen.base_mem_io + 0x38, current_packet_read - 0x10); } __attribute__((interrupt)) void rtl8139_handler(void *regs) { (void)regs; u16 status = inw(rtl8139.gen.base_mem_io + 0x3e); - outw(rtl8139.gen.base_mem_io + 0x3E, 0x5); if (status & (1 << 2)) { } if (status & (1 << 0)) { handle_packet(); } + outw(rtl8139.gen.base_mem_io + 0x3E, 0x5); EOI(0xB); } @@ -92,15 +109,14 @@ int rtl8139_send_data(u8 *data, u16 data_size) { // buffer if (data_size > 0x1000) return 0; - static int loop = 0; - if (loop > 3) { - loop = 0; + if (send_buffers_loop > 3) { + send_buffers_loop = 0; } - memcpy(send_buffers[loop], data, data_size); - outl(device->gen.base_mem_io + 0x20 + loop * 4, - (u32)virtual_to_physical(send_buffers[loop], NULL)); - outl(device->gen.base_mem_io + 0x10 + loop * 4, data_size); - loop += 1; + memcpy(send_buffers[send_buffers_loop], data, data_size); + outl(device->gen.base_mem_io + 0x20 + send_buffers_loop * 4, + (u32)virtual_to_physical(send_buffers[send_buffers_loop], NULL)); + outl(device->gen.base_mem_io + 0x10 + send_buffers_loop * 4, data_size); + send_buffers_loop += 1; return 1; } @@ -150,14 +166,15 @@ void rtl8139_init(void) { outb(base_address + CMD, 0x10); for (; 0 != (inb(base_address + CMD) & 0x10);) ; - device_buffer = ksbrk(8192 + 16); - memset(device_buffer, 0, 8192 + 16); + device_buffer = ksbrk(RTL8139_RXBUFFER_SIZE); + memset(device_buffer, 0, RTL8139_RXBUFFER_SIZE); // Setupt the recieve buffer u32 rx_buffer = (u32)virtual_to_physical(device_buffer, NULL); outl(base_address + RBSTART, rx_buffer); // Set IMR + ISR - outw(base_address + IMR, (1 << 2) | (1 << 3) | (1 << 0)); + // outw(base_address + IMR, (1 << 2) | (1 << 3) | (1 << 0)); + outw(base_address + IMR, (1 << 2) | (1 << 0)); // Set transmit and reciever enable outb(base_address + 0x37, (1 << 2) | (1 << 3)); @@ -166,7 +183,7 @@ void rtl8139_init(void) { outl(base_address + 0x44, 0xf); // 0xf is AB+AM+APM+AAP - install_handler(rtl8139_handler, INT_32_INTERRUPT_GATE(0x0), + install_handler(rtl8139_handler, INT_32_INTERRUPT_GATE(0x3), 0x20 + interrupt_line); // ksbrk() seems to have the magical ability of disabling interrupts? diff --git a/kernel/network/arp.c b/kernel/network/arp.c index b5825be..baff528 100644 --- a/kernel/network/arp.c +++ b/kernel/network/arp.c @@ -83,7 +83,6 @@ void send_arp_request(const u8 ip[4]) { } int get_mac_from_ip(const u8 ip[4], u8 mac[6]) { - print_ip("ARP GETTING MAC FROM IP: ", ip); for (int i = 0; i < 10; i++) { if (0 != memcmp(arp_table[i].ip, ip, sizeof(u8[4]))) continue; diff --git a/kernel/network/ipv4.c b/kernel/network/ipv4.c index e38ab9b..9565bb5 100644 --- a/kernel/network/ipv4.c +++ b/kernel/network/ipv4.c @@ -41,8 +41,7 @@ u16 ip_checksum(void *vdata, size_t length) { } extern u8 ip_address[4]; -void send_ipv4_packet(u32 ip, u8 protocol, const u8 *payload, - u16 length) { +void send_ipv4_packet(u32 ip, u8 protocol, const u8 *payload, u16 length) { u8 header[20] = {0}; header[0] = (4 /*version*/ << 4) | (5 /*IHL*/); *((u16 *)(header + 2)) = htons(length + 20); @@ -74,7 +73,8 @@ void handle_ipv4(const u8 *payload, u32 packet_length) { *(u16 *)(payload + 10) = 0; u16 calc_checksum = ip_checksum((u8 *)payload, 20); *(u16 *)(payload + 10) = saved_checksum; - assert(calc_checksum == saved_checksum); + if(calc_checksum != saved_checksum) + return; u8 version = (*payload & 0xF0) >> 4; u8 IHL = (*payload & 0xF); diff --git a/kernel/network/tcp.c b/kernel/network/tcp.c index 4b2c462..14bd0cb 100644 --- a/kernel/network/tcp.c +++ b/kernel/network/tcp.c @@ -15,6 +15,9 @@ extern u8 ip_address[4]; #define SYN (1 << 1) #define FIN (1 << 0) +// FIXME: This should be dynamic +#define WINDOW_SIZE 4096 + struct __attribute__((__packed__)) TCP_HEADER { u16 src_port; u16 dst_port; @@ -93,7 +96,7 @@ void tcp_close_connection(struct INCOMING_TCP_CONNECTION *inc) { header.data_offset = 5; header.reserved = 0; header.flags = FIN | ACK; - header.window_size = htons(512); + header.window_size = htons(WINDOW_SIZE); header.urgent_pointer = 0; u32 dst_ip; memcpy(&dst_ip, inc->ip, sizeof(dst_ip)); @@ -118,7 +121,7 @@ void send_tcp_packet(struct INCOMING_TCP_CONNECTION *inc, u8 *payload, header.data_offset = 5; header.reserved = 0; header.flags = PSH | ACK; - header.window_size = htons(512); + header.window_size = htons(WINDOW_SIZE); header.urgent_pointer = 0; u32 dst_ip; memcpy(&dst_ip, inc->ip, sizeof(dst_ip)); @@ -143,7 +146,7 @@ void send_empty_tcp_message(struct INCOMING_TCP_CONNECTION *inc, u8 flags, header.data_offset = 5; header.reserved = 0; header.flags = flags; - header.window_size = htons(512); // TODO: What does this actually mean? + header.window_size = htons(WINDOW_SIZE); header.urgent_pointer = 0; char payload[0]; tcp_calculate_checksum(ip_address, inc->ip, (const u8 *)payload, 0, &header); @@ -201,12 +204,11 @@ void handle_tcp(u8 src_ip[4], const u8 *payload, u32 payload_length) { // inc->seq_num = ack_num; } if (flags & PSH) { - kprintf("send ipv4 packet: %x\n", pit_num_ms()); u16 tcp_payload_length = payload_length - inc_header->data_offset * sizeof(u32); - fifo_object_write( - (u8 *)(payload + inc_header->data_offset * sizeof(u32)), 0, - tcp_payload_length, inc->data_file); + fifo_object_write((u8 *)(payload + inc_header->data_offset * sizeof(u32)), + 0, tcp_payload_length, inc->data_file); + *inc->has_data_ptr = 1; // Send back a ACK struct TCP_HEADER header = {0}; @@ -218,7 +220,7 @@ void handle_tcp(u8 src_ip[4], const u8 *payload, u32 payload_length) { header.data_offset = 5; header.reserved = 0; header.flags = ACK; - header.window_size = htons(512); // TODO: What does this actually mean? + header.window_size = htons(WINDOW_SIZE); header.urgent_pointer = 0; char payload[0]; tcp_calculate_checksum(ip_address, src_ip, (const u8 *)payload, 0, &header); diff --git a/kernel/socket.c b/kernel/socket.c index 630c203..27342e0 100644 --- a/kernel/socket.c +++ b/kernel/socket.c @@ -86,6 +86,8 @@ handle_incoming_tcp_connection(u8 ip[4], u16 n_port, u16 dst_port) { NULL /*create_directory*/, NULL /*get_vm_object*/, NULL /*truncate*/, NULL /*stat*/); + tcp_connections[i].has_data_ptr = &inode->has_data; + vfs_fd_t *fd; int n = vfs_create_fd(O_RDWR | O_NONBLOCK, 0, 0 /*is_tty*/, inode, &fd); @@ -102,7 +104,6 @@ handle_incoming_tcp_connection(u8 ip[4], u16 n_port, u16 dst_port) { // But it does not get freed since the reference count // is still over zero. fd->reference_count--; - kprintf("connection sent to server\n"); return &tcp_connections[i]; } diff --git a/kernel/socket.h b/kernel/socket.h index 5e8c3b1..954ee4d 100644 --- a/kernel/socket.h +++ b/kernel/socket.h @@ -46,6 +46,7 @@ struct INCOMING_TCP_CONNECTION { u16 n_port; u16 dst_port; FIFO_FILE *data_file; + u8 *has_data_ptr; u8 is_used; u32 ack_num; u32 seq_num; |