Annotation of Gnu-Mach/device/dev_pager.c, revision 1.1.1.5

1.1.1.2   root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1993-1989 Carnegie Mellon University
                      4:  * All Rights Reserved.
1.1.1.2   root        5:  *
1.1       root        6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
1.1.1.2   root       11:  *
1.1       root       12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1.1.1.2   root       15:  *
1.1       root       16:  * Carnegie Mellon requests users of this software to return to
1.1.1.2   root       17:  *
1.1       root       18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
1.1.1.2   root       22:  *
1.1       root       23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  *     Author: David B. Golub, Carnegie Mellon University
                     28:  *     Date:   3/89
                     29:  *
                     30:  *     Device pager.
                     31:  */
1.1.1.3   root       32: 
                     33: #include <string.h>
1.1       root       34: 
                     35: #include <mach/boolean.h>
                     36: #include <mach/port.h>
                     37: #include <mach/message.h>
                     38: #include <mach/std_types.h>
                     39: #include <mach/mach_types.h>
                     40: 
                     41: #include <ipc/ipc_port.h>
                     42: #include <ipc/ipc_space.h>
                     43: 
1.1.1.3   root       44: #include <kern/debug.h>
                     45: #include <kern/printf.h>
1.1       root       46: #include <kern/queue.h>
1.1.1.3   root       47: #include <kern/slab.h>
1.1       root       48: 
                     49: #include <vm/vm_page.h>
                     50: #include <vm/vm_kern.h>
1.1.1.3   root       51: #include <vm/vm_user.h>
1.1       root       52: 
                     53: #include <device/device_types.h>
                     54: #include <device/ds_routines.h>
                     55: #include <device/dev_hdr.h>
                     56: #include <device/io_req.h>
1.1.1.3   root       57: #include <device/memory_object_reply.user.h>
1.1.1.4   root       58: #include <device/dev_pager.h>
                     59: #include <device/blkio.h>
1.1       root       60: 
                     61: /*
                     62:  *     The device pager routines are called directly from the message
                     63:  *     system (via mach_msg), and thus run in the kernel-internal
                     64:  *     environment.  All ports are in internal form (ipc_port_t),
                     65:  *     and must be correctly reference-counted in order to be saved
                     66:  *     in other data structures.  Kernel routines may be called
                     67:  *     directly.  Kernel types are used for data objects (tasks,
                     68:  *     memory objects, ports).  The only IPC routines that may be
                     69:  *     called are ones that masquerade as the kernel task (via
                     70:  *     msg_send_from_kernel).
                     71:  *
                     72:  *     Port rights and references are maintained as follows:
                     73:  *             Memory object port:
                     74:  *                     The device_pager task has all rights.
                     75:  *             Memory object control port:
                     76:  *                     The device_pager task has only send rights.
                     77:  *             Memory object name port:
                     78:  *                     The device_pager task has only send rights.
                     79:  *                     The name port is not even recorded.
                     80:  *     Regardless how the object is created, the control and name
                     81:  *     ports are created by the kernel and passed through the memory
                     82:  *     management interface.
                     83:  *
                     84:  *     The device_pager assumes that access to its memory objects
                     85:  *     will not be propagated to more that one host, and therefore
                     86:  *     provides no consistency guarantees beyond those made by the
                     87:  *     kernel.
                     88:  *
                     89:  *     In the event that more than one host attempts to use a device
                     90:  *     memory object, the device_pager will only record the last set
                     91:  *     of port names.  [This can happen with only one host if a new
                     92:  *     mapping is being established while termination of all previous
                     93:  *     mappings is taking place.]  Currently, the device_pager assumes
                     94:  *     that its clients adhere to the initialization and termination
                     95:  *     protocols in the memory management interface; otherwise, port
                     96:  *     rights or out-of-line memory from erroneous messages may be
                     97:  *     allowed to accumulate.
                     98:  *
                     99:  *     [The phrase "currently" has been used above to denote aspects of
                    100:  *     the implementation that could be altered without changing the rest
                    101:  *     of the basic documentation.]
                    102:  */
                    103: 
                    104: /*
                    105:  * Basic device pager structure.
                    106:  */
                    107: struct dev_pager {
                    108:        decl_simple_lock_data(, lock)   /* lock for reference count */
                    109:        int             ref_count;      /* reference count */
                    110:        int             client_count;   /* How many memory_object_create
                    111:                                         * calls have we received */
                    112:        ipc_port_t      pager;          /* pager port */
                    113:        ipc_port_t      pager_request;  /* Known request port */
                    114:        ipc_port_t      pager_name;     /* Known name port */
                    115:        mach_device_t   device;         /* Device handle */
                    116:        int             type;           /* to distinguish */
                    117: #define DEV_PAGER_TYPE 0
                    118: #define CHAR_PAGER_TYPE        1
                    119:        /* char pager specifics */
                    120:        int             prot;
                    121:        vm_size_t       size;
                    122: };
                    123: typedef struct dev_pager *dev_pager_t;
                    124: #define        DEV_PAGER_NULL  ((dev_pager_t)0)
                    125: 
                    126: 
