xref: /haiku/src/add-ons/kernel/drivers/audio/generic/util.c (revision dd2a1e350b303b855a50fd64e6cb55618be1ae6a)
1 /*
2  * BeOS Driver for Intel ICH AC'97 Link interface
3  *
4  * Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
5  *
6  * All rights reserved.
7  * Redistribution and use in source and binary forms, with or without modification,
8  * are permitted provided that the following conditions are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  *   this list of conditions and the following disclaimer.
12  * - Redistributions in binary form must reproduce the above copyright notice,
13  *   this list of conditions and the following disclaimer in the documentation
14  *   and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 #include <Errors.h>
29 #include <OS.h>
30 #include <string.h>
31 
32 //#define DEBUG 2
33 
34 #include "debug.h"
35 #include "util.h"
36 
37 spinlock slock = B_SPINLOCK_INITIALIZER;
38 
39 uint32 round_to_pagesize(uint32 size);
40 
41 
42 cpu_status
43 lock(void)
44 {
45 	cpu_status status = disable_interrupts();
46 	acquire_spinlock(&slock);
47 	return status;
48 }
49 
50 
51 void
52 unlock(cpu_status status)
53 {
54 	release_spinlock(&slock);
55 	restore_interrupts(status);
56 }
57 
58 
59 uint32
60 round_to_pagesize(uint32 size)
61 {
62 	return (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
63 }
64 
65 
66 area_id
67 alloc_mem(phys_addr_t *phy, void **log, size_t size, const char *name, bool user)
68 {
69 	physical_entry pe;
70 	void * logadr;
71 	area_id area;
72 	status_t rv;
73 	uint32 protection;
74 
75 	LOG(("allocating %d bytes for %s\n",size,name));
76 
77 	protection = B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA;
78 	if (user)
79 		protection = B_READ_AREA | B_WRITE_AREA;
80 	size = round_to_pagesize(size);
81 	area = create_area(name, &logadr, B_ANY_KERNEL_ADDRESS, size,
82 		B_32_BIT_CONTIGUOUS, protection);
83 		// TODO: The rest of the code doesn't deal correctly with physical
84 		// addresses > 4 GB, so we have to force 32 bit addresses here.
85 	if (area < B_OK) {
86 		PRINT(("couldn't allocate area %s\n", name));
87 		return B_ERROR;
88 	}
89 	rv = get_memory_map(logadr, size, &pe, 1);
90 	if (rv < B_OK) {
91 		delete_area(area);
92 		PRINT(("couldn't map %s\n",name));
93 		return B_ERROR;
94 	}
95 	if (user)
96 		user_memset(logadr, 0, size);
97 	else
98 		memset(logadr, 0, size);
99 	if (log)
100 		*log = logadr;
101 	if (phy)
102 		*phy = pe.address;
103 	LOG(("area = %d, size = %d, log = %#08X, phy = %#08X\n", area, size, logadr,
104 		pe.address));
105 	return area;
106 }
107 
108 
109 area_id
110 map_mem(void **log, phys_addr_t phy, size_t size, const char *name)
111 {
112 	uint32 offset;
113 	phys_addr_t phyadr;
114 	void *mapadr;
115 	area_id area;
116 
117 	LOG(("mapping physical address %p with %#x bytes for %s\n",phy,size,name));
118 
119 	offset = (uint32)phy & (B_PAGE_SIZE - 1);
120 	phyadr = phy - offset;
121 	size = round_to_pagesize(size + offset);
122 	area = map_physical_memory(name, phyadr, size, B_ANY_KERNEL_ADDRESS,
123 		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, &mapadr);
124 	*log = (void *)((uintptr_t)mapadr + (uintptr_t)offset);
125 
126 	LOG(("physical = %p, logical = %p, offset = %#x, phyadr = %p, mapadr = %p, size = %#x, area = %#x\n",
127 		phy, *log, offset, phyadr, mapadr, size, area));
128 
129 	return area;
130 }
131