xref: /haiku/src/add-ons/kernel/drivers/graphics/radeon/driver.c (revision 67bce78b48ed6d01b5a8eef89f5694c372b7e0a1)
1 /*
2 	Copyright (c) 2002, Thomas Kurschel
3 
4 
5 	Part of Radeon kernel driver
6 
7 	DevFS interface
8 */
9 
10 #include "radeon_driver.h"
11 #ifdef ENABLE_LOGGING
12 #include "log_coll.h"
13 #endif
14 
15 #include <OS.h>
16 #include <malloc.h>
17 #include <graphic_driver.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <mmio.h>
21 #include <version.h>
22 
23 // tell the kernel what revision of the driver API we support
24 //int32	api_version = 2;
25 int32	api_version = B_CUR_DRIVER_API_VERSION; // apsed, was 2, is 2 in R5
26 
27 
28 static status_t open_hook( const char *name, uint32 flags, void **cookie );
29 static status_t close_hook( void *dev );
30 static status_t free_hook( void *dev );
31 static status_t read_hook( void *dev, off_t pos, void *buf, size_t *len );
32 static status_t write_hook( void *dev, off_t pos, const void *buf, size_t *len );
33 static status_t control_hook( void *dev, uint32 msg, void *buf, size_t len );
34 
35 
36 static device_hooks graphics_device_hooks = {
37 	open_hook,
38 	close_hook,
39 	free_hook,
40 	control_hook,
41 	read_hook,
42 	write_hook,
43 	NULL,
44 	NULL,
45 	NULL,
46 	NULL
47 };
48 
49 
50 // public function: check whether there is *any* supported hardware
51 status_t init_hardware( void )
52 {
53 	SHOW_INFO0( 0, RADEON_DRIVER_VERSION );
54 	if( Radeon_CardDetect() == B_OK )
55 		return B_OK;
56 	else
57 		return B_ERROR;
58 }
59 
60 
61 // public function: init driver
62 status_t init_driver( void )
63 {
64 	if( get_module(B_PCI_MODULE_NAME, (module_info **)&pci_bus) != B_OK )
65 		return B_ERROR;
66 
67 	/* driver private data */
68 	devices = (radeon_devices *)calloc( 1, sizeof( radeon_devices ));
69 	if( devices == NULL ) {
70 		put_module(B_PCI_MODULE_NAME);
71 		return B_ERROR;
72 	}
73 
74 	INIT_BEN( "Radeon Kernel", devices->kernel);
75 
76 	Radeon_ProbeDevices();
77 	return B_OK;
78 }
79 
80 
81 // public function: uninit driver
82 void uninit_driver( void )
83 {
84 	DELETE_BEN( devices->kernel );
85 
86 	free( devices );
87 	devices = NULL;
88 
89 	put_module( B_PCI_MODULE_NAME );
90 }
91 
92 
93 // public function: return list of device names
94 const char **publish_devices( void )
95 {
96 	return (const char **)devices->device_names;
97 }
98 
99 
100 // public function: find hooks for specific device given its name
101 device_hooks *find_device( const char *name )
102 {
103 	uint32 index;
104 
105 	// probably, we could always return standard hooks
106 	for( index = 0; devices->device_names[index]; ++index ) {
107 		if( strcmp( name, devices->device_names[index] ) == 0 )
108 			return &graphics_device_hooks;
109 	}
110 
111 	return NULL;
112 }
113 
114 
115 // public function: open device
116 static status_t open_hook( const char *name, uint32 flags, void **cookie )
117 {
118 	int32 index = 0;
119 	device_info *di;
120 	status_t	result = B_OK;
121 
122 	SHOW_FLOW( 3, "name=%s, flags=%ld, cookie=0x%08lx", name, flags, (uint32)cookie );
123 
124 	// find device info
125 	while( devices->device_names[index] &&
126 		strcmp(name, devices->device_names[index] ) != 0 )
127 		index++;
128 
129 	di = &(devices->di[index]);
130 
131 	ACQUIRE_BEN( devices->kernel );
132 
133 	if( !di->is_open )
134 		result = Radeon_FirstOpen( di );
135 
136 	if( result == B_OK ) {
137 		di->is_open++;
138 		*cookie = di;
139 	}
140 
141 	RELEASE_BEN( devices->kernel );
142 
143 	SHOW_FLOW( 3, "returning 0x%08lx", result );
144 	return result;
145 }
146 
147 
148 // public function: read from device (denied)
149 static status_t read_hook( void *dev, off_t pos, void *buf, size_t *len )
150 {
151 	*len = 0;
152 	return B_NOT_ALLOWED;
153 }
154 
155 
156 // public function: write to device (denied)
157 static status_t write_hook( void *dev, off_t pos, const void *buf, size_t *len )
158 {
159 	*len = 0;
160 	return B_NOT_ALLOWED;
161 }
162 
163 
164 // public function: close device (ignored, wait for free_hook instead)
165 static status_t close_hook( void *dev )
166 {
167 	return B_NO_ERROR;
168 }
169 
170 
171 // public function: free device
172 static status_t free_hook( void *dev )
173 {
174 	device_info *di = (device_info *)dev;
175 
176 	SHOW_FLOW0( 3, "" );
177 
178 	ACQUIRE_BEN( devices->kernel );
179 
180 	mem_freetag( di->local_memmgr, dev );
181 
182 	if( di->is_open == 1 )
183 		Radeon_LastClose( di );
184 
185 	di->is_open--;
186 	RELEASE_BEN( devices->kernel );
187 
188 	return B_OK;
189 }
190 
191 
192 // public function: ioctl
193 static status_t control_hook( void *dev, uint32 msg, void *buf, size_t len )
194 {
195 	device_info *di = (device_info *)dev;
196 	status_t result = B_DEV_INVALID_IOCTL;
197 
198 	switch (msg) {
199 		// needed by app_server to load accelerant
200 		case B_GET_ACCELERANT_SIGNATURE: {
201 			char *sig = (char *)buf;
202 			//strcpy(sig, "radeon2.accelerant");
203 			strcpy(sig, "radeon.accelerant");
204 			result = B_OK;
205 		} break;
206 
207 		// needed to share data between kernel and accelerant
208 		case RADEON_GET_PRIVATE_DATA: {
209 			radeon_get_private_data *gpd = (radeon_get_private_data *)buf;
210 
211 			if (gpd->magic == RADEON_PRIVATE_DATA_MAGIC) {
212 				gpd->shared_info_area = di->shared_area;
213 				gpd->virtual_card_area = di->virtual_card_area;
214 				result = B_OK;
215 			}
216 		} break;
217 
218 		// needed for cloning
219 		case RADEON_DEVICE_NAME: {
220 			radeon_device_name *dn = (radeon_device_name *)buf;
221 
222 			if( dn->magic == RADEON_PRIVATE_DATA_MAGIC ) {
223 				strncpy( dn->name, di->name, MAX_RADEON_DEVICE_NAME_LENGTH );
224 				result = B_OK;
225 			}
226 		} break;
227 
228 		// graphics mem manager
229 		case RADEON_ALLOC_LOCAL_MEM: {
230 			radeon_alloc_local_mem *am = (radeon_alloc_local_mem *)buf;
231 
232 			if( am->magic == RADEON_PRIVATE_DATA_MAGIC )
233 				result = mem_alloc( di->local_memmgr, am->size, dev, &am->handle, &am->fb_offset );
234 		} break;
235 
236 		case RADEON_FREE_LOCAL_MEM: {
237 			radeon_free_local_mem *fm = (radeon_free_local_mem *)buf;
238 
239 			if( fm->magic == RADEON_PRIVATE_DATA_MAGIC )
240 				result = mem_free( di->local_memmgr, fm->handle, dev );
241 		} break;
242 
243 		// interface to log data
244 #ifdef ENABLE_LOGGING
245 		case RADEON_GET_LOG_SIZE:
246 			*(uint32 *)buf = log_getsize( di->si->log );
247 			result = B_OK;
248 			break;
249 
250 		case RADEON_GET_LOG_DATA:
251 			log_getcopy( di->si->log, buf, ((uint32 *)buf)[0] );
252 			result = B_OK;
253 			break;
254 #endif
255 
256 		// interface to i2c-bus
257 		case RADEON_SET_I2C_SIGNALS: {
258 			radeon_getset_i2c *data = (radeon_getset_i2c *)buf;
259 
260 			if( data->magic == RADEON_PRIVATE_DATA_MAGIC ) {
261 				result = B_OK;
262 				OUTREG( di->regs, data->port, data->value );
263 			}
264 			break; }
265 		case RADEON_GET_I2C_SIGNALS: {
266 			radeon_getset_i2c *data = (radeon_getset_i2c *)buf;
267 
268 			if( data->magic == RADEON_PRIVATE_DATA_MAGIC ) {
269 				result = B_OK;
270 				data->value = INREG( di->regs, data->port );
271 			}
272 			break; }
273 	}
274 	return result;
275 }
276