- upl = (upl_t)port->ip_kobject;
- mutex_lock(&(upl)->Lock);
- upl->ref_count-=1;
- if(upl->ref_count == 0) {
- mutex_unlock(&(upl)->Lock);
- uc_upl_abort(upl, UPL_ABORT_ERROR);
- } else
- mutex_unlock(&(upl)->Lock);
-}
-
-/* Retrieve a upl for an object underlying an address range in a map */
-
-kern_return_t
-vm_map_get_upl(
- vm_map_t map,
- vm_offset_t offset,
- vm_size_t *upl_size,
- upl_t *upl,
- upl_page_info_t **page_list,
- int *count,
- int *flags,
- int force_data_sync)
-{
- vm_map_entry_t entry;
- int caller_flags;
- int sync_cow_data = FALSE;
- vm_object_t local_object;
- vm_offset_t local_offset;
- vm_offset_t local_start;
- kern_return_t ret;
-
- caller_flags = *flags;
- if (!(caller_flags & UPL_COPYOUT_FROM)) {
- sync_cow_data = TRUE;
- }
- if(upl == NULL)
- return KERN_INVALID_ARGUMENT;
-REDISCOVER_ENTRY:
- vm_map_lock(map);
- if (vm_map_lookup_entry(map, offset, &entry)) {
- if((entry->vme_end - offset) < *upl_size) {
- *upl_size = entry->vme_end - offset;
- }
- /*
- * Create an object if necessary.
- */
- if (entry->object.vm_object == VM_OBJECT_NULL) {
- entry->object.vm_object = vm_object_allocate(
- (vm_size_t)(entry->vme_end - entry->vme_start));
- entry->offset = 0;
- }
- if (!(caller_flags & UPL_COPYOUT_FROM)) {
- if (entry->needs_copy
- || entry->object.vm_object->copy) {
- vm_map_t local_map;
- vm_object_t object;
- vm_object_offset_t offset_hi;
- vm_object_offset_t offset_lo;
- vm_object_offset_t new_offset;
- vm_prot_t prot;
- boolean_t wired;
- vm_behavior_t behavior;
- vm_map_version_t version;
- vm_map_t pmap_map;
-
- local_map = map;
- vm_map_lock_write_to_read(map);
- if(vm_map_lookup_locked(&local_map,
- offset, VM_PROT_WRITE,
- &version, &object,
- &new_offset, &prot, &wired,
- &behavior, &offset_lo,
- &offset_hi, &pmap_map)) {
- vm_map_unlock(local_map);
- return KERN_FAILURE;
- }
- if (pmap_map != map) {
- vm_map_unlock(pmap_map);
- }
- vm_object_unlock(object);
- vm_map_unlock(local_map);
-
- goto REDISCOVER_ENTRY;
- }
- }
- if (entry->is_sub_map) {
- vm_map_t submap;
-
- submap = entry->object.sub_map;
- local_start = entry->vme_start;
- local_offset = entry->offset;
- vm_map_reference(submap);
- vm_map_unlock(map);
-
- ret = (vm_map_get_upl(submap,
- local_offset + (offset - local_start),
- upl_size, upl, page_list, count,
- flags, force_data_sync));
-
- vm_map_deallocate(submap);
- return ret;
- }
-
- if (sync_cow_data) {
- if (entry->object.vm_object->shadow) {
- int flags;
-
- local_object = entry->object.vm_object;
- local_start = entry->vme_start;
- local_offset = entry->offset;
- vm_object_reference(local_object);
- vm_map_unlock(map);
-
- if(local_object->copy == NULL) {
- flags = MEMORY_OBJECT_DATA_SYNC;
- } else {
- flags = MEMORY_OBJECT_COPY_SYNC;
- }
-
- if((local_object->paging_offset) &&
- (local_object->pager == 0)) {
- /*
- * do a little clean-up for our unorthodox
- * entry into a pager call from a non-pager
- * context. Normally the pager code
- * assumes that an object it has been called
- * with has a backing pager and so does
- * not bother to check the pager field
- * before relying on the paging_offset
- */
- vm_object_lock(local_object);
- if (local_object->pager == 0) {
- local_object->paging_offset = 0;
- }
- vm_object_unlock(local_object);
- }
-
- memory_object_lock_request(
- local_object, ((offset - local_start)
- + local_offset) +
- local_object->paging_offset,
- (vm_object_size_t)*upl_size, FALSE,
- flags,
- VM_PROT_NO_CHANGE, NULL, 0);
- sync_cow_data = FALSE;
- goto REDISCOVER_ENTRY;
- }
- }
-
- if (force_data_sync) {
-
- local_object = entry->object.vm_object;
- local_start = entry->vme_start;
- local_offset = entry->offset;
- vm_object_reference(local_object);
- vm_map_unlock(map);
-
- if((local_object->paging_offset) &&
- (local_object->pager == 0)) {
- /*
- * do a little clean-up for our unorthodox
- * entry into a pager call from a non-pager
- * context. Normally the pager code
- * assumes that an object it has been called
- * with has a backing pager and so does
- * not bother to check the pager field
- * before relying on the paging_offset
- */
- vm_object_lock(local_object);
- if (local_object->pager == 0) {
- local_object->paging_offset = 0;
- }
- vm_object_unlock(local_object);
- }
-
- memory_object_lock_request(
- local_object, ((offset - local_start)
- + local_offset) +
- local_object->paging_offset,
- (vm_object_size_t)*upl_size, FALSE,
- MEMORY_OBJECT_DATA_SYNC,
- VM_PROT_NO_CHANGE,
- NULL, 0);
- force_data_sync = FALSE;
- goto REDISCOVER_ENTRY;
- }
-
- if(!(entry->object.vm_object->private)) {
- if(*upl_size > (MAX_UPL_TRANSFER*PAGE_SIZE))
- *upl_size = (MAX_UPL_TRANSFER*PAGE_SIZE);
- if(entry->object.vm_object->phys_contiguous) {
- *flags = UPL_PHYS_CONTIG;
- } else {
- *flags = 0;
- }
- } else {
- *flags = UPL_DEV_MEMORY | UPL_PHYS_CONTIG;
- }
- local_object = entry->object.vm_object;
- local_offset = entry->offset;
- local_start = entry->vme_start;
- vm_object_reference(local_object);
- vm_map_unlock(map);
- ret = (vm_fault_list_request(local_object,
- ((offset - local_start) + local_offset),
- *upl_size,
- upl,
- page_list,
- *count,
- caller_flags));
- vm_object_deallocate(local_object);
- return(ret);
- }