]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/AT386/himem.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * @OSF_FREE_COPYRIGHT@
31 * Revision 1.1.1.1 1998/09/22 21:05:38 wsanchez
32 * Import of Mac OS X kernel (~semeria)
34 * Revision 1.1.1.1 1998/03/07 02:25:39 wsanchez
35 * Import of OSF Mach kernel (~mburg)
37 * Revision 1.3.17.7 1995/08/21 20:33:13 devrcs
38 * ri-osc CR1547: Fix himem buffer translation to cope with non
39 * page-aligned addresses.
40 * [1995/08/08 16:51:58 bolinger]
42 * Revision 1.3.17.6 1995/02/24 15:51:12 alanl
43 * DIPC: Merge from nmk17b2 to nmk18b8.
44 * Notes: lock package cleanup.
48 * Revision 1.3.17.5 1995/01/26 22:14:52 ezf
49 * removed extraneous CMU CR
50 * [1995/01/26 20:24:45 ezf]
52 * Revision 1.3.17.4 1995/01/10 04:51:04 devrcs
53 * mk6 CR801 - merge up from nmk18b4 to nmk18b7
54 * * Rev 1.3.17.3 1994/10/21 18:41:39 joe
56 * [1994/12/09 20:37:48 dwm]
58 * mk6 CR764 - s/spinlock/simple_lock/ (name change only)
59 * [1994/11/10 05:25:33 dwm]
61 * mk6 CR668 - 1.3b26 merge
62 * * Revision 1.3.5.8 1994/05/06 18:44:06 tmt
63 * Fix prototypes for new device signatures.
64 * * Revision 1.3.5.6 1993/12/10 18:08:15 jeffc
65 * CR10305 -- locking bug in himem_reserve(): change call to
66 * vm_page_free to VM_PAGE_FREE.
67 * * Revision 1.3.5.5 1993/11/19 17:56:58 jeffc
68 * CR10125 -- Uninitialized lock in himem_convert. Add himem_init
69 * CR9461 -- Locking bug in himem_convert - must retake lock after
72 * [1994/11/04 09:07:39 dwm]
74 * Revision 1.3.17.1 1994/06/14 03:04:20 toshi
76 * [1994/06/14 01:06:55 toshi]
78 * Revision 1.3.15.2 1994/06/08 21:14:24 dswartz
80 * [1994/06/08 21:12:29 dswartz]
82 * Revision 1.3.15.1 1994/05/19 20:30:23 dwm
83 * mk6 CR 74. Locking bug in himem_reserve(): use VM_PAGE_FREE.
84 * mk6 CR 9461. Init hil_lock used by himem_convert();
85 * retake lock after sleeping.
86 * [1994/05/19 20:30:07 dwm]
88 * Revision 1.3.11.1 1994/02/09 07:27:07 bernadat
89 * Added himem_init() for module initialization.
92 * Take back hil_lock lock on return from thread_sleep()
95 * Add vm_page_gobble() calls where needed. (dwm bug #542)
96 * Change from NORMA_MK14.6 [1993/02/09 22:24:00 dwm]
100 * Revision 1.3.5.4 1993/08/09 19:37:19 dswartz
101 * Add ANSI prototypes - CR#9523
102 * [1993/08/06 17:50:02 dswartz]
104 * Revision 1.3.5.3 1993/08/03 22:21:26 bernard
105 * CR#9523 - ANSI prototype fixes.
106 * [1993/08/03 15:34:10 bernard]
108 * Revision 1.3.5.2 1993/06/09 02:25:18 gm
109 * CR9157 - Find himem.h in the right place.
110 * [1993/05/28 17:27:23 brezak]
112 * Revision 1.3 1993/04/19 16:09:46 devrcs
113 * make endif tags ansi compliant/include files
114 * [1993/02/20 21:46:44 david]
116 * Print an appropriate message when going out of HIMEM pages.
117 * [93/01/26 bernadat]
119 * Revision 1.2 1992/11/25 01:07:08 robert
120 * integrate changes below for norma_14
121 * [1992/11/13 19:28:44 robert]
127 * support of memory above 16 Megs for DMA limited to memory
128 * below 16 Megs. Copies high memory lo low memory before DMA
129 * write operations and does the reverse at completion time for
130 * DMA read operations
134 #include <platforms.h>
135 #include <kern/lock.h>
136 #include <mach/vm_param.h>
137 #include <vm/vm_page.h>
138 #include <i386/AT386/himem.h>
139 #include <kern/kalloc.h>
140 #include <kern/spl.h>
141 #include <mach/boolean.h>
142 #include <kern/misc_protos.h>
143 #include <i386/AT386/misc_protos.h>
146 decl_simple_lock_data(,hil_lock
)
149 int himem_request
; /* number of requests */
150 int himem_used
; /* number of times used */
151 #endif /* HIMEM_STATS */
157 simple_lock_init(&hil_lock
, ETAP_VM_HIMEM
);
161 * Called by drivers, this indicates himem that this driver might need
162 * to allocate as many as npages pages in a single I/O DMA transfer
170 vm_page_t free_head
= VM_PAGE_NULL
;
174 extern vm_offset_t avail_end
;
176 if (avail_end
<= HIGH_MEM
)
178 hil
= (hil_t
)kalloc(npages
*sizeof(struct himem_link
));
180 panic("himem_reserve: kalloc failed\n");
182 for (i
=0; i
< npages
-1; i
++)
183 (hil
+i
)->next
= hil
+i
+1;
186 * This is the only way of getting low physical pages
187 * wtithout changing VM internals
189 for (i
=0; i
!= npages
;) {
190 if ((low
= vm_page_grab()) == VM_PAGE_NULL
)
191 panic("No low memory pages for himem\n");
192 vm_page_gobble(low
); /* mark as consumed internally */
193 if (_high_mem_page(low
->phys_addr
)) {
194 low
->pageq
.next
= (queue_entry_t
)free_head
;
197 (hil
+i
)->low_page
= low
->phys_addr
;
202 for (low
= free_head
; low
; low
= free_head
) {
203 free_head
= (vm_page_t
) low
->pageq
.next
;
208 simple_lock(&hil_lock
);
209 (hil
+npages
-1)->next
= hil_head
;
211 simple_unlock(&hil_lock
);
216 * Called by driver at DMA initialization time. Converts a high memory
217 * physical page to a low memory one. If operation is a write,
218 * [phys_addr, phys_addr+length-1] is copied to new page. Caller must
219 * provide a pointer to a pointer to a himem_list. This is used to store
220 * all the conversions and is use at completion time to revert the pages.
221 * This pointer must point to a null hil_t value for the call on the first
222 * page of a DMA transfer.
227 vm_offset_t phys_addr
,
234 vm_offset_t offset
= phys_addr
& (I386_PGBYTES
- 1);
236 assert (offset
+ length
<= I386_PGBYTES
);
239 simple_lock(&hil_lock
);
240 while (!(h
= hil_head
)) {
241 printf("WARNING: out of HIMEM pages\n");
242 thread_sleep_simple_lock((event_t
)&hil_head
,
243 simple_lock_addr(hil_lock
),
245 /* hil_lock relocked */
247 hil_head
= hil_head
->next
;
248 simple_unlock(&hil_lock
);
251 h
->high_addr
= phys_addr
;
253 if (io_op
== D_WRITE
) {
254 bcopy((char *)phystokv(phys_addr
), (char *)phystokv(h
->low_page
+ offset
),
262 assert(!*hil
|| (*hil
)->high_addr
);
266 return(h
->low_page
+ offset
);
270 * Called by driver at DMA completion time. Converts a list of low memory
271 * physical page to the original high memory one. If operation was read,
272 * [phys_addr, phys_addr+lenght-1] is copied to original page
280 boolean_t wakeup
= FALSE
;
285 bcopy((char *)phystokv(hil
->low_page
+ hil
->offset
),
286 (char *)phystokv(hil
->high_addr
),
294 simple_lock(&hil_lock
);
295 if (!(hil
->next
= hil_head
))
298 simple_unlock(&hil_lock
);
303 thread_wakeup((event_t
)&hil_head
);