1.1.1.3   root      127: struct kmem_cache      dev_pager_cache;
1.1       root      128: 
1.1.1.3   root      129: void dev_pager_reference(dev_pager_t   ds)
1.1       root      130: {
                    131:        simple_lock(&ds->lock);
                    132:        ds->ref_count++;
                    133:        simple_unlock(&ds->lock);
                    134: }
                    135: 
1.1.1.3   root      136: void dev_pager_deallocate(dev_pager_t  ds)
1.1       root      137: {
                    138:        simple_lock(&ds->lock);
                    139:        if (--ds->ref_count > 0) {
                    140:            simple_unlock(&ds->lock);
                    141:            return;
                    142:        }
                    143: 
                    144:        simple_unlock(&ds->lock);
1.1.1.3   root      145:        kmem_cache_free(&dev_pager_cache, (vm_offset_t)ds);
1.1       root      146: }
                    147: 
                    148: /*
                    149:  * A hash table of ports for device_pager backed objects.
                    150:  */
                    151: 
                    152: #define        DEV_PAGER_HASH_COUNT            127
                    153: 
                    154: struct dev_pager_entry {
                    155:        queue_chain_t   links;
                    156:        ipc_port_t      name;
                    157:        dev_pager_t     pager_rec;
                    158: };
                    159: typedef struct dev_pager_entry *dev_pager_entry_t;
                    160: 
                    161: queue_head_t   dev_pager_hashtable[DEV_PAGER_HASH_COUNT];
1.1.1.3   root      162: struct kmem_cache      dev_pager_hash_cache;
1.1       root      163: decl_simple_lock_data(,
                    164:                dev_pager_hash_lock)
                    165: 
                    166: #define        dev_pager_hash(name_port) \
1.1.1.3   root      167:                (((vm_offset_t)(name_port) & 0xffffff) % DEV_PAGER_HASH_COUNT)
1.1       root      168: 
                    169: void dev_pager_hash_init(void)
                    170: {
1.1.1.3   root      171:        int             i;
                    172:        vm_size_t       size;
1.1       root      173: 
                    174:        size = sizeof(struct dev_pager_entry);
1.1.1.3   root      175:        kmem_cache_init(&dev_pager_hash_cache, "dev_pager_entry", size, 0,
1.1.1.5 ! root      176:                        NULL, 0);
1.1       root      177:        for (i = 0; i < DEV_PAGER_HASH_COUNT; i++)
                    178:            queue_init(&dev_pager_hashtable[i]);
                    179:        simple_lock_init(&dev_pager_hash_lock);
                    180: }
                    181: 
                    182: void dev_pager_hash_insert(
1.1.1.4   root      183:        const ipc_port_t        name_port,
                    184:        const dev_pager_t       rec)
