xref: /haiku/src/add-ons/kernel/drivers/graphics/radeon/init.c (revision 67bce78b48ed6d01b5a8eef89f5694c372b7e0a1)
1 /*
2 	Copyright (c) 2002, Thomas Kurschel
3 
4 
5 	Part of Radeon kernel driver
6 
7 	Init and clean-up of devices
8 
9 	TBD: support for multiple virtual card per device is
10 	not implemented yet - there is only one per device;
11 	apart from additional device names, we need proper
12 	management of graphics mem to not interfere.
13 */
14 
15 #include "radeon_driver.h"
16 
17 #include <PCI.h>
18 #include <stdio.h>
19 #include <dac_regs.h>
20 #include <mmio.h>
21 
22 // helper macros for easier PCI access
23 #define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s))
24 #define set_pci(o, s, v) (*pci_bus->write_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s), (v))
25 
26 
27 // map frame buffer and registers
28 // mmio_only - true = map registers only (used during detection)
29 status_t Radeon_MapDevice( device_info *di, bool mmio_only )
30 {
31 	// framebuffer is stored in PCI range 0,
32 	// register map in PCI range 2
33 	int regs = 2;
34 	int fb   = 0;
35 	char buffer[B_OS_NAME_LENGTH];
36 	shared_info *si = di->si;
37 	uint32	tmp;
38 	pci_info *pcii = &(di->pcii);
39 	status_t result;
40 
41 	SHOW_FLOW( 3, "device: %02X%02X%02X",
42 		di->pcii.bus, di->pcii.device, di->pcii.function );
43 
44 	si->regs_area = si->fb_area = 0;
45 
46 	// enable memory mapped IO and frame buffer
47 	// also, enable bus mastering (some BIOSes seem to
48 	// disable that, like mine)
49 	tmp = get_pci( PCI_command, 2 );
50 	SHOW_FLOW( 3, "old PCI command state: 0x%08lx", tmp );
51 	tmp |= PCI_command_io | PCI_command_memory | PCI_command_master;
52 	set_pci( PCI_command, 2, tmp );
53 
54 	// registers cannot be accessed directly by user apps,
55 	// they need to clone area for safety reasons
56 	SHOW_INFO( 1, "physical address of memory-mapped I/O: 0x%8lx-0x%8lx",
57 		di->pcii.u.h0.base_registers[regs],
58 		di->pcii.u.h0.base_registers[regs] + di->pcii.u.h0.base_register_sizes[regs] - 1 );
59 
60 	sprintf( buffer, "%04X_%04X_%02X%02X%02X regs",
61 		di->pcii.vendor_id, di->pcii.device_id,
62 		di->pcii.bus, di->pcii.device, di->pcii.function );
63 
64 	si->regs_area = map_physical_memory(
65 		buffer,
66 		(void *) di->pcii.u.h0.base_registers[regs],
67 		di->pcii.u.h0.base_register_sizes[regs],
68 		B_ANY_KERNEL_ADDRESS,
69 		0,
70 		(void **)&(di->regs));
71 	if( si->regs_area < 0 )
72 		return si->regs_area;
73 
74 	if( mmio_only )
75 		return B_OK;
76 
77 	if( di->pcii.u.h0.base_register_sizes[fb] > di->local_mem_size ) {
78 		// Radeons allocate more address range then really needed ->
79 		// only map the area that contains physical memory
80 		SHOW_INFO( 1, "restrict frame buffer from 0x%8lx to 0x%8lx bytes",
81 			di->pcii.u.h0.base_register_sizes[fb],
82 			di->local_mem_size
83 		);
84 		di->pcii.u.h0.base_register_sizes[fb] = di->local_mem_size;
85 	}
86 
87 	// framebuffer can be accessed by everyone
88 	// this is not a perfect solution; preferably, only
89 	// those areas owned by an application are mapped into
90 	// its address space
91 	SHOW_INFO( 1, "physical address of framebuffer: 0x%8lx-0x%8lx",
92 		di->pcii.u.h0.base_registers[fb],
93 		di->pcii.u.h0.base_registers[fb] + di->pcii.u.h0.base_register_sizes[fb] - 1 );
94 
95 	sprintf(buffer, "%04X_%04X_%02X%02X%02X framebuffer",
96 		di->pcii.vendor_id, di->pcii.device_id,
97 		di->pcii.bus, di->pcii.device, di->pcii.function);
98 
99 	si->fb_area = map_physical_memory(
100 		buffer,
101 		(void *) di->pcii.u.h0.base_registers[fb],
102 		di->pcii.u.h0.base_register_sizes[fb],
103 		B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC,
104 		B_READ_AREA + B_WRITE_AREA,
105 		(void **)&(si->framebuffer));
106 
107 	if (si->fb_area < 0) {
108 		SHOW_FLOW0( 3, "couldn't enable WC for frame buffer" );
109 		si->fb_area = map_physical_memory(
110 			buffer,
111 			(void *) di->pcii.u.h0.base_registers[fb],
112 			di->pcii.u.h0.base_register_sizes[fb],
113 			B_ANY_KERNEL_BLOCK_ADDRESS,
114 			B_READ_AREA + B_WRITE_AREA,
115 			(void **)&(si->framebuffer));
116 	}
117 
118 	SHOW_FLOW( 3, "mapped frame buffer @%p", si->framebuffer );
119 
120 	if (si->fb_area < 0) {
121 		result = si->fb_area;
122 		goto err;
123 	}
124 
125 	// save physical address though noone can probably make
126 	// any use of it
127 	si->framebuffer_pci = (void *) di->pcii.u.h0.base_registers_pci[fb];
128 
129 	return B_OK;
130 
131 err:
132 	delete_area(si->regs_area);
133 	return result;
134 }
135 
136 
137 // unmap PCI ranges
138 void Radeon_UnmapDevice(device_info *di)
139 {
140 	shared_info *si = di->si;
141 	pci_info *pcii = &(di->pcii);
142 	uint32 tmp;
143 
144 	SHOW_FLOW0( 3, "" );
145 
146 	// disable PCI ranges (though it probably won't
147 	// hurt	leaving them enabled)
148 	tmp = get_pci( PCI_command, 2 );
149 	tmp &= ~PCI_command_io | PCI_command_memory | PCI_command_master;
150 	set_pci( PCI_command, 2, tmp );
151 
152 	if( si->regs_area > 0 )
153 		delete_area( si->regs_area );
154 
155 	if( si->fb_area > 0 )
156 		delete_area( si->fb_area );
157 
158 	si->regs_area = si->fb_area = 0;
159 }
160 
161 
162 // initialize shared infos on first open
163 status_t Radeon_FirstOpen( device_info *di )
164 {
165 	status_t result;
166 	char buffer[B_OS_NAME_LENGTH];
167 	shared_info *si;
168 	//uint32 /*dma_block, */dma_offset;
169 
170 	// create shared info; don't allow access by apps -
171 	// they'll clone it
172 	sprintf( buffer, "%04X_%04X_%02X%02X%02X shared",
173 		di->pcii.vendor_id, di->pcii.device_id,
174 		di->pcii.bus, di->pcii.device, di->pcii.function );
175 
176 	di->shared_area = create_area(
177 		buffer,
178 		(void **)&(di->si),
179 		B_ANY_KERNEL_ADDRESS,
180 		(sizeof(shared_info) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1),
181 		B_FULL_LOCK, 0);
182 	if (di->shared_area < 0) {
183 		result = di->shared_area;
184 		goto err8;
185 	}
186 
187 	memset( di->si, 0, sizeof( *di->si ));
188 
189 	si = di->si;
190 
191 #ifdef ENABLE_LOGGING
192 	si->log = log_init( 1000000 );
193 #endif
194 
195 	// copy all info into shared info
196 	si->vendor_id = di->pcii.vendor_id;
197 	si->device_id = di->pcii.device_id;
198 	si->revision = di->pcii.revision;
199 
200 	si->has_crtc2 = di->has_crtc2;
201 	si->asic = di->asic;
202 
203 	si->ports[0].disp_type = di->disp_type[0];
204 	si->ports[1].disp_type = di->disp_type[1];
205 	si->fp_port = di->fp_info;
206 	si->pll = di->pll;
207 /*	si->ram = di->ram;
208 	strcpy( si->ram_type, di->ram_type );*/
209 	si->local_mem_size = di->local_mem_size;
210 
211 	// create virtual card info; don't allow access by apps -
212 	// they'll clone it
213 	sprintf( buffer, "%04X_%04X_%02X%02X%02X virtual card 0",
214 		di->pcii.vendor_id, di->pcii.device_id,
215 		di->pcii.bus, di->pcii.device, di->pcii.function );
216 	di->virtual_card_area = create_area(
217 		buffer,
218 		(void **)&(di->vc),
219 		B_ANY_KERNEL_ADDRESS,
220 		(sizeof(virtual_card) + (B_PAGE_SIZE - 1)) & ~(B_PAGE_SIZE - 1),
221 		B_FULL_LOCK, 0);
222 	if (di->virtual_card_area < 0) {
223 		result = di->virtual_card_area;
224 		goto err5;
225 	}
226 
227 	// currently, we assign fixed ports to this virtual card
228 	di->vc->num_ports = si->has_crtc2 ? 2 : 1;
229 	di->vc->ports[0].is_crtc2 = false;
230 	di->vc->ports[0].physical_port = 0;
231 	di->vc->ports[1].is_crtc2 = true;
232 	di->vc->ports[1].physical_port = 1;
233 
234 	di->vc->fb_mem_handle = 0;
235 	di->vc->cursor.mem_handle = 0;
236 
237 	// create unique id
238 	di->vc->id = di->virtual_card_area;
239 
240 	result = Radeon_MapDevice( di, false );
241 	if (result < 0)
242 		goto err4;
243 
244 	// save dac2_cntl register
245 	// we need to restore that during uninit, else you only get
246 	// garbage on screen on reboot
247 	if( di->has_crtc2 )
248 		di->dac2_cntl = INREG( di->regs, RADEON_DAC_CNTL2 );
249 
250 	result = Radeon_InitDMA( di );
251 	if( result < 0 )
252 		goto err3;
253 
254 	// currently, we don't support VLI - something is broken there
255 	// (it doesn't change a thing apart from crashing)
256 /*	result = Radeon_SetupIRQ( di, buffer );
257 	if( result < 0 )
258 		goto err2;*/
259 
260 	di->local_memmgr = mem_init( 0, di->local_mem_size, 1024,
261 		di->local_mem_size / 1024 );
262 	if( di->local_memmgr == NULL ) {
263 		result = B_NO_MEMORY;
264 		goto err1;
265 	}
266 
267 	//Radeon_Fix_AGP();
268 
269 //	mem_alloc( di->local_memmgr, 0x100000, (void *)-1, &dma_block, &dma_offset );
270 /*	dma_offset = 15 * 1024 * 1024;
271 
272 	si->nonlocal_mem = (uint32 *)((uint32)si->framebuffer + dma_offset);
273 	si->nonlocal_vm_start = (uint32)si->framebuffer_pci + dma_offset;*/
274 
275 	return B_OK;
276 
277 err1:
278 	/*Radeon_CleanupIRQ( di );
279 err2:*/
280 	Radeon_CleanupDMA( di );
281 err3:
282 	Radeon_UnmapDevice( di );
283 err4:
284 	delete_area( di->virtual_card_area );
285 err5:
286 	delete_area( di->shared_area );
287 err8:
288 	return result;
289 }
290 
291 // clean up shared info on last close
292 // (we could for device destruction, but this makes
293 // testing easier as everythings gets cleaned up
294 // during tests)
295 void Radeon_LastClose( device_info *di )
296 {
297 	if( di->has_crtc2 )
298 		OUTREG( di->regs, RADEON_DAC_CNTL2, di->dac2_cntl );
299 
300 	mem_destroy( di->local_memmgr );
301 
302 //	Radeon_CleanupIRQ( di );
303 	Radeon_CleanupDMA( di );
304 	Radeon_UnmapDevice(di);
305 
306 #ifdef ENABLE_LOGGING
307 	log_exit( di->si->log );
308 #endif
309 
310 	delete_area( di->virtual_card_area );
311 	delete_area( di->shared_area );
312 }
313