xref: /haiku/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp (revision d2e1e872611179c9cfaa43ce11bd58b1e3554e4b)
1 /*
2  * Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "vesa_private.h"
8 
9 #include <string.h>
10 
11 #include <boot_item.h>
12 #include <frame_buffer_console.h>
13 #include <util/kernel_cpp.h>
14 
15 #include "driver.h"
16 #include "utility.h"
17 #include "vesa_info.h"
18 
19 
20 class PhysicalMemoryMapper {
21 	public:
22 		PhysicalMemoryMapper();
23 		~PhysicalMemoryMapper();
24 
25 		area_id Map(const char *name, void *physicalAddress, size_t numBytes,
26 			uint32 spec, uint32 protection, void **virtualAddress);
27 		status_t InitCheck() { return fArea < B_OK ? (status_t)fArea : B_OK; }
28 		void Keep();
29 
30 	private:
31 		area_id	fArea;
32 };
33 
34 
35 PhysicalMemoryMapper::PhysicalMemoryMapper()
36 	:
37 	fArea(-1)
38 {
39 }
40 
41 
42 PhysicalMemoryMapper::~PhysicalMemoryMapper()
43 {
44 	if (fArea >= B_OK)
45 		delete_area(fArea);
46 }
47 
48 
49 area_id
50 PhysicalMemoryMapper::Map(const char *name, void *physicalAddress,
51 	size_t numBytes, uint32 spec, uint32 protection, void **virtualAddress)
52 {
53 	fArea = map_physical_memory(name, physicalAddress, numBytes, spec,
54 		protection, virtualAddress);
55 	return fArea;
56 }
57 
58 
59 void
60 PhysicalMemoryMapper::Keep()
61 {
62 	fArea = -1;
63 }
64 
65 
66 //	#pragma mark -
67 
68 
69 static uint32
70 get_color_space_for_depth(uint32 depth)
71 {
72 	switch (depth) {
73 		case 4:
74 			return B_GRAY8;
75 				// the app_server is smart enough to translate this to VGA mode
76 		case 8:
77 			return B_CMAP8;
78 		case 15:
79 			return B_RGB15;
80 		case 16:
81 			return B_RGB16;
82 		case 24:
83 			return B_RGB24;
84 		case 32:
85 			return B_RGB32;
86 	}
87 
88 	return 0;
89 }
90 
91 
92 //	#pragma mark -
93 
94 
95 status_t
96 vesa_init(vesa_info &info)
97 {
98 	frame_buffer_boot_info *bufferInfo
99 		= (frame_buffer_boot_info *)get_boot_item(FRAME_BUFFER_BOOT_INFO, NULL);
100 	if (bufferInfo == NULL)
101 		return B_ERROR;
102 
103 	size_t modesSize = 0;
104 	vesa_mode *modes = (vesa_mode *)get_boot_item(VESA_MODES_BOOT_INFO,
105 		&modesSize);
106 
107 	size_t sharedSize = (sizeof(vesa_shared_info) + 7) & ~7;
108 
109 	info.shared_area = create_area("vesa shared info",
110 		(void **)&info.shared_info, B_ANY_KERNEL_ADDRESS,
111 		ROUND_TO_PAGE_SIZE(sharedSize + modesSize), B_FULL_LOCK,
112 		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_USER_CLONEABLE_AREA);
113 	if (info.shared_area < B_OK)
114 		return info.shared_area;
115 
116 	vesa_shared_info &sharedInfo = *info.shared_info;
117 
118 	memset(/*(void *)*/&sharedInfo, 0, sizeof(vesa_shared_info));
119 
120 	if (modes != NULL) {
121 		sharedInfo.vesa_mode_offset = sharedSize;
122 		sharedInfo.vesa_mode_count = modesSize / sizeof(vesa_mode);
123 
124 		memcpy((uint8*)&sharedInfo + sharedSize, modes, modesSize);
125 	}
126 
127 	sharedInfo.frame_buffer_area = bufferInfo->area;
128 	sharedInfo.frame_buffer = (uint8 *)bufferInfo->frame_buffer;
129 
130 	sharedInfo.current_mode.virtual_width = bufferInfo->width;
131 	sharedInfo.current_mode.virtual_height = bufferInfo->height;
132 	sharedInfo.current_mode.space = get_color_space_for_depth(
133 		bufferInfo->depth);
134 	sharedInfo.bytes_per_row = bufferInfo->bytes_per_row;
135 
136 	physical_entry mapping;
137 	get_memory_map((void *)sharedInfo.frame_buffer, B_PAGE_SIZE,
138 		&mapping, 1);
139 	sharedInfo.physical_frame_buffer = (uint8 *)mapping.address;
140 
141 	dprintf(DEVICE_NAME ": vesa_init() completed successfully!\n");
142 	return B_OK;
143 }
144 
145 
146 void
147 vesa_uninit(vesa_info &info)
148 {
149 	dprintf(DEVICE_NAME": vesa_uninit()\n");
150 
151 	delete_area(info.shared_info->frame_buffer_area);
152 	delete_area(info.shared_area);
153 }
154 
155