OSData * IOMapper:: NewARTTable(IOByteCount size, void ** virtAddrP, ppnum_t *physAddrP) { if (!virtAddrP || !physAddrP) return 0; kern_return_t kr; vm_address_t address; size = round_page(size); kr = kmem_alloc_contig(kernel_map, &address, size, PAGE_MASK, 0 /*max_pnum*/, 0 /*pnum_mask*/, false); if (kr) return 0; ppnum_t pagenum = pmap_find_phys(kernel_pmap, (addr64_t) address); if (pagenum) *physAddrP = pagenum; else { FreeARTTable((OSData *) address, size); address = 0; } *virtAddrP = (void *) address; return (OSData *) address; }
/* * UMA backend page allocator for the jumbo frame zones. * * Allocates kernel virtual memory that is backed by contiguous physical * pages. */ static void * mbuf_jumbo_alloc(uma_zone_t zone, int bytes, uint8_t *flags, int wait) { /* Inform UMA that this allocator uses kernel_map/object. */ *flags = UMA_SLAB_KERNEL; return ((void *)kmem_alloc_contig(kernel_map, bytes, wait, (vm_paddr_t)0, ~(vm_paddr_t)0, 1, 0, VM_MEMATTR_DEFAULT)); }
int dmar_init_qi(struct dmar_unit *unit) { uint64_t iqa; uint32_t ics; int qi_sz; if (!DMAR_HAS_QI(unit) || (unit->hw_cap & DMAR_CAP_CM) != 0) return (0); unit->qi_enabled = 1; TUNABLE_INT_FETCH("hw.dmar.qi", &unit->qi_enabled); if (!unit->qi_enabled) return (0); TAILQ_INIT(&unit->tlb_flush_entries); TASK_INIT(&unit->qi_task, 0, dmar_qi_task, unit); unit->qi_taskqueue = taskqueue_create_fast("dmarqf", M_WAITOK, taskqueue_thread_enqueue, &unit->qi_taskqueue); taskqueue_start_threads(&unit->qi_taskqueue, 1, PI_AV, "dmar%d qi taskq", unit->unit); unit->inv_waitd_gen = 0; unit->inv_waitd_seq = 1; qi_sz = DMAR_IQA_QS_DEF; TUNABLE_INT_FETCH("hw.dmar.qi_size", &qi_sz); if (qi_sz > DMAR_IQA_QS_MAX) qi_sz = DMAR_IQA_QS_MAX; unit->inv_queue_size = (1ULL << qi_sz) * PAGE_SIZE; /* Reserve one descriptor to prevent wraparound. */ unit->inv_queue_avail = unit->inv_queue_size - DMAR_IQ_DESCR_SZ; /* The invalidation queue reads by DMARs are always coherent. */ unit->inv_queue = kmem_alloc_contig(kernel_arena, unit->inv_queue_size, M_WAITOK | M_ZERO, 0, dmar_high, PAGE_SIZE, 0, VM_MEMATTR_DEFAULT); unit->inv_waitd_seq_hw_phys = pmap_kextract( (vm_offset_t)&unit->inv_waitd_seq_hw); DMAR_LOCK(unit); dmar_write8(unit, DMAR_IQT_REG, 0); iqa = pmap_kextract(unit->inv_queue); iqa |= qi_sz; dmar_write8(unit, DMAR_IQA_REG, iqa); dmar_enable_qi(unit); ics = dmar_read4(unit, DMAR_ICS_REG); if ((ics & DMAR_ICS_IWC) != 0) { ics = DMAR_ICS_IWC; dmar_write4(unit, DMAR_ICS_REG, ics); } dmar_enable_qi_intr(unit); DMAR_UNLOCK(unit); return (0); }
/* * UMA backend page allocator for the jumbo frame zones. * * Allocates kernel virtual memory that is backed by contiguous physical * pages. */ static void * mbuf_jumbo_alloc(uma_zone_t zone, int bytes, uint8_t *flags, int wait) { #ifndef __rtems__ /* Inform UMA that this allocator uses kernel_map/object. */ *flags = UMA_SLAB_KERNEL; return ((void *)kmem_alloc_contig(kernel_map, bytes, wait, (vm_paddr_t)0, ~(vm_paddr_t)0, 1, 0, VM_MEMATTR_DEFAULT)); #else /* __rtems__ */ return ((void *)malloc(bytes, M_TEMP, wait)); #endif /* __rtems__ */ }
/* * contigmalloc: * * Allocate a block of physically contiguous memory. * * If M_NOWAIT is set, this routine will not block and return NULL if * the allocation fails. */ void * contigmalloc(unsigned long size, struct malloc_type *type, int flags, vm_paddr_t low, vm_paddr_t high, unsigned long alignment, vm_paddr_t boundary) { void *ret; ret = (void *)kmem_alloc_contig(kernel_arena, size, flags, low, high, alignment, boundary, VM_MEMATTR_DEFAULT); if (ret != NULL) malloc_type_allocated(type, round_page(size)); return (ret); }
static int jzlcd_allocfb(struct jzlcd_softc *sc) { sc->vaddr = kmem_alloc_contig(kernel_arena, sc->fbsize, M_NOWAIT | M_ZERO, 0, ~0, FB_ALIGN, 0, VM_MEMATTR_WRITE_COMBINING); if (sc->vaddr == 0) { device_printf(sc->dev, "failed to allocate FB memory\n"); return (ENOMEM); } sc->paddr = pmap_kextract(sc->vaddr); return (0); }
/* * UMA backend page allocator for the jumbo frame zones. * * Allocates kernel virtual memory that is backed by contiguous physical * pages. */ static void * mbuf_jumbo_alloc(uma_zone_t zone, int bytes, uint8_t *flags, int wait) { #if 0 /* Inform UMA that this allocator uses kernel_map/object. */ *flags = UMA_SLAB_KERNEL; return ((void *)kmem_alloc_contig(kernel_map, bytes, wait, (vm_paddr_t)0, ~(vm_paddr_t)0, 1, 0, VM_MEMATTR_DEFAULT)); #else /* OSv: We don't use an allocf function in the UMA allocator stub so this * function isn't being called */ return (NULL); #endif }
void * dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag) { vm_paddr_t high; size_t align; void *mem; #if 0 /* XXX swildner */ if (dev->dma_mask) high = *dev->dma_mask; else #endif high = BUS_SPACE_MAXADDR_32BIT; align = PAGE_SIZE << get_order(size); mem = (void *)kmem_alloc_contig(size, 0, high, align); if (mem) *dma_handle = vtophys(mem); else *dma_handle = 0; return (mem); }
static int load_fw(struct tegra_xhci_softc *sc) { const struct firmware *fw; const struct tegra_xusb_fw_hdr *fw_hdr; vm_paddr_t fw_paddr, fw_base; vm_offset_t fw_vaddr; vm_size_t fw_size; uint32_t code_tags, code_size; struct clocktime fw_clock; struct timespec fw_timespec; int i; /* Reset ARU */ FPCI_WR4(sc, XUSB_CFG_ARU_RST, ARU_RST_RESET); DELAY(3000); /* Check if FALCON already runs */ if (CSB_RD4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO) != 0) { device_printf(sc->dev, "XUSB CPU is already loaded, CPUCTL: 0x%08X\n", CSB_RD4(sc, XUSB_FALCON_CPUCTL)); return (0); } fw = firmware_get(sc->fw_name); if (fw == NULL) { device_printf(sc->dev, "Cannot read xusb firmware\n"); return (ENOENT); } /* Allocate uncached memory and copy firmware into. */ fw_hdr = (const struct tegra_xusb_fw_hdr *)fw->data; fw_size = fw_hdr->fwimg_len; fw_vaddr = kmem_alloc_contig(kernel_arena, fw_size, M_WAITOK, 0, -1UL, PAGE_SIZE, 0, VM_MEMATTR_UNCACHEABLE); fw_paddr = vtophys(fw_vaddr); fw_hdr = (const struct tegra_xusb_fw_hdr *)fw_vaddr; memcpy((void *)fw_vaddr, fw->data, fw_size); firmware_put(fw, FIRMWARE_UNLOAD); sc->fw_vaddr = fw_vaddr; sc->fw_size = fw_size; /* Setup firmware physical address and size. */ fw_base = fw_paddr + sizeof(*fw_hdr); CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_ATTR, fw_size); CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO, fw_base & 0xFFFFFFFF); CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_HI, (uint64_t)fw_base >> 32); CSB_WR4(sc, XUSB_CSB_MEMPOOL_APMAP, APMAP_BOOTPATH); /* Invalidate full L2IMEM context. */ CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG, L2IMEMOP_INVALIDATE_ALL); /* Program load of L2IMEM by boot code. */ code_tags = howmany(fw_hdr->boot_codetag, XUSB_CSB_IMEM_BLOCK_SIZE); code_size = howmany(fw_hdr->boot_codesize, XUSB_CSB_IMEM_BLOCK_SIZE); CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE, L2IMEMOP_SIZE_OFFSET(code_tags) | L2IMEMOP_SIZE_SIZE(code_size)); /* Execute L2IMEM boot code fetch. */ CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG, L2IMEMOP_LOAD_LOCKED_RESULT); /* Program FALCON auto-fill range and block count */ CSB_WR4(sc, XUSB_FALCON_IMFILLCTL, code_size); CSB_WR4(sc, XUSB_FALCON_IMFILLRNG1, IMFILLRNG1_TAG_LO(code_tags) | IMFILLRNG1_TAG_HI(code_tags + code_size)); CSB_WR4(sc, XUSB_FALCON_DMACTL, 0); /* Wait for CPU */ for (i = 500; i > 0; i--) { if (CSB_RD4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT) & L2IMEMOP_RESULT_VLD) break; DELAY(100); } if (i <= 0) { device_printf(sc->dev, "Timedout while wating for DMA, " "state: 0x%08X\n", CSB_RD4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT)); return (ETIMEDOUT); } /* Boot FALCON cpu */ CSB_WR4(sc, XUSB_FALCON_BOOTVEC, fw_hdr->boot_codetag); CSB_WR4(sc, XUSB_FALCON_CPUCTL, CPUCTL_STARTCPU); /* Wait for CPU */ for (i = 50; i > 0; i--) { if (CSB_RD4(sc, XUSB_FALCON_CPUCTL) == CPUCTL_STOPPED) break; DELAY(100); } if (i <= 0) { device_printf(sc->dev, "Timedout while wating for FALCON cpu, " "state: 0x%08X\n", CSB_RD4(sc, XUSB_FALCON_CPUCTL)); return (ETIMEDOUT); } fw_timespec.tv_sec = fw_hdr->fwimg_created_time; fw_timespec.tv_nsec = 0; clock_ts_to_ct(&fw_timespec, &fw_clock); device_printf(sc->dev, " Falcon firmware version: %02X.%02X.%04X," " (%d/%d/%d %d:%02d:%02d UTC)\n", (fw_hdr->version_id >> 24) & 0xFF,(fw_hdr->version_id >> 15) & 0xFF, fw_hdr->version_id & 0xFFFF, fw_clock.day, fw_clock.mon, fw_clock.year, fw_clock.hour, fw_clock.min, fw_clock.sec); return (0); }
mach_vm_address_t IOKernelAllocateWithPhysicalRestrict(mach_vm_size_t size, mach_vm_address_t maxPhys, mach_vm_size_t alignment, bool contiguous) { kern_return_t kr; mach_vm_address_t address; mach_vm_address_t allocationAddress; mach_vm_size_t adjustedSize; mach_vm_address_t alignMask; if (size == 0) return (0); if (alignment == 0) alignment = 1; alignMask = alignment - 1; adjustedSize = (2 * size) + sizeof(mach_vm_size_t) + sizeof(mach_vm_address_t); contiguous = (contiguous && (adjustedSize > page_size)) || (alignment > page_size); if (contiguous || maxPhys) { int options = 0; vm_offset_t virt; adjustedSize = size; contiguous = (contiguous && (adjustedSize > page_size)) || (alignment > page_size); if (!contiguous) { if (maxPhys <= 0xFFFFFFFF) { maxPhys = 0; options |= KMA_LOMEM; } else if (gIOLastPage && (atop_64(maxPhys) > gIOLastPage)) { maxPhys = 0; } } if (contiguous || maxPhys) { kr = kmem_alloc_contig(kernel_map, &virt, size, alignMask, atop(maxPhys), atop(alignMask), 0); } else { kr = kernel_memory_allocate(kernel_map, &virt, size, alignMask, options); } if (KERN_SUCCESS == kr) address = virt; else address = 0; } else { adjustedSize += alignMask; allocationAddress = (mach_vm_address_t) kalloc(adjustedSize); if (allocationAddress) { address = (allocationAddress + alignMask + (sizeof(mach_vm_size_t) + sizeof(mach_vm_address_t))) & (~alignMask); if (atop_32(address) != atop_32(address + size - 1)) address = round_page(address); *((mach_vm_size_t *)(address - sizeof(mach_vm_size_t) - sizeof(mach_vm_address_t))) = adjustedSize; *((mach_vm_address_t *)(address - sizeof(mach_vm_address_t))) = allocationAddress; } else address = 0; } if (address) { IOStatisticsAlloc(kIOStatisticsMallocContiguous, size); #if IOALLOCDEBUG debug_iomalloc_size += size; #endif } return (address); }
static int fimd_attach(device_t dev) { struct panel_info panel; struct fimd_softc *sc; device_t gpio_dev; int reg; sc = device_get_softc(dev); sc->dev = dev; if (bus_alloc_resources(dev, fimd_spec, sc->res)) { device_printf(dev, "could not allocate resources\n"); return (ENXIO); } /* Memory interface */ sc->bst = rman_get_bustag(sc->res[0]); sc->bsh = rman_get_bushandle(sc->res[0]); sc->bst_disp = rman_get_bustag(sc->res[1]); sc->bsh_disp = rman_get_bushandle(sc->res[1]); sc->bst_sysreg = rman_get_bustag(sc->res[2]); sc->bsh_sysreg = rman_get_bushandle(sc->res[2]); if (get_panel_info(sc, &panel)) { device_printf(dev, "Can't get panel info\n"); return (ENXIO); } panel.fixvclk = 0; panel.ivclk = 0; panel.clkval_f = 2; sc->panel = &panel; /* Get the GPIO device, we need this to give power to USB */ gpio_dev = devclass_get_device(devclass_find("gpio"), 0); if (gpio_dev == NULL) { /* TODO */ } reg = bus_space_read_4(sc->bst_sysreg, sc->bsh_sysreg, 0x214); reg |= FIMDBYPASS_DISP1; bus_space_write_4(sc->bst_sysreg, sc->bsh_sysreg, 0x214, reg); sc->sc_info.fb_width = panel.width; sc->sc_info.fb_height = panel.height; sc->sc_info.fb_stride = sc->sc_info.fb_width * 2; sc->sc_info.fb_bpp = sc->sc_info.fb_depth = 16; sc->sc_info.fb_size = sc->sc_info.fb_height * sc->sc_info.fb_stride; sc->sc_info.fb_vbase = (intptr_t)kmem_alloc_contig(kernel_arena, sc->sc_info.fb_size, M_ZERO, 0, ~0, PAGE_SIZE, 0, VM_MEMATTR_UNCACHEABLE); sc->sc_info.fb_pbase = (intptr_t)vtophys(sc->sc_info.fb_vbase); #if 0 printf("%dx%d [%d]\n", sc->sc_info.fb_width, sc->sc_info.fb_height, sc->sc_info.fb_stride); printf("pbase == 0x%08x\n", sc->sc_info.fb_pbase); #endif memset((int8_t *)sc->sc_info.fb_vbase, 0x0, sc->sc_info.fb_size); fimd_init(sc); sc->sc_info.fb_name = device_get_nameunit(dev); /* Ask newbus to attach framebuffer device to me. */ sc->sc_fbd = device_add_child(dev, "fbd", device_get_unit(dev)); if (sc->sc_fbd == NULL) device_printf(dev, "Can't attach fbd device\n"); if (device_probe_and_attach(sc->sc_fbd) != 0) { device_printf(sc->dev, "Failed to attach fbd device\n"); } return (0); }