Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #4
0
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}