|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.