1.1       root      185: {
1.1.1.3   root      186:        dev_pager_entry_t new_entry;
1.1       root      187: 
1.1.1.3   root      188:        new_entry = (dev_pager_entry_t) kmem_cache_alloc(&dev_pager_hash_cache);
1.1       root      189:        new_entry->name = name_port;
                    190:        new_entry->pager_rec = rec;
                    191: 
                    192:        simple_lock(&dev_pager_hash_lock);
                    193:        queue_enter(&dev_pager_hashtable[dev_pager_hash(name_port)],
                    194:                        new_entry, dev_pager_entry_t, links);
                    195:        simple_unlock(&dev_pager_hash_lock);
                    196: }
                    197: 
1.1.1.4   root      198: void dev_pager_hash_delete(const ipc_port_t name_port)
1.1       root      199: {
1.1.1.3   root      200:        queue_t                 bucket;
                    201:        dev_pager_entry_t       entry;
1.1       root      202: 
                    203:        bucket = &dev_pager_hashtable[dev_pager_hash(name_port)];
                    204: 
                    205:        simple_lock(&dev_pager_hash_lock);
                    206:        for (entry = (dev_pager_entry_t)queue_first(bucket);
                    207:             !queue_end(bucket, &entry->links);
                    208:             entry = (dev_pager_entry_t)queue_next(&entry->links)) {
                    209:            if (entry->name == name_port) {
                    210:                queue_remove(bucket, entry, dev_pager_entry_t, links);
                    211:                break;
                    212:            }
                    213:        }
                    214:        simple_unlock(&dev_pager_hash_lock);
                    215:        if (entry)
1.1.1.3   root      216:            kmem_cache_free(&dev_pager_hash_cache, (vm_offset_t)entry);
1.1       root      217: }
                    218: 
1.1.1.4   root      219: dev_pager_t dev_pager_hash_lookup(const ipc_port_t name_port)
1.1       root      220: {
1.1.1.3   root      221:        queue_t                 bucket;
                    222:        dev_pager_entry_t       entry;
                    223:        dev_pager_t             pager;
1.1       root      224: 
                    225:        bucket = &dev_pager_hashtable[dev_pager_hash(name_port)];
                    226: 
                    227:        simple_lock(&dev_pager_hash_lock);
                    228:        for (entry = (dev_pager_entry_t)queue_first(bucket);
                    229:             !queue_end(bucket, &entry->links);
                    230:             entry = (dev_pager_entry_t)queue_next(&entry->links)) {
                    231:            if (entry->name == name_port) {
                    232:                pager = entry->pager_rec;
                    233:                dev_pager_reference(pager);
                    234:                simple_unlock(&dev_pager_hash_lock);
                    235:                return (pager);
                    236:            }
                    237:        }
                    238:        simple_unlock(&dev_pager_hash_lock);
                    239:        return (DEV_PAGER_NULL);
                    240: }
                    241: 
                    242: kern_return_t  device_pager_setup(
1.1.1.4   root      243:        const mach_device_t     device,
                    244:        int                     prot,
                    245:        vm_offset_t             offset,
                    246:        vm_size_t               size,
                    247:        mach_port_t             *pager)
