xref: /haiku/src/add-ons/kernel/bus_managers/firewire/util.c (revision 220d04022750f40f8bac8f01fa551211e28d04f2)
1 /* Realtek RTL8169 Family Driver
2  * Copyright (C) 2004 Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
3  *
4  * Permission to use, copy, modify and distribute this software and its
5  * documentation for any purpose and without fee is hereby granted, provided
6  * that the above copyright notice appear in all copies, and that both the
7  * copyright notice and this permission notice appear in supporting documentation.
8  *
9  * Marcus Overhagen makes no representations about the suitability of this software
10  * for any purpose. It is provided "as is" without express or implied warranty.
11  *
12  * MARCUS OVERHAGEN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
13  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL MARCUS
14  * OVERHAGEN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
15  * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 #include <Errors.h>
20 #include <OS.h>
21 #include <string.h>
22 
23 //#define DEBUG
24 
25 #include "fwdebug.h"
26 #include "util.h"
27 
28 
29 static inline uint32
30 round_to_pagesize(uint32 size)
31 {
32 	return (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
33 }
34 
35 
36 area_id
37 alloc_mem(void **virt, void **phy, size_t size, uint32 protection,
38 	const char *name)
39 {
40 // TODO: phy should be phys_addr_t*!
41 	physical_entry pe;
42 	void *virtadr;
43 	area_id area;
44 	status_t rv;
45 
46 	TRACE("allocating %ld bytes for %s\n", size, name);
47 
48 	size = round_to_pagesize(size);
49 	area = create_area(name, &virtadr, B_ANY_KERNEL_ADDRESS, size,
50 		B_32_BIT_CONTIGUOUS, protection);
51 		// TODO: The rest of the code doesn't deal correctly with physical
52 		// addresses > 4 GB, so we have to force 32 bit addresses here.
53 	if (area < B_OK) {
54 		ERROR("couldn't allocate area %s\n", name);
55 		return B_ERROR;
56 	}
57 	rv = get_memory_map(virtadr, size, &pe, 1);
58 	if (rv < B_OK) {
59 		delete_area(area);
60 		ERROR("couldn't get mapping for %s\n", name);
61 		return B_ERROR;
62 	}
63 	memset(virtadr, 0, size);
64 	if (virt)
65 		*virt = virtadr;
66 	if (phy)
67 		*phy = (void*)(addr_t)pe.address;
68 	TRACE("area = %ld, size = %ld, virt = %p, phy = %" B_PRIxPHYSADDR "\n", area, size, virtadr,
69 		pe.address);
70 	return area;
71 }
72 
73 
74 area_id
75 map_mem(void **virt, void *phy, size_t size, uint32 protection,
76 	const char *name)
77 {
78 	uint32 offset;
79 	void *phyadr;
80 	void *mapadr;
81 	area_id area;
82 
83 	TRACE("mapping physical address %p with %ld bytes for %s\n", phy, size,
84 		name);
85 
86 	offset = (uint32)phy & (B_PAGE_SIZE - 1);
87 	phyadr = (char *)phy - offset;
88 	size = round_to_pagesize(size + offset);
89 	area = map_physical_memory(name, (addr_t)phyadr, size,
90 		B_ANY_KERNEL_BLOCK_ADDRESS, protection, &mapadr);
91 	if (area < B_OK) {
92 		ERROR("mapping '%s' failed, error 0x%lx (%s)\n", name, area,
93 			strerror(area));
94 		return area;
95 	}
96 
97 	*virt = (char *)mapadr + offset;
98 
99 	TRACE("physical = %p, virtual = %p, offset = %ld, phyadr = %p, mapadr = "
100 		"%p, size = %ld, area = 0x%08lx\n", phy, *virt, offset, phyadr, mapadr,
101 		size, area);
102 
103 	return area;
104 }
105