1/*
2 * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef KERNEL_ARCH_M68K_PAGING_32_BIT_M68K_PAGING_METHOD_32_BIT_H
6#define KERNEL_ARCH_M68K_PAGING_32_BIT_M68K_PAGING_METHOD_32_BIT_H
7
8
9#include "paging/040/paging.h"
10#include "paging/M68KPagingMethod.h"
11#include "paging/M68KPagingStructures.h"
12
13
14class TranslationMapPhysicalPageMapper;
15class M68KPhysicalPageMapper;
16
17
18class M68KPagingMethod040 : public M68KPagingMethod {
19public:
20								M68KPagingMethod040();
21	virtual						~M68KPagingMethod040();
22
23	virtual	status_t			Init(kernel_args* args,
24									VMPhysicalPageMapper** _physicalPageMapper);
25	virtual	status_t			InitPostArea(kernel_args* args);
26
27	virtual	status_t			CreateTranslationMap(bool kernel,
28									VMTranslationMap** _map);
29
30	virtual	status_t			MapEarly(kernel_args* args,
31									addr_t virtualAddress,
32									phys_addr_t physicalAddress,
33									uint8 attributes,
34									phys_addr_t (*get_free_page)(kernel_args*));
35
36	virtual	bool				IsKernelPageAccessible(addr_t virtualAddress,
37									uint32 protection);
38
39	virtual void				SetPageRoot(uint32 pageRoot);
40
41
42#if 0
43	inline	page_table_entry*	PageHole() const
44									{ return fPageHole; }
45	inline	page_directory_entry* PageHolePageDir() const
46									{ return fPageHolePageDir; }
47#endif
48	inline	uint32				KernelPhysicalPageRoot() const
49									{ return fKernelPhysicalPageRoot; }
50	inline	page_directory_entry* KernelVirtualPageRoot() const
51									{ return fKernelVirtualPageRoot; }
52	inline	M68KPhysicalPageMapper* PhysicalPageMapper() const
53									{ return fPhysicalPageMapper; }
54	inline	TranslationMapPhysicalPageMapper* KernelPhysicalPageMapper() const
55									{ return fKernelPhysicalPageMapper; }
56
57	static	M68KPagingMethod040* Method();
58
59	static	void				PutPageDirInPageRoot(
60									page_root_entry* entry,
61									phys_addr_t pgdirPhysical,
62									uint32 attributes);
63	static	void				PutPageTableInPageDir(
64									page_directory_entry* entry,
65									phys_addr_t pgtablePhysical,
66									uint32 attributes);
67	static	void				PutPageTableEntryInTable(
68									page_table_entry* entry,
69									phys_addr_t physicalAddress,
70									uint32 attributes, uint32 memoryType,
71									bool globalPage);
72#if 1
73	static	page_table_entry	SetPageTableEntry(page_table_entry* entry,
74									page_table_entry newEntry);
75	static	page_table_entry	SetPageTableEntryFlags(page_table_entry* entry,
76									uint32 flags);
77	static	page_table_entry	TestAndSetPageTableEntry(
78									page_table_entry* entry,
79									page_table_entry newEntry,
80									page_table_entry oldEntry);
81	static	page_table_entry	ClearPageTableEntry(page_table_entry* entry);
82	static	page_table_entry	ClearPageTableEntryFlags(
83									page_table_entry* entry, uint32 flags);
84#endif
85
86	static	uint32				MemoryTypeToPageTableEntryFlags(
87									uint32 memoryType);
88
89private:
90			struct PhysicalPageSlotPool;
91			friend struct PhysicalPageSlotPool;
92
93private:
94	static	void				_EarlyPreparePageTables(
95									page_table_entry* pageTables,
96									addr_t address, size_t size);
97	static	status_t			_EarlyQuery(addr_t virtualAddress,
98									phys_addr_t *_physicalAddress);
99
100private:
101#if 0
102			page_table_entry*	fPageHole;
103			page_directory_entry* fPageHolePageDir;
104#endif
105			uint32				fKernelPhysicalPageRoot;
106			page_directory_entry* fKernelVirtualPageRoot;
107
108			M68KPhysicalPageMapper* fPhysicalPageMapper;
109			TranslationMapPhysicalPageMapper* fKernelPhysicalPageMapper;
110};
111
112
113/*static*/ inline M68KPagingMethod040*
114M68KPagingMethod040::Method()
115{
116	return static_cast<M68KPagingMethod040*>(gM68KPagingMethod);
117}
118
119
120#if 1
121/*static*/ inline page_table_entry
122M68KPagingMethod040::SetPageTableEntry(page_table_entry* entry,
123	page_table_entry newEntry)
124{
125	return atomic_get_and_set((int32*)entry, newEntry);
126}
127
128
129/*static*/ inline page_table_entry
130M68KPagingMethod040::SetPageTableEntryFlags(page_table_entry* entry,
131	uint32 flags)
132{
133	return atomic_or((int32*)entry, flags);
134}
135
136
137/*static*/ inline page_table_entry
138M68KPagingMethod040::TestAndSetPageTableEntry(page_table_entry* entry,
139	page_table_entry newEntry, page_table_entry oldEntry)
140{
141	return atomic_test_and_set((int32*)entry, newEntry, oldEntry);
142}
143
144
145/*static*/ inline page_table_entry
146M68KPagingMethod040::ClearPageTableEntry(page_table_entry* entry)
147{
148	return SetPageTableEntry(entry, DFL_PAGEENT_VAL);
149}
150
151
152/*static*/ inline page_table_entry
153M68KPagingMethod040::ClearPageTableEntryFlags(page_table_entry* entry, uint32 flags)
154{
155	return atomic_and((int32*)entry, ~flags);
156}
157#endif
158
159/*static*/ inline uint32
160M68KPagingMethod040::MemoryTypeToPageTableEntryFlags(uint32 memoryType)
161{
162	// x86:
163	// ATM we only handle the uncacheable and write-through type explicitly. For
164	// all other types we rely on the MTRRs to be set up correctly. Since we set
165	// the default memory type to write-back and since the uncacheable type in
166	// the PTE overrides any MTRR attribute (though, as per the specs, that is
167	// not recommended for performance reasons), this reduces the work we
168	// actually *have* to do with the MTRRs to setting the remaining types
169	// (usually only write-combining for the frame buffer).
170#warning M68K: Check this
171	switch (memoryType) {
172		case B_MTR_UC:
173			return CM_DISABLED_SERIALIZED | CM_CACHABLE_WRITETHROUGH;
174
175		case B_MTR_WC:
176			return 0;
177
178		case B_MTR_WT:
179			return CM_CACHABLE_WRITETHROUGH;
180
181		case B_MTR_WP:
182		case B_MTR_WB:
183		default:
184			return 0;
185	}
186}
187
188
189#endif	// KERNEL_ARCH_M68K_PAGING_32_BIT_M68K_PAGING_METHOD_32_BIT_H
190