1.1       root      248: {
1.1.1.3   root      249:        dev_pager_t     d;
1.1       root      250: 
                    251:        /*
                    252:         *      Verify the device is indeed mappable
                    253:         */
                    254:        if (!device->dev_ops->d_mmap || (device->dev_ops->d_mmap == nomap))
                    255:                return (D_INVALID_OPERATION);
                    256: 
                    257:        /*
                    258:         *      Allocate a structure to hold the arguments
                    259:         *      and port to represent this object.
                    260:         */
                    261: 
                    262:        d = dev_pager_hash_lookup((ipc_port_t)device);  /* HACK */
                    263:        if (d != DEV_PAGER_NULL) {
                    264:                *pager = (mach_port_t) ipc_port_make_send(d->pager);
                    265:                dev_pager_deallocate(d);
                    266:                return (D_SUCCESS);
                    267:        }
                    268: 
1.1.1.3   root      269:        d = (dev_pager_t) kmem_cache_alloc(&dev_pager_cache);
1.1       root      270:        if (d == DEV_PAGER_NULL)
                    271:                return (KERN_RESOURCE_SHORTAGE);
                    272: 
                    273:        simple_lock_init(&d->lock);
                    274:        d->ref_count = 1;
                    275: 
                    276:        /*
                    277:         * Allocate the pager port.
                    278:         */
                    279:        d->pager = ipc_port_alloc_kernel();
                    280:        if (d->pager == IP_NULL) {
                    281:                dev_pager_deallocate(d);
                    282:                return (KERN_RESOURCE_SHORTAGE);
                    283:        }
                    284: 
                    285:        d->client_count = 0;
                    286:        d->pager_request = IP_NULL;
                    287:        d->pager_name = IP_NULL;
                    288:        d->device = device;
                    289:        mach_device_reference(device);
                    290:        d->prot = prot;
                    291:        d->size = round_page(size);
                    292:        if (device->dev_ops->d_mmap == block_io_mmap) {
                    293:                d->type = DEV_PAGER_TYPE;
                    294:        } else {
                    295:                d->type = CHAR_PAGER_TYPE;
                    296:        }
                    297: 
                    298:        dev_pager_hash_insert(d->pager, d);
                    299:        dev_pager_hash_insert((ipc_port_t)device, d);   /* HACK */
                    300: 
                    301:        *pager = (mach_port_t) ipc_port_make_send(d->pager);
                    302:        return (KERN_SUCCESS);
                    303: }
                    304: 
                    305: /*
                    306:  *     Routine:        device_pager_release
                    307:  *     Purpose:
                    308:  *             Relinquish any references or rights that were
                    309:  *             associated with the result of a call to
                    310:  *             device_pager_setup.
                    311:  */
                    312: void   device_pager_release(memory_object_t    object)
                    313: {
                    314:        if (MACH_PORT_VALID(object))
                    315:                ipc_port_release_send((ipc_port_t) object);
                    316: }
                    317: 
                    318: boolean_t      device_pager_debug = FALSE;
                    319: 
                    320: kern_return_t  device_pager_data_request(
1.1.1.4   root      321:        const ipc_port_t        pager,
                    322:        const ipc_port_t        pager_request,
                    323:        vm_offset_t             offset,
                    324:        vm_size_t               length,
                    325:        vm_prot_t               protection_required)
