1af9bf370Sbeveloper/*
2af9bf370Sbeveloper * BeOS Driver for Intel ICH AC'97 Link interface
3af9bf370Sbeveloper *
4af9bf370Sbeveloper * Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
5af9bf370Sbeveloper *
6af9bf370Sbeveloper * All rights reserved.
7b0884f0cSAxel Dörfler * Redistribution and use in source and binary forms, with or without modification,
8af9bf370Sbeveloper * are permitted provided that the following conditions are met:
9af9bf370Sbeveloper *
10b0884f0cSAxel Dörfler * - Redistributions of source code must retain the above copyright notice,
11af9bf370Sbeveloper *   this list of conditions and the following disclaimer.
12af9bf370Sbeveloper * - Redistributions in binary form must reproduce the above copyright notice,
13b0884f0cSAxel Dörfler *   this list of conditions and the following disclaimer in the documentation
14af9bf370Sbeveloper *   and/or other materials provided with the distribution.
15af9bf370Sbeveloper *
16b0884f0cSAxel Dörfler * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17b0884f0cSAxel Dörfler * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18b0884f0cSAxel Dörfler * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19b0884f0cSAxel Dörfler * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20b0884f0cSAxel Dörfler * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21b0884f0cSAxel Dörfler * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22b0884f0cSAxel Dörfler * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23b0884f0cSAxel Dörfler * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24b0884f0cSAxel Dörfler * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25af9bf370Sbeveloper * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26af9bf370Sbeveloper *
27af9bf370Sbeveloper */
28af9bf370Sbeveloper#include <Errors.h>
29af9bf370Sbeveloper#include <OS.h>
30af9bf370Sbeveloper#include <string.h>
31af9bf370Sbeveloper
32af9bf370Sbeveloper//#define DEBUG 2
33af9bf370Sbeveloper
34af9bf370Sbeveloper#include "debug.h"
35af9bf370Sbeveloper#include "util.h"
36af9bf370Sbeveloper
37af9bf370Sbeveloperspinlock slock = 0;
38af9bf370Sbeveloper
39dc03e28fSbeveloperuint32 round_to_pagesize(uint32 size);
40dc03e28fSbeveloper
41b0884f0cSAxel Dörfler
42b0884f0cSAxel Dörflercpu_status
43b0884f0cSAxel Dörflerlock(void)
44af9bf370Sbeveloper{
45af9bf370Sbeveloper	cpu_status status = disable_interrupts();
46af9bf370Sbeveloper	acquire_spinlock(&slock);
47af9bf370Sbeveloper	return status;
48af9bf370Sbeveloper}
49af9bf370Sbeveloper
50b0884f0cSAxel Dörfler
51b0884f0cSAxel Dörflervoid
52b0884f0cSAxel Dörflerunlock(cpu_status status)
53af9bf370Sbeveloper{
54af9bf370Sbeveloper	release_spinlock(&slock);
55af9bf370Sbeveloper	restore_interrupts(status);
56af9bf370Sbeveloper}
57af9bf370Sbeveloper
58b0884f0cSAxel Dörfler
59b0884f0cSAxel Dörfleruint32
60b0884f0cSAxel Dörflerround_to_pagesize(uint32 size)
61af9bf370Sbeveloper{
62af9bf370Sbeveloper	return (size + B_PAGE_SIZE - 1) & ~(B_PAGE_SIZE - 1);
63af9bf370Sbeveloper}
64af9bf370Sbeveloper
65b0884f0cSAxel Dörfler
66b0884f0cSAxel Dörflerarea_id
67b0884f0cSAxel Dörfleralloc_mem(void **log, void **phy, size_t size, const char *name)
68af9bf370Sbeveloper{
6964d79effSIngo Weinhold// TODO: phy should be phys_addr_t*!
70af9bf370Sbeveloper	physical_entry pe;
71af9bf370Sbeveloper	void * logadr;
72af9bf370Sbeveloper	area_id areaid;
73af9bf370Sbeveloper	status_t rv;
74b0884f0cSAxel Dörfler
7515ea765dSbeveloper	LOG(("allocating %d bytes for %s\n",size,name));
76af9bf370Sbeveloper
77af9bf370Sbeveloper	size = round_to_pagesize(size);
78b0884f0cSAxel Dörfler	areaid = create_area(name, &logadr, B_ANY_KERNEL_ADDRESS, size,
799fb2d737SIngo Weinhold		B_32_BIT_CONTIGUOUS, B_READ_AREA | B_WRITE_AREA);
80d108c419SIngo Weinhold		// TODO: The rest of the code doesn't deal correctly with physical
81d108c419SIngo Weinhold		// addresses > 4 GB, so we have to force 32 bit addresses here.
82af9bf370Sbeveloper	if (areaid < B_OK) {
8315ea765dSbeveloper		PRINT(("couldn't allocate area %s\n",name));
84af9bf370Sbeveloper		return B_ERROR;
85af9bf370Sbeveloper	}
86af9bf370Sbeveloper	rv = get_memory_map(logadr,size,&pe,1);
87af9bf370Sbeveloper	if (rv < B_OK) {
88af9bf370Sbeveloper		delete_area(areaid);
8915ea765dSbeveloper		PRINT(("couldn't map %s\n",name));
90af9bf370Sbeveloper		return B_ERROR;
91af9bf370Sbeveloper	}
92af9bf370Sbeveloper	memset(logadr,0,size);
93af9bf370Sbeveloper	if (log)
94af9bf370Sbeveloper		*log = logadr;
95af9bf370Sbeveloper	if (phy)
9664d79effSIngo Weinhold		*phy = (void*)(addr_t)pe.address;
9715ea765dSbeveloper	LOG(("area = %d, size = %d, log = %#08X, phy = %#08X\n",areaid,size,logadr,pe.address));
98af9bf370Sbeveloper	return areaid;
99af9bf370Sbeveloper}
100af9bf370Sbeveloper
101b0884f0cSAxel Dörfler
102106c88e9Sbeveloper/* This is not the most advanced method to map physical memory for io access.
103106c88e9Sbeveloper * Perhaps using B_ANY_KERNEL_ADDRESS instead of B_ANY_KERNEL_BLOCK_ADDRESS
104106c88e9Sbeveloper * makes the whole offset calculation and relocation obsolete. But the code
105106c88e9Sbeveloper * below does work, and I can't test if using B_ANY_KERNEL_ADDRESS also works.
106106c88e9Sbeveloper */
107b0884f0cSAxel Dörflerarea_id
108b0884f0cSAxel Dörflermap_mem(void **log, void *phy, size_t size, const char *name)
109106c88e9Sbeveloper{
110106c88e9Sbeveloper	uint32 offset;
111106c88e9Sbeveloper	void *phyadr;
112106c88e9Sbeveloper	void *mapadr;
113106c88e9Sbeveloper	area_id area;
114106c88e9Sbeveloper
115106c88e9Sbeveloper	LOG(("mapping physical address %p with %#x bytes for %s\n",phy,size,name));
116106c88e9Sbeveloper
117106c88e9Sbeveloper	offset = (uint32)phy & (B_PAGE_SIZE - 1);
118ef86d67dSbeveloper	phyadr = (char *)phy - offset;
119106c88e9Sbeveloper	size = round_to_pagesize(size + offset);
12064d79effSIngo Weinhold	area = map_physical_memory(name, (addr_t)phyadr, size,
12164d79effSIngo Weinhold		B_ANY_KERNEL_BLOCK_ADDRESS, B_READ_AREA | B_WRITE_AREA, &mapadr);
122ef86d67dSbeveloper	*log = (char *)mapadr + offset;
123106c88e9Sbeveloper
124106c88e9Sbeveloper	LOG(("physical = %p, logical = %p, offset = %#x, phyadr = %p, mapadr = %p, size = %#x, area = %#x\n",
125106c88e9Sbeveloper		phy, *log, offset, phyadr, mapadr, size, area));
126b0884f0cSAxel Dörfler
127106c88e9Sbeveloper	return area;
128106c88e9Sbeveloper}
129