static addr_t vtophys(void *virt) { addr_t phys = 0; vm_get_page_mapping(vm_get_kernel_aspace_id(), (addr_t)virt, &phys); return phys; }
static int init_dma(pci_bus_cookie *cookie) { addr_t temp; uint8 val = in8(cookie->io_port + BM_STATUS_REG ); TRACE(("entering init_dma status = %d\n",val)); if (!( val &( BM_SR_MASK_DRV1 | BM_SR_MASK_DRV0 ))) { TRACE(("BM_STATUS is wrong %d\n",val)); return -1; } cookie->prd_region_id = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "ide_prd_buf", (void **)&cookie->prd_buf_address, REGION_ADDR_ANY_ADDRESS, 4096, REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW); cookie->stat_reg = in8( cookie->io_port + + BM_STATUS_REG ); cookie->stat_reg = cookie->stat_reg & 0xe0; memset(cookie->prd_buf_address, 0, 4096); vm_get_page_mapping(vm_get_kernel_aspace_id(), (addr_t)cookie->prd_buf_address, &cookie->prd_phy_address); cookie->raw_buffer = (uint8*)0x80000; vm_map_physical_memory(vm_get_kernel_aspace_id(), "test", (void *)&cookie->mapped_address, REGION_ADDR_ANY_ADDRESS,0x10000, LOCK_RW|LOCK_KERNEL, (addr_t)cookie->raw_buffer); TRACE(("mapped address is %X\n",cookie->mapped_address)); return 0; }
status_t X86VMTranslationMap64Bit::Init(bool kernel) { TRACE("X86VMTranslationMap64Bit::Init()\n"); X86VMTranslationMap::Init(kernel); fPagingStructures = new(std::nothrow) X86PagingStructures64Bit; if (fPagingStructures == NULL) return B_NO_MEMORY; X86PagingMethod64Bit* method = X86PagingMethod64Bit::Method(); if (kernel) { // Get the page mapper. fPageMapper = method->KernelPhysicalPageMapper(); // Kernel PML4 is already mapped. fPagingStructures->Init(method->KernelVirtualPML4(), method->KernelPhysicalPML4()); } else { // Allocate a physical page mapper. status_t error = method->PhysicalPageMapper() ->CreateTranslationMapPhysicalPageMapper(&fPageMapper); if (error != B_OK) return error; // Assuming that only the top 2 PML4 entries are occupied for the // kernel. STATIC_ASSERT(KERNEL_PMAP_BASE == 0xffffff0000000000); STATIC_ASSERT(KERNEL_BASE == 0xffffff8000000000); // Allocate and clear the PML4. uint64* virtualPML4 = (uint64*)memalign(B_PAGE_SIZE, B_PAGE_SIZE); if (virtualPML4 == NULL) return B_NO_MEMORY; memset(virtualPML4, 0, B_PAGE_SIZE); // Copy the top 2 PML4 entries. virtualPML4[510] = method->KernelVirtualPML4()[510]; virtualPML4[511] = method->KernelVirtualPML4()[511]; // Look up the PML4 physical address. phys_addr_t physicalPML4; vm_get_page_mapping(VMAddressSpace::KernelID(), (addr_t)virtualPML4, &physicalPML4); // Initialize the paging structures. fPagingStructures->Init(virtualPML4, physicalPML4); } return B_OK; }
status_t ARMVMTranslationMap32Bit::Init(bool kernel) { TRACE("ARMVMTranslationMap32Bit::Init()\n"); ARMVMTranslationMap::Init(kernel); fPagingStructures = new(std::nothrow) ARMPagingStructures32Bit; if (fPagingStructures == NULL) return B_NO_MEMORY; ARMPagingMethod32Bit* method = ARMPagingMethod32Bit::Method(); if (!kernel) { // user // allocate a physical page mapper status_t error = method->PhysicalPageMapper() ->CreateTranslationMapPhysicalPageMapper(&fPageMapper); if (error != B_OK) return error; // allocate the page directory page_directory_entry* virtualPageDir = (page_directory_entry*)memalign( B_PAGE_SIZE, B_PAGE_SIZE); if (virtualPageDir == NULL) return B_NO_MEMORY; // look up the page directory's physical address phys_addr_t physicalPageDir; vm_get_page_mapping(VMAddressSpace::KernelID(), (addr_t)virtualPageDir, &physicalPageDir); fPagingStructures->Init(virtualPageDir, physicalPageDir, method->KernelVirtualPageDirectory()); } else { // kernel // get the physical page mapper fPageMapper = method->KernelPhysicalPageMapper(); // we already know the kernel pgdir mapping fPagingStructures->Init(method->KernelVirtualPageDirectory(), method->KernelPhysicalPageDirectory(), NULL); } return B_OK; }
status_t M68KVMTranslationMap040::Init(bool kernel) { TRACE("M68KVMTranslationMap040::Init()\n"); M68KVMTranslationMap::Init(kernel); fPagingStructures = new(std::nothrow) M68KPagingStructures040; if (fPagingStructures == NULL) return B_NO_MEMORY; M68KPagingMethod040* method = M68KPagingMethod040::Method(); if (!kernel) { // user // allocate a physical page mapper status_t error = method->PhysicalPageMapper() ->CreateTranslationMapPhysicalPageMapper(&fPageMapper); if (error != B_OK) return error; // allocate the page root page_root_entry* virtualPageRoot = (page_root_entry*)memalign( SIZ_ROOTTBL, SIZ_ROOTTBL); if (virtualPageRoot == NULL) return B_NO_MEMORY; // look up the page directory's physical address phys_addr_t physicalPageRoot; vm_get_page_mapping(VMAddressSpace::KernelID(), (addr_t)virtualPageRoot, &physicalPageRoot); fPagingStructures->Init(virtualPageRoot, physicalPageRoot, method->KernelVirtualPageRoot()); } else { // kernel // get the physical page mapper fPageMapper = method->KernelPhysicalPageMapper(); // we already know the kernel pgdir mapping fPagingStructures->Init(method->KernelVirtualPageRoot(), method->KernelPhysicalPageRoot(), NULL); } return B_OK; }
status_t arch_vm_init_end(kernel_args *args) { TRACE(("arch_vm_init_end(): %lu virtual ranges to keep:\n", args->arch_args.num_virtual_ranges_to_keep)); for (int i = 0; i < (int)args->arch_args.num_virtual_ranges_to_keep; i++) { addr_range &range = args->arch_args.virtual_ranges_to_keep[i]; TRACE((" start: %p, size: 0x%lx\n", (void*)range.start, range.size)); #if 0 // skip ranges outside the kernel address space if (!IS_KERNEL_ADDRESS(range.start)) { TRACE((" no kernel address, skipping...\n")); continue; } phys_addr_t physicalAddress; void *address = (void*)range.start; if (vm_get_page_mapping(VMAddressSpace::KernelID(), range.start, &physicalAddress) != B_OK) panic("arch_vm_init_end(): No page mapping for %p\n", address); area_id area = vm_map_physical_memory(VMAddressSpace::KernelID(), "boot loader reserved area", &address, B_EXACT_ADDRESS, range.size, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, physicalAddress, true); if (area < 0) { panic("arch_vm_init_end(): Failed to create area for boot loader " "reserved area: %p - %p\n", (void*)range.start, (void*)(range.start + range.size)); } #endif } #if 0 // Throw away any address space mappings we've inherited from the boot // loader and have not yet turned into an area. vm_free_unused_boot_loader_range(0, 0xffffffff - B_PAGE_SIZE + 1); #endif return B_OK; }
int rhine_init(rhine *r) { bigtime_t time; int err = -1; addr_t temp; int i; dprintf("rhine_init: r %p\n", r); r->region = vm_map_physical_memory(vm_get_kernel_aspace_id(), "rhine_region", (void **)&r->virt_base, REGION_ADDR_ANY_ADDRESS, r->phys_size, LOCK_KERNEL|LOCK_RW, r->phys_base); if(r->region < 0) { dprintf("rhine_init: error creating memory mapped region\n"); err = -1; goto err; } dprintf("rhine mapped at address 0x%lx\n", r->virt_base); /* create regions for tx and rx descriptors */ r->rxdesc_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rhine_rxdesc", (void **)&r->rxdesc, REGION_ADDR_ANY_ADDRESS, RXDESC_COUNT * sizeof(struct rhine_rx_desc), REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW); r->rxdesc_phys = vtophys(r->rxdesc); dprintf("rhine: rx descriptors at %p, phys 0x%x\n", r->rxdesc, r->rxdesc_phys); r->txdesc_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rhine_txdesc", (void **)&r->txdesc, REGION_ADDR_ANY_ADDRESS, TXDESC_COUNT * sizeof(struct rhine_tx_desc), REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW); r->txdesc_phys = vtophys(r->txdesc); dprintf("rhine: tx descriptors at %p, phys 0x%x\n", r->txdesc, r->txdesc_phys); r->reg_spinlock = 0; /* stick all rx and tx buffers in a circular buffer */ for (i=0; i < RXDESC_COUNT; i++) { RXDESC(r, i).status = 0; RXDESC(r, i).framelen = 0; RXDESC(r, i).buflen = 0; RXDESC(r, i).ptr = 0; if (i == RXDESC_COUNT-1) RXDESC(r, i).next = RXDESC_PHYS(r, 0); else RXDESC(r, i).next = RXDESC_PHYS(r, i + 1); } // XXX do same for tx r->rx_head = r->rx_tail = 0; /* reset the chip */ time = system_time(); RHINE_WRITE_16(r, RHINE_CR0, 0x8000); // reset the chip do { thread_snooze(10000); // 10ms if(system_time() - time > 1000000) { break; } } while(RHINE_READ_16(r, RHINE_CR0) & 0x8000); if (RHINE_READ_16(r, RHINE_CR0) & 0x8000) { dprintf("chip didn't reset, trying alternate method\n"); RHINE_SETBITS_8(r, RHINE_MISC_CR1, 0x40); thread_snooze(10000); } /* read in the mac address */ RHINE_WRITE_8(r, RHINE_EECSR, RHINE_READ_8(r, RHINE_EECSR) | (1<<5)); r->mac_addr[0] = RHINE_READ_8(r, RHINE_PAR0); r->mac_addr[1] = RHINE_READ_8(r, RHINE_PAR1); r->mac_addr[2] = RHINE_READ_8(r, RHINE_PAR2); r->mac_addr[3] = RHINE_READ_8(r, RHINE_PAR3); r->mac_addr[4] = RHINE_READ_8(r, RHINE_PAR4); r->mac_addr[5] = RHINE_READ_8(r, RHINE_PAR5); dprintf("rhine: mac addr %x:%x:%x:%x:%x:%x\n", r->mac_addr[0], r->mac_addr[1], r->mac_addr[2], r->mac_addr[3], r->mac_addr[4], r->mac_addr[5]); /* set up the rx state */ /* 64 byte fifo threshold, all physical/broadcast/multicast/small/error packets accepted */ RHINE_WRITE_8(r, RHINE_RCR, (0<<5) | (1<<4) | (1<<3) | (1<<2) | (1<<1) | (1<<0)); RHINE_WRITE_32(r, RHINE_RDA0, RXDESC_PHYS(r, r->rx_head)); /* set up tx state */ /* 64 byte fifo, default backup, default loopback mode */ RHINE_WRITE_8(r, RHINE_TCR, 0); /* mask all interrupts */ RHINE_WRITE_16(r, RHINE_IMR0, 0); /* clear all pending interrupts */ RHINE_WRITE_16(r, RHINE_ISR0, 0xffff); /* set up the interrupt handler */ int_set_io_interrupt_handler(r->irq, &rhine_int, r, "rhine"); { static uint8 buf[2048]; RXDESC(r, r->rx_tail).ptr = vtophys(buf); RXDESC(r, r->rx_tail).buflen = sizeof(buf); RXDESC(r, r->rx_tail).status = 0; RXDESC(r, r->rx_tail).framelen = RHINE_RX_OWNER; r->rx_tail++; RHINE_WRITE_16(r, RHINE_CR0, (1<<1) | (1<<3) | (1<<6)); } /* unmask all interrupts */ RHINE_WRITE_16(r, RHINE_IMR0, 0xffff); #if 0 // try to reset the device time = system_time(); RTL_WRITE_8(r, RT_CHIPCMD, RT_CMD_RESET); do { thread_snooze(10000); // 10ms if(system_time() - time > 1000000) { err = -1; goto err1; } } while((RTL_READ_8(r, RT_CHIPCMD) & RT_CMD_RESET)); // create a rx and tx buf r->rxbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rhine_rxbuf", (void **)&r->rxbuf, REGION_ADDR_ANY_ADDRESS, 64*1024 + 16, REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW); r->txbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rhine_txbuf", (void **)&r->txbuf, REGION_ADDR_ANY_ADDRESS, 8*1024, REGION_WIRING_WIRED, LOCK_KERNEL|LOCK_RW); // set up the transmission buf and sem r->tx_sem = sem_create(4, "rhine_txsem"); mutex_init(&r->lock, "rhine"); r->txbn = 0; r->last_txbn = 0; r->rx_sem = sem_create(0, "rhine_rxsem"); r->reg_spinlock = 0; // set up the interrupt handler int_set_io_interrupt_handler(r->irq, &rhine_int, r, "rhine"); // read the mac address r->mac_addr[0] = RTL_READ_8(r, RT_IDR0); r->mac_addr[1] = RTL_READ_8(r, RT_IDR0 + 1); r->mac_addr[2] = RTL_READ_8(r, RT_IDR0 + 2); r->mac_addr[3] = RTL_READ_8(r, RT_IDR0 + 3); r->mac_addr[4] = RTL_READ_8(r, RT_IDR0 + 4); r->mac_addr[5] = RTL_READ_8(r, RT_IDR0 + 5); dprintf("rhine: mac addr %x:%x:%x:%x:%x:%x\n", r->mac_addr[0], r->mac_addr[1], r->mac_addr[2], r->mac_addr[3], r->mac_addr[4], r->mac_addr[5]); // enable writing to the config registers RTL_WRITE_8(r, RT_CFG9346, 0xc0); // reset config 1 RTL_WRITE_8(r, RT_CONFIG1, 0); // Enable receive and transmit functions RTL_WRITE_8(r, RT_CHIPCMD, RT_CMD_RX_ENABLE | RT_CMD_TX_ENABLE); // Set Rx FIFO threashold to 256, Rx size to 64k+16, 256 byte DMA burst RTL_WRITE_32(r, RT_RXCONFIG, 0x00009c00); // Set Tx 256 byte DMA burst RTL_WRITE_32(r, RT_TXCONFIG, 0x03000400); // Turn off lan-wake and set the driver-loaded bit RTL_WRITE_8(r, RT_CONFIG1, (RTL_READ_8(r, RT_CONFIG1) & ~0x30) | 0x20); // Enable FIFO auto-clear RTL_WRITE_8(r, RT_CONFIG4, RTL_READ_8(r, RT_CONFIG4) | 0x80); // go back to normal mode RTL_WRITE_8(r, RT_CFG9346, 0); // Setup RX buffers *(int *)r->rxbuf = 0; vm_get_page_mapping(vm_get_kernel_aspace_id(), r->rxbuf, &temp); dprintf("rx buffer will be at 0x%lx\n", temp); RTL_WRITE_32(r, RT_RXBUF, temp); // Setup TX buffers dprintf("tx buffer (virtual) is at 0x%lx\n", r->txbuf); *(int *)r->txbuf = 0; vm_get_page_mapping(vm_get_kernel_aspace_id(), r->txbuf, &temp); RTL_WRITE_32(r, RT_TXADDR0, temp); RTL_WRITE_32(r, RT_TXADDR1, temp + 2*1024); dprintf("first half of txbuf at 0x%lx\n", temp); *(int *)(r->txbuf + 4*1024) = 0; vm_get_page_mapping(vm_get_kernel_aspace_id(), r->txbuf + 4*1024, &temp); RTL_WRITE_32(r, RT_TXADDR2, temp); RTL_WRITE_32(r, RT_TXADDR3, temp + 2*1024); dprintf("second half of txbuf at 0x%lx\n", temp); /* RTL_WRITE_32(r, RT_TXSTATUS0, RTL_READ_32(r, RT_TXSTATUS0) | 0xfffff000); RTL_WRITE_32(r, RT_TXSTATUS1, RTL_READ_32(r, RT_TXSTATUS1) | 0xfffff000); RTL_WRITE_32(r, RT_TXSTATUS2, RTL_READ_32(r, RT_TXSTATUS2) | 0xfffff000); RTL_WRITE_32(r, RT_TXSTATUS3, RTL_READ_32(r, RT_TXSTATUS3) | 0xfffff000); */ // Reset RXMISSED counter RTL_WRITE_32(r, RT_RXMISSED, 0); // Enable receiving broadcast and physical match packets // RTL_WRITE_32(r, RT_RXCONFIG, RTL_READ_32(r, RT_RXCONFIG) | 0x0000000a); RTL_WRITE_32(r, RT_RXCONFIG, RTL_READ_32(r, RT_RXCONFIG) | 0x0000000f); // Filter out all multicast packets RTL_WRITE_32(r, RT_MAR0, 0); RTL_WRITE_32(r, RT_MAR0 + 4, 0); // Disable all multi-interrupts RTL_WRITE_16(r, RT_MULTIINTR, 0); RTL_WRITE_16(r, RT_INTRMASK, MYRT_INTS); // RTL_WRITE_16(r, RT_INTRMASK, 0x807f); // Enable RX/TX once more RTL_WRITE_8(r, RT_CHIPCMD, RT_CMD_RX_ENABLE | RT_CMD_TX_ENABLE); RTL_WRITE_8(r, RT_CFG9346, 0); #endif return 0; err1: vm_delete_region(vm_get_kernel_aspace_id(), r->region); err: return err; }
int rtl8139_init(rtl8139 *rtl) { bigtime_t time; int err = -1; addr_t temp; dprintf("rtl8139_init: rtl %p\n", rtl); rtl->region = vm_map_physical_memory(vm_get_kernel_aspace_id(), "rtl8139_region", (void **)&rtl->virt_base, REGION_ADDR_ANY_ADDRESS, rtl->phys_size, LOCK_KERNEL|LOCK_RW, rtl->phys_base); if(rtl->region < 0) { dprintf("rtl8139_init: error creating memory mapped region\n"); err = -1; goto err; } dprintf("rtl8139 mapped at address 0x%lx\n", rtl->virt_base); // try to reset the device time = system_time(); RTL_WRITE_8(rtl, RT_CHIPCMD, RT_CMD_RESET); do { thread_snooze(10000); // 10ms if(system_time() - time > 1000000) { err = -1; goto err1; } } while((RTL_READ_8(rtl, RT_CHIPCMD) & RT_CMD_RESET)); // create a rx and tx buf rtl->rxbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8139_rxbuf", (void **)&rtl->rxbuf, REGION_ADDR_ANY_ADDRESS, 64*1024 + 16, REGION_WIRING_WIRED_CONTIG, LOCK_KERNEL|LOCK_RW); rtl->txbuf_region = vm_create_anonymous_region(vm_get_kernel_aspace_id(), "rtl8139_txbuf", (void **)&rtl->txbuf, REGION_ADDR_ANY_ADDRESS, 8*1024, REGION_WIRING_WIRED, LOCK_KERNEL|LOCK_RW); // set up the transmission buf and sem rtl->tx_sem = sem_create(4, "rtl8139_txsem"); mutex_init(&rtl->lock, "rtl8139"); rtl->txbn = 0; rtl->last_txbn = 0; rtl->rx_sem = sem_create(0, "rtl8139_rxsem"); rtl->reg_spinlock = 0; // set up the interrupt handler int_set_io_interrupt_handler(rtl->irq, &rtl8139_int, rtl, "rtl8139"); // read the mac address rtl->mac_addr[0] = RTL_READ_8(rtl, RT_IDR0); rtl->mac_addr[1] = RTL_READ_8(rtl, RT_IDR0 + 1); rtl->mac_addr[2] = RTL_READ_8(rtl, RT_IDR0 + 2); rtl->mac_addr[3] = RTL_READ_8(rtl, RT_IDR0 + 3); rtl->mac_addr[4] = RTL_READ_8(rtl, RT_IDR0 + 4); rtl->mac_addr[5] = RTL_READ_8(rtl, RT_IDR0 + 5); dprintf("rtl8139: mac addr %x:%x:%x:%x:%x:%x\n", rtl->mac_addr[0], rtl->mac_addr[1], rtl->mac_addr[2], rtl->mac_addr[3], rtl->mac_addr[4], rtl->mac_addr[5]); // enable writing to the config registers RTL_WRITE_8(rtl, RT_CFG9346, 0xc0); // reset config 1 RTL_WRITE_8(rtl, RT_CONFIG1, 0); // Enable receive and transmit functions RTL_WRITE_8(rtl, RT_CHIPCMD, RT_CMD_RX_ENABLE | RT_CMD_TX_ENABLE); // Set Rx FIFO threashold to 256, Rx size to 64k+16, 256 byte DMA burst RTL_WRITE_32(rtl, RT_RXCONFIG, 0x00009c00); // Set Tx 256 byte DMA burst RTL_WRITE_32(rtl, RT_TXCONFIG, 0x03000400); // Turn off lan-wake and set the driver-loaded bit RTL_WRITE_8(rtl, RT_CONFIG1, (RTL_READ_8(rtl, RT_CONFIG1) & ~0x30) | 0x20); // Enable FIFO auto-clear RTL_WRITE_8(rtl, RT_CONFIG4, RTL_READ_8(rtl, RT_CONFIG4) | 0x80); // go back to normal mode RTL_WRITE_8(rtl, RT_CFG9346, 0); // Setup RX buffers *(int *)rtl->rxbuf = 0; vm_get_page_mapping(vm_get_kernel_aspace_id(), rtl->rxbuf, &temp); dprintf("rx buffer will be at 0x%lx\n", temp); RTL_WRITE_32(rtl, RT_RXBUF, temp); // Setup TX buffers dprintf("tx buffer (virtual) is at 0x%lx\n", rtl->txbuf); *(int *)rtl->txbuf = 0; vm_get_page_mapping(vm_get_kernel_aspace_id(), rtl->txbuf, &temp); RTL_WRITE_32(rtl, RT_TXADDR0, temp); RTL_WRITE_32(rtl, RT_TXADDR1, temp + 2*1024); dprintf("first half of txbuf at 0x%lx\n", temp); *(int *)(rtl->txbuf + 4*1024) = 0; vm_get_page_mapping(vm_get_kernel_aspace_id(), rtl->txbuf + 4*1024, &temp); RTL_WRITE_32(rtl, RT_TXADDR2, temp); RTL_WRITE_32(rtl, RT_TXADDR3, temp + 2*1024); dprintf("second half of txbuf at 0x%lx\n", temp); /* RTL_WRITE_32(rtl, RT_TXSTATUS0, RTL_READ_32(rtl, RT_TXSTATUS0) | 0xfffff000); RTL_WRITE_32(rtl, RT_TXSTATUS1, RTL_READ_32(rtl, RT_TXSTATUS1) | 0xfffff000); RTL_WRITE_32(rtl, RT_TXSTATUS2, RTL_READ_32(rtl, RT_TXSTATUS2) | 0xfffff000); RTL_WRITE_32(rtl, RT_TXSTATUS3, RTL_READ_32(rtl, RT_TXSTATUS3) | 0xfffff000); */ // Reset RXMISSED counter RTL_WRITE_32(rtl, RT_RXMISSED, 0); // Enable receiving broadcast and physical match packets // RTL_WRITE_32(rtl, RT_RXCONFIG, RTL_READ_32(rtl, RT_RXCONFIG) | 0x0000000a); RTL_WRITE_32(rtl, RT_RXCONFIG, RTL_READ_32(rtl, RT_RXCONFIG) | 0x0000000f); // Filter out all multicast packets RTL_WRITE_32(rtl, RT_MAR0, 0); RTL_WRITE_32(rtl, RT_MAR0 + 4, 0); // Disable all multi-interrupts RTL_WRITE_16(rtl, RT_MULTIINTR, 0); RTL_WRITE_16(rtl, RT_INTRMASK, MYRT_INTS); // RTL_WRITE_16(rtl, RT_INTRMASK, 0x807f); // Enable RX/TX once more RTL_WRITE_8(rtl, RT_CHIPCMD, RT_CMD_RX_ENABLE | RT_CMD_TX_ENABLE); RTL_WRITE_8(rtl, RT_CFG9346, 0); return 0; err1: vm_delete_region(vm_get_kernel_aspace_id(), rtl->region); err: return err; }