1.1       root      326: {
1.1.1.3   root      327:        dev_pager_t     ds;
1.1       root      328: 
                    329:        if (device_pager_debug)
1.1.1.3   root      330:                printf("(device_pager)data_request: pager=%p, offset=0x%lx, length=0x%x\n",
1.1       root      331:                        pager, offset, length);
                    332: 
1.1.1.4   root      333:        ds = dev_pager_hash_lookup(pager);
1.1       root      334:        if (ds == DEV_PAGER_NULL)
                    335:                panic("(device_pager)data_request: lookup failed");
                    336: 
                    337:        if (ds->pager_request != pager_request)
                    338:                panic("(device_pager)data_request: bad pager_request");
                    339: 
                    340:        if (ds->type == CHAR_PAGER_TYPE) {
1.1.1.3   root      341:            vm_object_t                 object;
1.1       root      342: 
                    343:            object = vm_object_lookup(pager_request);
                    344:            if (object == VM_OBJECT_NULL) {
                    345:                    (void) r_memory_object_data_error(pager_request,
                    346:                                                      offset, length,
                    347:                                                      KERN_FAILURE);
                    348:                    dev_pager_deallocate(ds);
                    349:                    return (KERN_SUCCESS);
                    350:            }
                    351: 
                    352:            vm_object_page_map(object,
                    353:                               offset, length,
1.1.1.4   root      354:                               device_map_page, (void *)ds);
1.1       root      355: 
                    356:            vm_object_deallocate(object);
                    357:        }
                    358:        else {
1.1.1.3   root      359:            io_req_t                    ior;
                    360:            mach_device_t               device;
1.1       root      361:            io_return_t                 result;
                    362: 
                    363:            panic("(device_pager)data_request: dev pager");
1.1.1.2   root      364: 
1.1       root      365:            device = ds->device;
                    366:            mach_device_reference(device);
                    367:            dev_pager_deallocate(ds);
1.1.1.2   root      368: 
1.1       root      369:            /*
                    370:             * Package the read for the device driver.
                    371:             */
                    372:            io_req_alloc(ior, 0);
1.1.1.2   root      373: 
1.1       root      374:            ior->io_device      = device;
                    375:            ior->io_unit        = device->dev_number;
                    376:            ior->io_op          = IO_READ | IO_CALL;
                    377:            ior->io_mode        = 0;
                    378:            ior->io_recnum      = offset / device->bsize;
                    379:            ior->io_data        = 0;            /* driver must allocate */
                    380:            ior->io_count       = length;
                    381:            ior->io_alloc_size  = 0;            /* no data allocated yet */
                    382:            ior->io_residual    = 0;
                    383:            ior->io_error       = 0;
                    384:            ior->io_done        = device_pager_data_request_done;
                    385:            ior->io_reply_port  = pager_request;
                    386:            ior->io_reply_port_type = MACH_MSG_TYPE_PORT_SEND;
1.1.1.2   root      387: 
1.1       root      388:            result = (*device->dev_ops->d_read)(device->dev_number, ior);
                    389:            if (result == D_IO_QUEUED)
                    390:                return (KERN_SUCCESS);
1.1.1.2   root      391: 
1.1       root      392:            /*
                    393:             * Return by queuing IOR for io_done thread, to reply in
                    394:             * correct environment (kernel).
                    395:             */
                    396:            ior->io_error = result;
                    397:            iodone(ior);
                    398:        }
                    399: 
                    400:        dev_pager_deallocate(ds);
                    401: 
                    402:        return (KERN_SUCCESS);
                    403: }
                    404: 
                    405: /*
                    406:  * Always called by io_done thread.
                    407:  */
