void set_nframes(uint32_t n) { nframes = n; if (frames) panic("reallocing frames\n"); frames = (uint32_t *)kmalloc(INDEX_BIT(nframes * 8)); memset(frames, 0, INDEX_BIT(nframes)); uintptr_t p; kernel_dir = kvmalloc_p(sizeof(page_dir_t), &p); printk("mm: frame: kernel_dir at 0x%x\n", kernel_dir); memset(kernel_dir, 0, sizeof(page_dir_t)); }
int init_rtl(void) { if (rtl_device_pci) { debug_print(NOTICE, "Located an RTL 8139: 0x%x\n", rtl_device_pci); uint16_t command_reg = pci_read_field(rtl_device_pci, PCI_COMMAND, 4); debug_print(NOTICE, "COMMAND register before: 0x%4x\n", command_reg); if (command_reg & (1 << 2)) { debug_print(NOTICE, "Bus mastering already enabled.\n"); } else { command_reg |= (1 << 2); /* bit 2 */ debug_print(NOTICE, "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); debug_print(NOTICE, "COMMAND register after: 0x%4x\n", command_reg); } rtl_irq = pci_read_field(rtl_device_pci, PCI_INTERRUPT_LINE, 1); debug_print(NOTICE, "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); debug_print(NOTICE, "BAR0: 0x%8x\n", rtl_bar0); debug_print(NOTICE, "BAR1: 0x%8x\n", rtl_bar1); rtl_iobase = 0x00000000; if (rtl_bar0 & 0x00000001) { rtl_iobase = rtl_bar0 & 0xFFFFFFFC; } else { debug_print(NOTICE, "This doesn't seem right! RTL8139 should be using an I/O BAR; this looks like a memory bar."); } debug_print(NOTICE, "RTL iobase: 0x%x\n", rtl_iobase); rx_wait = list_create(); debug_print(NOTICE, "Determining mac address...\n"); for (int i = 0; i < 6; ++i) { mac[i] = inports(rtl_iobase + RTL_PORT_MAC + i); } debug_print(NOTICE, "%2x:%2x:%2x:%2x:%2x:%2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); debug_print(NOTICE, "Enabling RTL8139.\n"); outportb(rtl_iobase + RTL_PORT_CONFIG, 0x0); debug_print(NOTICE, "Resetting RTL8139.\n"); outportb(rtl_iobase + RTL_PORT_CMD, 0x10); while ((inportb(rtl_iobase + 0x37) & 0x10) != 0) { } debug_print(NOTICE, "Done resetting RTL8139.\n"); for (int i = 0; i < 5; ++i) { 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; } } rtl_rx_buffer = (uint8_t *)kvmalloc_p(0x3000, &rtl_rx_phys); memset(rtl_rx_buffer, 0x00, 0x3000); 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)); for (int i = 0; i < 5; ++i) { debug_print(NOTICE, " tx 0x%x [phys 0x%x]\n", rtl_tx_buffer[i], rtl_tx_phys[i]); } debug_print(NOTICE, "Initializing receive buffer.\n"); outportl(rtl_iobase + RTL_PORT_RBSTART, rtl_rx_phys); debug_print(NOTICE, "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 */ 0x04 | /* Tx okay */ 0x02 | /* Rx error */ 0x01 /* Rx okay */ ); /* TOK, ROK */ debug_print(NOTICE, "Configuring transmit\n"); outportl(rtl_iobase + RTL_PORT_TCR, 0 ); debug_print(NOTICE, "Configuring receive buffer.\n"); outportl(rtl_iobase + RTL_PORT_RCR, (0) | /* 8K receive */ 0x08 | /* broadcast */ 0x01 /* all physical */ ); debug_print(NOTICE, "Enabling receive and transmit.\n"); outportb(rtl_iobase + RTL_PORT_CMD, 0x08 | 0x04); debug_print(NOTICE, "Resetting rx stats\n"); outportl(rtl_iobase + RTL_PORT_RXMISS, 0); net_queue = list_create(); #if 1 { debug_print(NOTICE, "Sending DHCP discover\n"); 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); next_tx++; if (next_tx == 4) { next_tx = 0; } } { struct ethernet_packet * eth = (struct ethernet_packet *)rtl_dequeue(); uint16_t eth_type = ntohs(eth->type); debug_print(NOTICE, "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); debug_print(NOTICE, "IP packet [%s → %s] length=%d bytes\n", src_ip, dst_ip, length); struct udp_packet * udp = (struct udp_packet *)ipv4->payload;; uint16_t src_port = ntohs(udp->source_port); uint16_t dst_port = ntohs(udp->destination_port); uint16_t udp_len = ntohs(udp->length); debug_print(NOTICE, "UDP [%d → %d] length=%d bytes\n", src_port, dst_port, udp_len); struct dhcp_packet * dhcp = (struct dhcp_packet *)udp->payload; uint32_t yiaddr = ntohl(dhcp->yiaddr); char yiaddr_ip[16]; ip_ntoa(yiaddr, yiaddr_ip); debug_print(NOTICE, "DHCP Offer: %s\n", yiaddr_ip); free(eth); } #endif debug_print(NOTICE, "Card is configured, going to start worker thread now.\n"); debug_print(NOTICE, "Initializing netif functions\n"); init_netif_funcs(rtl_get_mac, rtl_get_packet, rtl_send_packet); create_kernel_tasklet(net_handler, "[eth]", NULL); debug_print(NOTICE, "Back from starting the worker thread.\n"); } else { return -1; } return 0; }
int init_rtl(void) { if (rtl_device_pci) { debug_print(NOTICE, "Located an RTL 8139: 0x%x\n", rtl_device_pci); uint16_t command_reg = pci_read_field(rtl_device_pci, PCI_COMMAND, 4); debug_print(NOTICE, "COMMAND register before: 0x%4x\n", command_reg); if (command_reg & (1 << 2)) { debug_print(NOTICE, "Bus mastering already enabled.\n"); } else { command_reg |= (1 << 2); /* bit 2 */ debug_print(NOTICE, "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); debug_print(NOTICE, "COMMAND register after: 0x%4x\n", command_reg); } rtl_irq = pci_get_interrupt(rtl_device_pci); debug_print(NOTICE, "Interrupt Line: %x\n", rtl_irq); irq_install_handler(rtl_irq, rtl_irq_handler, "rtl8139"); 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); debug_print(NOTICE, "BAR0: 0x%8x\n", rtl_bar0); debug_print(NOTICE, "BAR1: 0x%8x\n", rtl_bar1); rtl_iobase = 0x00000000; if (rtl_bar0 & 0x00000001) { rtl_iobase = rtl_bar0 & 0xFFFFFFFC; } else { debug_print(NOTICE, "This doesn't seem right! RTL8139 should be using an I/O BAR; this looks like a memory bar."); } debug_print(NOTICE, "RTL iobase: 0x%x\n", rtl_iobase); rx_wait = list_create(); debug_print(NOTICE, "Determining mac address...\n"); for (int i = 0; i < 6; ++i) { mac[i] = inports(rtl_iobase + RTL_PORT_MAC + i); } debug_print(NOTICE, "%2x:%2x:%2x:%2x:%2x:%2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); debug_print(NOTICE, "Enabling RTL8139.\n"); outportb(rtl_iobase + RTL_PORT_CONFIG, 0x0); debug_print(NOTICE, "Resetting RTL8139.\n"); outportb(rtl_iobase + RTL_PORT_CMD, 0x10); while ((inportb(rtl_iobase + 0x37) & 0x10) != 0) { } debug_print(NOTICE, "Done resetting RTL8139.\n"); for (int i = 0; i < 5; ++i) { 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; } } rtl_rx_buffer = (uint8_t *)kvmalloc_p(0x3000, &rtl_rx_phys); memset(rtl_rx_buffer, 0x00, 0x3000); 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)); for (int i = 0; i < 5; ++i) { debug_print(NOTICE, " tx 0x%x [phys 0x%x]\n", rtl_tx_buffer[i], rtl_tx_phys[i]); } debug_print(NOTICE, "Initializing receive buffer.\n"); outportl(rtl_iobase + RTL_PORT_RBSTART, rtl_rx_phys); debug_print(NOTICE, "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 */ 0x04 | /* Tx okay */ 0x02 | /* Rx error */ 0x01 /* Rx okay */ ); /* TOK, ROK */ debug_print(NOTICE, "Configuring transmit\n"); outportl(rtl_iobase + RTL_PORT_TCR, 0 ); debug_print(NOTICE, "Configuring receive buffer.\n"); outportl(rtl_iobase + RTL_PORT_RCR, (0) | /* 8K receive */ 0x08 | /* broadcast */ 0x01 /* all physical */ ); debug_print(NOTICE, "Enabling receive and transmit.\n"); outportb(rtl_iobase + RTL_PORT_CMD, 0x08 | 0x04); debug_print(NOTICE, "Resetting rx stats\n"); outportl(rtl_iobase + RTL_PORT_RXMISS, 0); net_queue = list_create(); debug_print(NOTICE, "Initializing netif functions\n"); init_netif_funcs(rtl_get_mac, rtl_get_packet, rtl_send_packet, "RTL8139"); debug_print(NOTICE, "Back from starting the worker thread.\n"); } else { return -1; } return 0; }