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

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

unix.superglobalmegacorp.com

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