1.1.1.3   root      408: boolean_t device_pager_data_request_done(io_req_t      ior)
1.1       root      409: {
                    410:        vm_offset_t     start_alloc, end_alloc;
                    411:        vm_size_t       size_read;
                    412: 
                    413:        if (ior->io_error == D_SUCCESS) {
                    414:            size_read = ior->io_count;
                    415:            if (ior->io_residual) {
                    416:                if (device_pager_debug)
1.1.1.3   root      417:                    printf("(device_pager)data_request_done: r: 0x%lx\n", ior->io_residual);
                    418:                memset((&ior->io_data[ior->io_count - ior->io_residual]), 0, 
1.1.1.4   root      419:                      (size_t) ior->io_residual);
1.1       root      420:            }
                    421:        } else {
                    422:            size_read = ior->io_count - ior->io_residual;
                    423:        }
                    424: 
1.1.1.4   root      425:        start_alloc = trunc_page(ior->io_data);
1.1       root      426:        end_alloc   = start_alloc + round_page(ior->io_alloc_size);
                    427: 
                    428:        if (ior->io_error == D_SUCCESS) {
                    429:            vm_map_copy_t copy;
                    430:            kern_return_t kr;
                    431: 
                    432:            kr = vm_map_copyin(kernel_map, (vm_offset_t)ior->io_data,
                    433:                                size_read, TRUE, &copy);
                    434:            if (kr != KERN_SUCCESS)
                    435:                panic("device_pager_data_request_done");
                    436: 
                    437:            (void) r_memory_object_data_provided(
                    438:                                        ior->io_reply_port,
                    439:                                        ior->io_recnum * ior->io_device->bsize,
                    440:                                        (vm_offset_t)copy,
                    441:                                        size_read,
                    442:                                        VM_PROT_NONE);
                    443:        }
                    444:        else {
                    445:            (void) r_memory_object_data_error(
                    446:                                        ior->io_reply_port,
                    447:                                        ior->io_recnum * ior->io_device->bsize,
                    448:                                        (vm_size_t)ior->io_count,
                    449:                                        ior->io_error);
                    450:        }
                    451: 
                    452:        (void)vm_deallocate(kernel_map,
                    453:                            start_alloc,
                    454:                            end_alloc - start_alloc);
                    455:        mach_device_deallocate(ior->io_device);
                    456:        return (TRUE);
                    457: }
                    458: 
                    459: kern_return_t device_pager_data_write(
1.1.1.4   root      460:        const ipc_port_t        pager,
                    461:        const ipc_port_t        pager_request,
1.1.1.3   root      462:        vm_offset_t             offset,
                    463:        pointer_t               addr,
1.1       root      464:        vm_size_t               data_count)
                    465: {
1.1.1.3   root      466:        dev_pager_t             ds;
                    467:        mach_device_t           device;
                    468:        io_req_t                ior;
1.1       root      469:        kern_return_t           result;
                    470: 
                    471:        panic("(device_pager)data_write: called");
                    472: 
1.1.1.4   root      473:        ds = dev_pager_hash_lookup(pager);
1.1       root      474:        if (ds == DEV_PAGER_NULL)
                    475:                panic("(device_pager)data_write: lookup failed");
                    476: 
                    477:        if (ds->pager_request != pager_request)
                    478:                panic("(device_pager)data_write: bad pager_request");
                    479: 
                    480:        if (ds->type == CHAR_PAGER_TYPE)
                    481:                panic("(device_pager)data_write: char pager");
                    482: 
                    483:        device = ds->device;
                    484:        mach_device_reference(device);
                    485:        dev_pager_deallocate(ds);
                    486: 
                    487:        /*
                    488:         * Package the write request for the device driver.
                    489:         */
                    490:        io_req_alloc(ior, data_count);
                    491: 
                    492:        ior->io_device          = device;
                    493:        ior->io_unit            = device->dev_number;
                    494:        ior->io_op              = IO_WRITE | IO_CALL;
                    495:        ior->io_mode            = 0;
                    496:        ior->io_recnum          = offset / device->bsize;
                    497:        ior->io_data            = (io_buf_ptr_t)addr;
                    498:        ior->io_count           = data_count;
                    499:        ior->io_alloc_size      = data_count;   /* amount to deallocate */
                    500:        ior->io_residual        = 0;
                    501:        ior->io_error           = 0;
                    502:        ior->io_done            = device_pager_data_write_done;
                    503:        ior->io_reply_port      = IP_NULL;
                    504: 
                    505:        result = (*device->dev_ops->d_write)(device->dev_number, ior);
                    506: 
                    507:        if (result != D_IO_QUEUED) {
                    508:            device_write_dealloc(ior);
                    509:            io_req_free((vm_offset_t)ior);
                    510:            mach_device_deallocate(device);
                    511:        }
                    512: 
                    513:        return (KERN_SUCCESS);
                    514: }
                    515: 
