Annotation of XNU/osfmk/i386/AT386/himem.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      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.
                     11:  * 
                     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
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_FREE_COPYRIGHT@
                     24:  */
                     25: /*
                     26:  * HISTORY
                     27:  * 
                     28:  * Revision 1.1.1.1  1998/09/22 21:05:38  wsanchez
                     29:  * Import of Mac OS X kernel (~semeria)
                     30:  *
                     31:  * Revision 1.1.1.1  1998/03/07 02:25:39  wsanchez
                     32:  * Import of OSF Mach kernel (~mburg)
                     33:  *
                     34:  * Revision 1.3.17.7  1995/08/21  20:33:13  devrcs
                     35:  *     ri-osc CR1547:  Fix himem buffer translation to cope with non
                     36:  *     page-aligned addresses.
                     37:  *     [1995/08/08  16:51:58  bolinger]
                     38:  *
                     39:  * Revision 1.3.17.6  1995/02/24  15:51:12  alanl
                     40:  *     DIPC:  Merge from nmk17b2 to nmk18b8.
                     41:  *     Notes:  lock package cleanup.
                     42:  *     [95/01/23            alanl]
                     43:  *     [95/02/24            alanl]
                     44:  * 
                     45:  * Revision 1.3.17.5  1995/01/26  22:14:52  ezf
                     46:  *     removed extraneous CMU CR
                     47:  *     [1995/01/26  20:24:45  ezf]
                     48:  * 
                     49:  * Revision 1.3.17.4  1995/01/10  04:51:04  devrcs
                     50:  *     mk6 CR801 - merge up from nmk18b4 to nmk18b7
                     51:  *     * Rev 1.3.17.3  1994/10/21  18:41:39  joe
                     52:  *       Added ETAP support
                     53:  *     [1994/12/09  20:37:48  dwm]
                     54:  * 
                     55:  *     mk6 CR764 - s/spinlock/simple_lock/ (name change only)
                     56:  *     [1994/11/10  05:25:33  dwm]
                     57:  * 
                     58:  *     mk6 CR668 - 1.3b26 merge
                     59:  *     * Revision 1.3.5.8  1994/05/06  18:44:06  tmt
                     60:  *     Fix prototypes for new device signatures.
                     61:  *     * Revision 1.3.5.6  1993/12/10  18:08:15  jeffc
                     62:  *     CR10305 -- locking bug in himem_reserve(): change call to
                     63:  *     vm_page_free to VM_PAGE_FREE.
                     64:  *     * Revision 1.3.5.5  1993/11/19  17:56:58  jeffc
                     65:  *     CR10125 -- Uninitialized lock in himem_convert. Add himem_init
                     66:  *     CR9461 -- Locking bug in himem_convert - must retake lock after
                     67:  *     thread_sleep.
                     68:  *     * End1.3merge
                     69:  *     [1994/11/04  09:07:39  dwm]
                     70:  * 
                     71:  * Revision 1.3.17.1  1994/06/14  03:04:20  toshi
                     72:  *     Merge MK6 and NMK17
                     73:  *     [1994/06/14  01:06:55  toshi]
                     74:  * 
                     75:  * Revision 1.3.15.2  1994/06/08  21:14:24  dswartz
                     76:  *     Preemption merge.
                     77:  *     [1994/06/08  21:12:29  dswartz]
                     78:  * 
                     79:  * Revision 1.3.15.1  1994/05/19  20:30:23  dwm
                     80:  *     mk6 CR 74.  Locking bug in himem_reserve(): use VM_PAGE_FREE.
                     81:  *     mk6 CR 9461.  Init hil_lock used by himem_convert();
                     82:  *     retake lock after sleeping.
                     83:  *     [1994/05/19  20:30:07  dwm]
                     84:  * 
                     85:  * Revision 1.3.11.1  1994/02/09  07:27:07  bernadat
                     86:  *     Added himem_init() for module initialization.
                     87:  *     [93/08/12            paire]
                     88:  * 
                     89:  *     Take back hil_lock lock on return from thread_sleep()
                     90:  *     [93/07/16            bernadat]
                     91:  * 
                     92:  *     Add vm_page_gobble() calls where needed. (dwm bug #542)
                     93:  *     Change from NORMA_MK14.6 [1993/02/09  22:24:00  dwm]
                     94:  *     [93/07/16            bernadat]
                     95:  *     [94/02/08            bernadat]
                     96:  * 
                     97:  * Revision 1.3.5.4  1993/08/09  19:37:19  dswartz
                     98:  *     Add ANSI prototypes - CR#9523
                     99:  *     [1993/08/06  17:50:02  dswartz]
                    100:  * 
                    101:  * Revision 1.3.5.3  1993/08/03  22:21:26  bernard
                    102:  *     CR#9523 - ANSI prototype fixes.
                    103:  *     [1993/08/03  15:34:10  bernard]
                    104:  * 
                    105:  * Revision 1.3.5.2  1993/06/09  02:25:18  gm
                    106:  *     CR9157 - Find himem.h in the right place.
                    107:  *     [1993/05/28  17:27:23  brezak]
                    108:  * 
                    109:  * Revision 1.3  1993/04/19  16:09:46  devrcs
                    110:  *     make endif tags ansi compliant/include files
                    111:  *     [1993/02/20  21:46:44  david]
                    112:  * 
                    113:  *     Print an appropriate message when going out of HIMEM pages.
                    114:  *     [93/01/26            bernadat]
                    115:  * 
                    116:  * Revision 1.2  1992/11/25  01:07:08  robert
                    117:  *     integrate changes below for norma_14
                    118:  *     [1992/11/13  19:28:44  robert]
                    119:  * 
                    120:  * $EndLog$
                    121:  */
                    122: 
                    123: /*
                    124:  * support of memory above 16 Megs for DMA limited to memory
                    125:  * below 16 Megs. Copies high memory lo low memory before DMA
                    126:  * write operations and does the reverse at completion time for
                    127:  * DMA read operations
                    128:  */
                    129: 
                    130: #include <cpus.h>
                    131: #include <platforms.h>
                    132: #include <kern/lock.h>
                    133: #include <mach/vm_param.h>
                    134: #include <vm/vm_page.h>
                    135: #include <i386/AT386/himem.h>
                    136: #include <kern/kalloc.h>
                    137: #include <kern/spl.h>
                    138: #include <mach/boolean.h>
                    139: #include <kern/misc_protos.h>
                    140: #include <i386/AT386/misc_protos.h>
                    141: 
                    142: hil_t          hil_head;
                    143: decl_simple_lock_data(,hil_lock)
                    144: 
                    145: #if    HIMEM_STATS
                    146: int himem_request;     /* number of requests */
                    147: int himem_used;                /* number of times used */
                    148: #endif /* HIMEM_STATS */
                    149: 
                    150: void
                    151: himem_init(
                    152:        void)
                    153: {
                    154:        simple_lock_init(&hil_lock, ETAP_VM_HIMEM);
                    155: }
                    156: 
                    157: /* 
                    158:  * Called by drivers, this indicates himem that this driver might need
                    159:  * to allocate as many as npages pages in a single I/O DMA transfer
                    160:  */
                    161: 
                    162: void
                    163: himem_reserve(
                    164:        int             npages)
                    165: {
                    166:        register                i = 0;
                    167:        vm_page_t               free_head = VM_PAGE_NULL;
                    168:        vm_page_t               low;
                    169:        hil_t                   hil;
                    170:        spl_t                   ipl;
                    171:        extern vm_offset_t      avail_end;
                    172: 
                    173:        if (avail_end <= HIGH_MEM)
                    174:                return;
                    175:        hil = (hil_t)kalloc(npages*sizeof(struct himem_link));
                    176:        if (hil == (hil_t)0) 
                    177:                panic("himem_reserve: kalloc failed\n");
                    178: 
                    179:        for (i=0; i < npages-1; i++)
                    180:                (hil+i)->next = hil+i+1;
                    181: 
                    182:        /*
                    183:         * This is the only way of getting low physical pages 
                    184:         * wtithout changing VM internals
                    185:         */
                    186:        for (i=0; i != npages;) {
                    187:                if ((low = vm_page_grab()) == VM_PAGE_NULL)
                    188:                        panic("No low memory pages for himem\n");
                    189:                vm_page_gobble(low); /* mark as consumed internally */
                    190:                if (_high_mem_page(low->phys_addr)) {
                    191:                        low->pageq.next = (queue_entry_t)free_head;
                    192:                        free_head = low;
                    193:                } else {
                    194:                        (hil+i)->low_page = low->phys_addr;
                    195:                        i++;
                    196:                }
                    197:        }
                    198: 
                    199:        for (low = free_head; low; low = free_head) {
                    200:                free_head = (vm_page_t) low->pageq.next;
                    201:                VM_PAGE_FREE(low);
                    202:         }
                    203: 
                    204:        ipl = splhi();
                    205:        simple_lock(&hil_lock);
                    206:        (hil+npages-1)->next = hil_head;
                    207:        hil_head = hil;
                    208:        simple_unlock(&hil_lock);
                    209:        splx(ipl);
                    210: }
                    211: 
                    212: /*
                    213:  * Called by driver at DMA initialization time. Converts a high memory
                    214:  * physical page to a low memory one. If operation is a write, 
                    215:  * [phys_addr, phys_addr+length-1] is copied to new page. Caller must
                    216:  * provide a pointer to a pointer to a himem_list. This is used to store
                    217:  * all the conversions and is use at completion time to revert the pages.
                    218:  * This pointer must point to a null hil_t value for the call on the first
                    219:  * page of a DMA transfer.
                    220:  */
                    221: 
                    222: vm_offset_t
                    223: himem_convert(
                    224:        vm_offset_t     phys_addr,
                    225:        vm_size_t       length,
                    226:        int             io_op,
                    227:        hil_t           *hil)
                    228: {
                    229:        hil_t           h;
                    230:        spl_t           ipl;
                    231:        vm_offset_t     offset = phys_addr & (I386_PGBYTES - 1);
                    232: 
                    233:        assert (offset + length <= I386_PGBYTES);
                    234: 
                    235:        ipl = splhi();
                    236:        simple_lock(&hil_lock);
                    237:        while (!(h = hil_head)) { 
                    238:                printf("WARNING: out of HIMEM pages\n");
                    239:                thread_sleep_simple_lock((event_t)&hil_head,
                    240:                                        simple_lock_addr(hil_lock), FALSE);
                    241:                simple_lock (&hil_lock);
                    242:        }
                    243:        hil_head = hil_head->next;
                    244:        simple_unlock(&hil_lock);
                    245:        splx(ipl);
                    246:        
                    247:        h->high_addr = phys_addr;
                    248: 
                    249:        if (io_op == D_WRITE) {
                    250:          bcopy((char *)phystokv(phys_addr), (char *)phystokv(h->low_page + offset),
                    251:                length);
                    252:          h->length = 0;
                    253:        } else {
                    254:          h->length = length;
                    255:        }
                    256:        h->offset = offset;
                    257: 
                    258:        assert(!*hil || (*hil)->high_addr);
                    259: 
                    260:        h->next = *hil;
                    261:        *hil = h;
                    262:        return(h->low_page + offset);
                    263: }
                    264: 
                    265: /*
                    266:  * Called by driver at DMA completion time. Converts a list of low memory
                    267:  * physical page to the original high memory one. If operation was read, 
                    268:  * [phys_addr, phys_addr+lenght-1] is copied to original page
                    269:  */
                    270: 
                    271: void
                    272: himem_revert(
                    273:        hil_t           hil)
                    274: {
                    275:        hil_t           next;
                    276:        boolean_t       wakeup = FALSE;
                    277:        spl_t           ipl;
                    278: 
                    279:        while(hil) {
                    280:                if (hil->length) {
                    281:                        bcopy((char *)phystokv(hil->low_page + hil->offset),
                    282:                                (char *)phystokv(hil->high_addr),
                    283:                              hil->length);
                    284:                }
                    285:                hil->high_addr = 0;
                    286:                hil->length = 0;
                    287:                hil->offset = 0;
                    288:                next = hil->next;
                    289:                ipl = splhi();
                    290:                simple_lock(&hil_lock);
                    291:                if (!(hil->next = hil_head))
                    292:                        wakeup = TRUE;
                    293:                hil_head = hil;
                    294:                simple_unlock(&hil_lock);
                    295:                splx(ipl);
                    296:                hil = next;
                    297:        }
                    298:        if (wakeup)
                    299:                thread_wakeup((event_t)&hil_head);
                    300: }

unix.superglobalmegacorp.com

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