2 * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 #include <sys/errno.h>
24 #include <kern/host.h>
25 #include <mach/mach_types.h>
26 #include <vm/vm_map.h>
27 #include <vm/vm_kern.h>
28 #include <vm/vm_pageout.h>
29 #include <mach/kern_return.h>
30 #include <mach/memory_object_types.h>
31 #include <mach/port.h>
32 #include <mach/policy.h>
33 #include <ipc/ipc_port.h>
34 #include <ipc/ipc_space.h>
35 #include <kern/thread.h>
36 #include <device/device_port.h>
37 #include <vm/vm_pageout.h>
39 #include <libkern/OSAtomic.h>
42 /* Device VM COMPONENT INTERFACES */
50 /* until component support available */
54 /* until component support available */
55 int device_pager_workaround
;
57 typedef int device_port_t
;
59 typedef struct device_pager
{
60 int *pager
; /* pager workaround pointer */
61 unsigned int pager_ikot
; /* fake ip_kotype() */
62 unsigned int ref_count
; /* reference count */
63 memory_object_control_t control_handle
; /* mem object's cntrl handle */
64 device_port_t device_handle
; /* device_handle */
72 device_pager_bootstrap(
90 memory_object_control_t
,
95 device_pager_data_request(
97 memory_object_offset_t
,
102 device_pager_data_return(
104 memory_object_offset_t
,
110 device_pager_reference(
114 device_pager_deallocate(
118 device_pager_data_initialize(
120 memory_object_offset_t
,
124 device_pager_data_unlock(
126 memory_object_offset_t
,
131 device_pager_terminate(
135 device_pager_synchronize(
137 memory_object_offset_t
,
146 device_object_create(void);
148 zone_t device_pager_zone
;
151 #define DEVICE_PAGER_NULL ((device_pager_t) 0)
154 #define MAX_DNODE 10000
164 device_pager_bootstrap(void)
166 register vm_size_t size
;
168 size
= (vm_size_t
) sizeof(struct device_pager
);
169 device_pager_zone
= zinit(size
, (vm_size_t
) MAX_DNODE
*size
,
170 PAGE_SIZE
, "device node pager structures");
180 memory_object_t device
,
185 device_pager_t device_object
;
187 device_object
= device_object_create();
188 if (device_object
== DEVICE_PAGER_NULL
)
189 panic("device_pager_setup: device_object_create() failed");
191 device_object
->device_handle
= device_handle
;
192 device_object
->size
= size
;
193 device_object
->flags
= 0;
194 if(flags
& DEVICE_PAGER_CONTIGUOUS
) {
195 device_object
->flags
|= DEVICE_PAGER_CONTIGUOUS
;
197 if(flags
& DEVICE_PAGER_NOPHYSCACHE
) {
198 device_object
->flags
|= DEVICE_PAGER_NOPHYSCACHE
;
201 return((memory_object_t
)device_object
);
208 device_pager_populate_object(
209 memory_object_t device
,
210 memory_object_offset_t offset
,
211 vm_offset_t phys_addr
,
214 device_pager_t device_object
;
215 vm_object_t vm_object
;
220 device_object
= device_pager_lookup(device
);
221 if(device_object
== DEVICE_PAGER_NULL
)
224 vm_object
= (vm_object_t
)memory_object_control_to_vm_object(
225 device_object
->control_handle
);
226 if(vm_object
== NULL
)
229 kr
= vm_object_populate_with_private(
230 vm_object
, offset
, phys_addr
, size
);
231 if(kr
!= KERN_SUCCESS
)
234 if(!vm_object
->phys_contiguous
) {
236 kr
= vm_object_upl_request(vm_object
,
237 (vm_object_offset_t
)offset
, size
, &upl
, NULL
,
238 &null_size
, (UPL_NO_SYNC
| UPL_CLEAN_IN_PLACE
));
240 if(kr
!= KERN_SUCCESS
)
241 panic("device_pager_populate_object: list_req failed");
243 upl_commit(upl
, NULL
);
256 memory_object_t name
)
258 device_pager_t device_object
;
260 device_object
= (device_pager_t
)name
;
261 assert(device_object
->pager
== &device_pager_workaround
);
262 return (device_object
);
269 device_pager_init(memory_object_t mem_obj
,
270 memory_object_control_t control
,
273 device_pager_t device_object
;
275 memory_object_attr_info_data_t attributes
;
277 vm_object_t vm_object
;
280 if (control
== MEMORY_OBJECT_CONTROL_NULL
)
281 return KERN_INVALID_ARGUMENT
;
283 device_object
= device_pager_lookup(mem_obj
);
285 memory_object_control_reference(control
);
286 device_object
->control_handle
= control
;
289 /* The following settings should be done through an expanded change */
290 /* attributes call */
292 vm_object
= (vm_object_t
)memory_object_control_to_vm_object(control
);
293 vm_object_lock(vm_object
);
294 vm_object
->private = TRUE
;
295 if(device_object
->flags
& DEVICE_PAGER_CONTIGUOUS
)
296 vm_object
->phys_contiguous
= TRUE
;
297 if(device_object
->flags
& DEVICE_PAGER_NOPHYSCACHE
)
298 vm_object
->nophyscache
= TRUE
;
299 vm_object_unlock(vm_object
);
302 attributes
.copy_strategy
= MEMORY_OBJECT_COPY_DELAY
;
303 /* attributes.cluster_size = (1 << (CLUSTER_SHIFT + PAGE_SHIFT));*/
304 attributes
.cluster_size
= (1 << (PAGE_SHIFT
));
305 attributes
.may_cache_object
= FALSE
;
306 attributes
.temporary
= TRUE
;
308 kr
= memory_object_change_attributes(
310 MEMORY_OBJECT_ATTRIBUTE_INFO
,
311 (memory_object_info_t
) &attributes
,
312 MEMORY_OBJECT_ATTR_INFO_COUNT
);
313 if (kr
!= KERN_SUCCESS
)
314 panic("device_pager_init: memory_object_change_attributes() failed");
316 return(KERN_SUCCESS
);
323 device_pager_data_return(
324 memory_object_t mem_obj
,
325 memory_object_offset_t offset
,
328 boolean_t kernel_copy
)
330 device_pager_t device_object
;
332 device_object
= device_pager_lookup(mem_obj
);
333 if (device_object
== DEVICE_PAGER_NULL
)
334 panic("device_pager_data_return: lookup failed");
336 return device_data_action(device_object
->device_handle
, device_object
,
337 VM_PROT_READ
| VM_PROT_WRITE
, offset
, data_cnt
);
344 device_pager_data_request(
345 memory_object_t mem_obj
,
346 memory_object_offset_t offset
,
348 vm_prot_t protection_required
)
350 device_pager_t device_object
;
352 device_object
= device_pager_lookup(mem_obj
);
354 if (device_object
== DEVICE_PAGER_NULL
)
355 panic("device_pager_data_request: lookup failed");
357 device_data_action(device_object
->device_handle
, device_object
,
358 VM_PROT_READ
, offset
, length
);
366 device_pager_reference(
367 memory_object_t mem_obj
)
369 device_pager_t device_object
;
370 unsigned int prev_ref_count
;
372 device_object
= device_pager_lookup(mem_obj
);
373 prev_ref_count
= OSIncrementAtomic((UInt32
*)&device_object
->ref_count
);
374 assert(prev_ref_count
> 0);
381 device_pager_deallocate(
382 memory_object_t mem_obj
)
384 device_pager_t device_object
;
386 device_object
= device_pager_lookup(mem_obj
);
388 if (OSDecrementAtomic((UInt32
*)&device_object
->ref_count
) == 1) {
389 if (device_object
->device_handle
!= (device_port_t
) NULL
) {
390 device_close(device_object
->device_handle
);
392 zfree(device_pager_zone
, (vm_offset_t
) device_object
);
398 device_pager_data_initialize(
399 memory_object_t mem_obj
,
400 memory_object_offset_t offset
,
407 device_pager_data_unlock(
408 memory_object_t mem_obj
,
409 memory_object_offset_t offset
,
411 vm_prot_t desired_access
)
416 device_pager_terminate(
417 memory_object_t mem_obj
)
428 device_pager_synchronize(
429 memory_object_t mem_obj
,
430 memory_object_offset_t offset
,
432 vm_sync_t sync_flags
)
434 device_pager_t device_object
;
436 device_object
= device_pager_lookup(mem_obj
);
438 memory_object_synchronize_completed(
439 device_object
->control_handle
, offset
, length
);
449 memory_object_t mem_obj
)
460 device_object_create()
462 register device_pager_t device_object
;
464 device_object
= (struct device_pager
*) zalloc(device_pager_zone
);
465 if (device_object
== DEVICE_PAGER_NULL
)
466 return(DEVICE_PAGER_NULL
);
467 device_object
->pager
= &device_pager_workaround
;
468 device_object
->pager_ikot
= IKOT_MEMORY_OBJECT
;
469 device_object
->ref_count
= 1;
470 device_object
->control_handle
= MEMORY_OBJECT_CONTROL_NULL
;
473 return(device_object
);