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 "lala.h"
35
36uint32 round_to_pagesize(uint32 size);
37
38
39uint32
40round_to_pagesize(uint32 size)
41{
42	return (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
43}
44
45
46area_id
47alloc_mem(void **virt, void **phy, size_t size, uint32 protection,
48	const char *name)
49{
50// TODO: phy should be phys_addr_t*!
51	physical_entry pe;
52	void * virtadr;
53	area_id areaid;
54	status_t rv;
55
56	LOG(("allocating %ld bytes for %s\n", size, name));
57
58	size = round_to_pagesize(size);
59	areaid = create_area(name, &virtadr, B_ANY_KERNEL_ADDRESS, size,
60		B_32_BIT_CONTIGUOUS, protection);
61		// TODO: The rest of the code doesn't deal correctly with physical
62		// addresses > 4 GB, so we have to force 32 bit addresses here.
63	if (areaid < B_OK) {
64		PRINT(("couldn't allocate area %s\n",name));
65		return B_ERROR;
66	}
67	rv = get_memory_map(virtadr, size, &pe, 1);
68	if (rv < B_OK) {
69		delete_area(areaid);
70		PRINT(("couldn't map %s\n",name));
71		return B_ERROR;
72	}
73	memset(virtadr, 0, size);
74	if (virt)
75		*virt = virtadr;
76	if (phy)
77		*phy = (void*)(addr_t)pe.address;
78	LOG(("area = %ld, size = %ld, virt = %p, phy = %p\n", areaid, size, virtadr, pe.address));
79	return areaid;
80}
81
82
83/* This is not the most advanced method to map physical memory for io access.
84 * Perhaps using B_ANY_KERNEL_ADDRESS instead of B_ANY_KERNEL_BLOCK_ADDRESS
85 * makes the whole offset calculation and relocation obsolete. But the code
86 * below does work, and I can't test if using B_ANY_KERNEL_ADDRESS also works.
87 */
88area_id
89map_mem(void **virt, void *phy, size_t size, uint32 protection, const char *name)
90{
91	uint32 offset;
92	void *phyadr;
93	void *mapadr;
94	area_id area;
95
96	LOG(("mapping physical address %p with %ld bytes for %s\n", phy, size, name));
97
98	offset = (uint32)phy & (B_PAGE_SIZE - 1);
99	phyadr = (char *)phy - offset;
100	size = round_to_pagesize(size + offset);
101	area = map_physical_memory(name, (addr_t)phyadr, size,
102		B_ANY_KERNEL_BLOCK_ADDRESS, protection, &mapadr);
103	*virt = (char *)mapadr + offset;
104
105	LOG(("physical = %p, virtual = %p, offset = %ld, phyadr = %p, mapadr = %p, size = %ld, area = 0x%08lx\n",
106		phy, *virt, offset, phyadr, mapadr, size, area));
107
108	return area;
109}
110