1.1.1.4   root      516: boolean_t device_pager_data_write_done(io_req_t ior)
1.1       root      517: {
                    518:        device_write_dealloc(ior);
                    519:        mach_device_deallocate(ior->io_device);
                    520: 
                    521:        return (TRUE);
                    522: }
                    523: 
                    524: kern_return_t device_pager_copy(
1.1.1.4   root      525:        const ipc_port_t        pager,
                    526:        const ipc_port_t        pager_request,
1.1.1.3   root      527:        vm_offset_t             offset,
                    528:        vm_size_t               length,
1.1.1.4   root      529:        const ipc_port_t        new_pager)
1.1       root      530: {
                    531:        panic("(device_pager)copy: called");
                    532: }
                    533: 
                    534: kern_return_t
                    535: device_pager_supply_completed(
1.1.1.4   root      536:        const ipc_port_t pager,
                    537:        const ipc_port_t pager_request,
1.1       root      538:        vm_offset_t offset,
                    539:        vm_size_t length,
                    540:        kern_return_t result,
                    541:        vm_offset_t error_offset)
                    542: {
                    543:        panic("(device_pager)supply_completed: called");
                    544: }
                    545: 
                    546: kern_return_t
                    547: device_pager_data_return(
1.1.1.4   root      548:        const ipc_port_t        pager,
                    549:        const ipc_port_t        pager_request,
1.1       root      550:        vm_offset_t             offset,
1.1.1.3   root      551:        pointer_t               addr,
1.1       root      552:        vm_size_t               data_cnt,
                    553:        boolean_t               dirty,
                    554:        boolean_t               kernel_copy)
                    555: {
                    556:        panic("(device_pager)data_return: called");
                    557: }
                    558: 
                    559: kern_return_t
                    560: device_pager_change_completed(
1.1.1.4   root      561:        const ipc_port_t pager,
1.1       root      562:        boolean_t may_cache,
                    563:        memory_object_copy_strategy_t copy_strategy)
                    564: {
                    565:        panic("(device_pager)change_completed: called");
                    566: }
                    567: 
                    568: /*
                    569:  *     The mapping function takes a byte offset, but returns
                    570:  *     a machine-dependent page frame number.  We convert
                    571:  *     that into something that the pmap module will
                    572:  *     accept later.
                    573:  */
                    574: vm_offset_t device_map_page(
                    575:        void            *dsp,
                    576:        vm_offset_t     offset)
                    577: {
1.1.1.3   root      578:        dev_pager_t     ds = (dev_pager_t) dsp;
1.1       root      579: 
                    580:        return pmap_phys_address(
                    581:                   (*(ds->device->dev_ops->d_mmap))
                    582:                        (ds->device->dev_number, offset, ds->prot));
                    583: }
                    584: 
                    585: kern_return_t device_pager_init_pager(
1.1.1.4   root      586:        const ipc_port_t        pager,
                    587:        const ipc_port_t        pager_request,
                    588:        const ipc_port_t        pager_name,
                    589:        vm_size_t               pager_page_size)
1.1       root      590: {
1.1.1.3   root      591:        dev_pager_t     ds;
1.1       root      592: 
                    593:        if (device_pager_debug)
1.1.1.3   root      594:                printf("(device_pager)init: pager=%p, request=%p, name=%p\n",
1.1       root      595:                       pager, pager_request, pager_name);
                    596: 
                    597:        assert(pager_page_size == PAGE_SIZE);
                    598:        assert(IP_VALID(pager_request));
                    599:        assert(IP_VALID(pager_name));
                    600: 
                    601:        ds = dev_pager_hash_lookup(pager);
                    602:        assert(ds != DEV_PAGER_NULL);
                    603: 
                    604:        assert(ds->client_count == 0);
                    605:        assert(ds->pager_request == IP_NULL);
                    606:        assert(ds->pager_name == IP_NULL);
                    607: 
                    608:        ds->client_count = 1;
                    609: 
                    610:        /*
                    611:         * We save the send rights for the request and name ports.
                    612:         */
                    613: 
                    614:        ds->pager_request = pager_request;
                    615:        ds->pager_name = pager_name;
                    616: 
                    617:        if (ds->type == CHAR_PAGER_TYPE) {
                    618:            /*
                    619:             * Reply that the object is ready
                    620:             */
                    621:            (void) r_memory_object_set_attributes(pager_request,
                    622:                                                TRUE,   /* ready */
                    623:                                                FALSE,  /* do not cache */
                    624:                                                MEMORY_OBJECT_COPY_NONE);
                    625:        } else {
                    626:            (void) r_memory_object_set_attributes(pager_request,
                    627:                                                TRUE,   /* ready */
                    628:                                                TRUE,   /* cache */
                    629:                                                MEMORY_OBJECT_COPY_DELAY);
                    630:        }
                    631: 
                    632:        dev_pager_deallocate(ds);
                    633:        return (KERN_SUCCESS);
                    634: }
                    635: 
                    636: kern_return_t device_pager_terminate(
1.1.1.4   root      637:        const ipc_port_t        pager,
                    638:        const ipc_port_t        pager_request,
                    639:        const ipc_port_t        pager_name)
