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