void pci_scan_slot(pci_func_t f, int type, int bus, int slot) { uint32_t dev = pci_box_device(bus, slot, 0); if (pci_read_field(dev, PCI_VENDOR_ID, 2) == PCI_NONE) { return; } pci_scan_func(f, type, bus, slot, 0); if (!pci_read_field(dev, PCI_HEADER_TYPE, 1)) { return; } for (int func = 1; func < 8; func++) { uint32_t dev = pci_box_device(bus, slot, func); if (pci_read_field(dev, PCI_VENDOR_ID, 2) != PCI_NONE) { pci_scan_func(f, type, bus, slot, func); } } }
void pci_scan(pci_func_t f, int type) { pci_scan_bus(f, type, 0); if (!pci_read_field(0, PCI_HEADER_TYPE, 1)) { return; } for (int func = 1; func < 8; ++func) { uint32_t dev = pci_box_device(0, 0, func); if (pci_read_field(dev, PCI_VENDOR_ID, 2) != PCI_NONE) { pci_scan_bus(f, type, func); } else { break; } } }
static void find_usb_device(uint32_t device, uint16_t vendorid, uint16_t deviceid, void * extra) { if (pci_find_type(device) == 0xc03) { int prog_if = (int)pci_read_field(device, PCI_PROG_IF, 1); if (prog_if == 0) { *((uint32_t *)extra)= device; } } }
void pci_scan_func(pci_func_t f, int type, int bus, int slot, int func) { uint32_t dev = pci_box_device(bus, slot, func); if (type == -1 || type == pci_find_type(dev)) { pci_scan_hit(f, dev); } if (pci_find_type(dev) == PCI_TYPE_BRIDGE) { pci_scan_bus(f, type, pci_read_field(dev, PCI_SECONDARY_BUS, 1)); } }
static void bochas_scan_pci(u32 device,u16 v,u16 d,void *extra) { printf("vendor : %x device : %x\n",v,d); if((v == 0x1234 && d == 0x1111) || (v == 0x80EE && d == 0xBEEF)) { uintptr_t t = pci_read_field(device, PCI_BAR0,4); if(t > 0) *((u8 **)extra) = (u8 *)(t & 0xFFFFFFF0); } }
int bochs_init(void) { outw(VBE_DISPI_IOPORT_INDEX, 0); int n = inw(VBE_DISPI_IOPORT_DATA); if(!(CHECK_BGA(n))) return E_ERR; __lfbptr = 0; void pci_func(uint32_t device, uint16_t vendor_id, uint16_t device_id, void* arg) { if(likely(!( (vendor_id == 0x1234) && (device_id == 0x1111) ))) return; __lfbptr = (uintptr_t) pci_read_field(device, PCI_BAR0, 4); } int i; for(i = 0; i < 65536 && !__lfbptr; i++) pci_scan(&pci_func, i, NULL); if(!__lfbptr) return E_ERR; #define ALIGN(x) \ (((x) + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1)) if(__lfbptr) { uintptr_t frame = ALIGN(__lfbptr) - PAGE_SIZE; uintptr_t end = ALIGN(frame + BGA_VIDEORAM_SIZE); for(; frame < end; frame += PAGE_SIZE) map_page(frame, frame, 1); } else return E_ERR; fbdev->name = "Bochs VBE Extensions"; fbdev->setvideomode = bga_setvideomode; return E_OK; #else int bga_init(void) { return E_ERR; #endif }
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(void) { void find_pci(uint32_t device, uint16_t venid, uint16_t devid, void* data) { if((venid == 0x1022) && (devid == 0x2000)) *((uint32_t*) data) = device; } int pci = 0; pci_scan(&find_pci, -1, &pci); if(!pci) { kprintf(ERROR "pcnet: pci device not found!\n"); return -1; } struct pcnet* dev = (struct pcnet*) kmalloc(sizeof(struct pcnet), GFP_KERNEL); struct ethif* eth = (struct ethif*) kmalloc(sizeof(struct ethif), GFP_KERNEL); memset(dev, 0, sizeof(struct pcnet)); memset(eth, 0, sizeof(struct ethif)); eth->internals = (void*) dev; dev->pci = pci; spinlock_init(&dev->lock); dev->buf = (uintptr_t) kvalloc(0x10000, GFP_KERNEL); dev->bufp = (uintptr_t) V2P((void*) dev->buf); uint16_t cmd = pci_read_field(dev->pci, PCI_COMMAND, 4); if(!(cmd & (1 << 2))) pci_write_field(dev->pci, PCI_COMMAND, 4, cmd | (1 << 2)); dev->irq = pci_read_field(dev->pci, PCI_INTERRUPT_LINE, 1); dev->io = pci_read_field(dev->pci, PCI_BAR0, 4) & 0xFFFFFFF0; dev->mem = pci_read_field(dev->pci, PCI_BAR1, 4) & 0xFFFFFFF0; kprintf(LOG "pcnet: irq: %d, io: %p, mem: %p\n", dev->irq, dev->io, dev->mem); int i; for(i = 0; i < 6; i++) eth->address[i] = inb(dev->io + i); pcnet_irqno = dev->irq; /* FIXME: fix current_irq */ irq_enable(dev->irq, pcnet_irq); irq_set_data(dev->irq, dev); eth->low_level_init = pcnet_init; eth->low_level_startoutput = pcnet_startoutput; eth->low_level_output = pcnet_output; eth->low_level_endoutput = pcnet_endoutput; eth->low_level_startinput = pcnet_startinput; eth->low_level_input = pcnet_input; eth->low_level_endinput = pcnet_endinput; eth->low_level_input_nomem = pcnet_input_nomem; IP4_ADDR(ð->ip, 10, 0, 2, 15); IP4_ADDR(ð->nm, 255, 255, 255, 0); IP4_ADDR(ð->gw, 10, 0, 2, 2); struct netif* netif = (struct netif*) kmalloc(sizeof(struct netif), GFP_KERNEL); dev->netif = netif; if(!netif_add(netif, ð->ip, ð->nm, ð->gw, eth, ethif_init, ethernet_input)) { kprintf(ERROR "pcnet: netif_add() failed\n"); kfree(dev); kfree(eth); kfree(netif); return -1; } netif_set_default(netif); netif_set_up(netif); 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; }
void pci_scan_hit(pci_func_t f, uint32_t dev) { int dev_vend = (int)pci_read_field(dev, PCI_VENDOR_ID, 2); int dev_dvid = (int)pci_read_field(dev, PCI_DEVICE_ID, 2); f(dev, dev_vend, dev_dvid); }
uint16_t pci_find_type(uint32_t dev) { return (pci_read_field(dev, PCI_CLASS, 1) << 8) | pci_read_field(dev, PCI_SUBCLASS, 1); }