1.1       root      640: {
1.1.1.3   root      641:        dev_pager_t     ds;
1.1       root      642: 
                    643:        assert(IP_VALID(pager_request));
                    644:        assert(IP_VALID(pager_name));
                    645: 
                    646:        ds = dev_pager_hash_lookup(pager);
                    647:        assert(ds != DEV_PAGER_NULL);
                    648: 
                    649:        assert(ds->client_count == 1);
                    650:        assert(ds->pager_request == pager_request);
                    651:        assert(ds->pager_name == pager_name);
                    652: 
                    653:        dev_pager_hash_delete(ds->pager);
                    654:        dev_pager_hash_delete((ipc_port_t)ds->device);  /* HACK */
                    655:        mach_device_deallocate(ds->device);
                    656: 
                    657:        /* release the send rights we have saved from the init call */
                    658: 
                    659:        ipc_port_release_send(pager_request);
                    660:        ipc_port_release_send(pager_name);
                    661: 
                    662:        /* release the naked receive rights we just acquired */
                    663: 
                    664:        ipc_port_release_receive(pager_request);
                    665:        ipc_port_release_receive(pager_name);
                    666: 
                    667:        /* release the kernel's receive right for the pager port */
                    668: 
                    669:        ipc_port_dealloc_kernel(pager);
                    670: 
                    671:        /* once for ref from lookup, once to make it go away */
                    672:        dev_pager_deallocate(ds);
                    673:        dev_pager_deallocate(ds);
                    674: 
                    675:        return (KERN_SUCCESS);
                    676: }
                    677: 
                    678: kern_return_t device_pager_data_unlock(
1.1.1.4   root      679:        const ipc_port_t memory_object,
                    680:        const ipc_port_t memory_control_port,
1.1       root      681:        vm_offset_t offset,
                    682:        vm_size_t length,
                    683:        vm_prot_t desired_access)
                    684: {
                    685:        panic("(device_pager)data_unlock: called");
                    686:        return (KERN_FAILURE);
                    687: }
                    688: 
                    689: kern_return_t device_pager_lock_completed(
1.1.1.4   root      690:        const ipc_port_t        memory_object,
                    691:        const ipc_port_t        pager_request_port,
                    692:        vm_offset_t             offset,
                    693:        vm_size_t               length)
1.1       root      694: {
                    695:        panic("(device_pager)lock_completed: called");
                    696:        return (KERN_FAILURE);
                    697: }
                    698: 
                    699: void device_pager_init(void)
                    700: {
1.1.1.3   root      701:        vm_size_t       size;
1.1       root      702: 
                    703:        /*
1.1.1.3   root      704:         * Initialize cache of paging structures.
1.1       root      705:         */
                    706:        size = sizeof(struct dev_pager);
1.1.1.3   root      707:        kmem_cache_init(&dev_pager_cache, "dev_pager", size, 0,
1.1.1.5 ! root      708:                        NULL, 0);
1.1       root      709: 
                    710:        /*
                    711:         *      Initialize the name port hashing stuff.
                    712:         */
                    713:        dev_pager_hash_init();
                    714: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.