/*------------------------------------------------------------------------* * usb_pc_alloc_mem - allocate DMA'able memory * * Returns: * 0: Success * Else: Failure *------------------------------------------------------------------------*/ uint8_t usb_pc_alloc_mem(struct usb_page_cache *pc, struct usb_page *pg, usb_size_t size, usb_size_t align) { void *ptr; uint32_t rem; /* allocate zeroed memory */ if (align != 1) { ptr = usb_malloc(size + align); if (ptr == NULL) goto error; rem = (-((uintptr_t)ptr)) & (align - 1); } else { ptr = usb_malloc(size); if (ptr == NULL) goto error; rem = 0; } /* setup page cache */ pc->buffer = ((uint8_t *)ptr) + rem; pc->page_start = pg; pc->page_offset_buf = 0; pc->page_offset_end = size; pc->map = NULL; pc->tag = ptr; pc->ismultiseg = (align == 1); /* compute physical address */ usb_pc_common_mem_cb(pc, ptr, size); usb_pc_cpu_flush(pc); return (0); error: /* reset most of the page cache */ pc->buffer = NULL; pc->page_start = NULL; pc->page_offset_buf = 0; pc->page_offset_end = 0; pc->map = NULL; pc->tag = NULL; return (1); }
/*------------------------------------------------------------------------* * usb_pc_load_mem - load virtual memory into DMA * * Return values: * 0: Success * Else: Error *------------------------------------------------------------------------*/ uint8_t usb_pc_load_mem(struct usb_page_cache *pc, usb_size_t size, uint8_t sync) { /* setup page cache */ pc->page_offset_buf = 0; pc->page_offset_end = size; pc->ismultiseg = 1; mtx_assert(pc->tag_parent->mtx, MA_OWNED); if (size > 0) { /* compute physical address */ usb_pc_common_mem_cb(pc, pc->buffer, size); } if (sync == 0) { /* * Call callback so that refcount is decremented * properly: */ pc->tag_parent->dma_error = 0; (pc->tag_parent->func) (pc->tag_parent); } return (0); }
/*------------------------------------------------------------------------* * usb_pc_load_mem_cb - BUS-DMA callback function *------------------------------------------------------------------------*/ static void usb_pc_load_mem_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) { usb_pc_common_mem_cb(arg, segs, nseg, error, 1); }