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
29static inline uint32
30round_to_pagesize(uint32 size)
31{
32	return (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
33}
34
35
36area_id
37alloc_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 = %" B_PRId32 ", size = %ld, virt = %p, phy = %" B_PRIxPHYSADDR "\n", area, size, virtadr,
69		pe.address);
70	return area;
71}
72
73
74area_id
75map_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 = (intptr_t)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%" B_PRIx32 " (%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 = %" B_PRId32 ", phyadr = %p, "
100		"mapadr = %p, size = %ld, area = 0x%08" B_PRIx32 "\n", phy, *virt,
101		offset, phyadr, mapadr, size, area);
102
103	return area;
104}
105