Initial commit
[fireglload.git] / main.c
1 /*
2  * fireglload
3  * (C) notaz, 2014
4  *
5  * This work is licensed under the terms of 3-clause BSD license.
6  * See COPYING file in the top-level directory.
7  */
8
9 #include <stdio.h>
10 #include <dlfcn.h>
11 #include <pthread.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <time.h>
17
18 #include <pciaccess.h>
19
20 #include <xorg/xf86.h>
21 #include <xorg/xf86Module.h>
22 #include <xorg/xf86str.h>
23
24 #if 0
25 #define TRACE(f, ...) \
26         fprintf(stderr, ". %s " f, __FUNCTION__, ##__VA_ARGS__)
27 #define NI() \
28         fprintf(stderr, "NI: %s\n", __FUNCTION__)
29 #else
30 #define TRACE(...)
31 #define NI()
32 #endif
33
34 #ifndef _X_EXPORT
35 #define _X_EXPORT      __attribute__((visibility("default")))
36 #endif
37
38 static GDevRec drec;
39
40 #ifdef DIX_H
41 _X_EXPORT ClientPtr clients[MAXCLIENTS];
42 _X_EXPORT ScreenInfo screenInfo;
43 _X_EXPORT ClientPtr serverClient;
44 #else
45 #define MAXCLIENTS      256
46 _X_EXPORT void *clients[MAXCLIENTS];
47 _X_EXPORT long screenInfo[16]; // ScreenInfo
48 _X_EXPORT void *serverClient;
49 #endif
50 #ifdef _XF86_H
51 _X_EXPORT ScrnInfoPtr *xf86Screens;
52 _X_EXPORT confDRIRec xf86ConfigDRI;
53 #else
54 _X_EXPORT void *xf86Screens;
55 _X_EXPORT long xf86ConfigDRI[4]; // confDRIRec
56 #endif
57 _X_EXPORT int PanoramiXNumScreens;
58 _X_EXPORT long inputInfo[16]; // InputInfo
59 _X_EXPORT unsigned long globalSerialNumber = 0;
60 _X_EXPORT unsigned long serverGeneration = 0;
61 _X_EXPORT int noPanoramiXExtension;
62 _X_EXPORT int noRRExtension;
63 _X_EXPORT int noCompositeExtension;
64 _X_EXPORT int noRenderExtension;
65 _X_EXPORT char dispatchException;
66 _X_EXPORT void *xf86DriverList;
67 _X_EXPORT int xf86NumDrivers;
68 _X_EXPORT void *xf86configptr;
69 _X_EXPORT int xf86DefaultModes[1024]; // DisplayModeRec[]
70 _X_EXPORT int xf86Info[64]; // xf86InfoRec
71 _X_EXPORT int xf86Initialising;
72 _X_EXPORT int XRT_WINDOW;
73 _X_EXPORT int monitorResolution;
74 _X_EXPORT int DPMSEnabled;
75 #define SCREEN_SAVER_OFF  1
76 _X_EXPORT int screenIsSaved = SCREEN_SAVER_OFF;
77
78 #ifndef _XF86_H
79 _X_EXPORT void xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...);
80 _X_EXPORT Bool xf86LoaderCheckSymbol(const char *name);
81 _X_EXPORT void xf86AddDriver(DriverPtr driver, pointer module, int flags);
82 #endif
83 _X_EXPORT void GetSpritePosition(struct _DeviceIntRec*, int *, int *);
84 _X_EXPORT int xf86LoadKernelModule(const char *pathname);
85
86 // don't delete my globals..
87 extern void ddmg(void *g);
88
89 static void __attribute__((constructor)) ddmg_hack(void)
90 {
91         ddmg(&clients);
92         ddmg(&PanoramiXNumScreens);
93         ddmg(&inputInfo);
94         ddmg(&screenInfo);
95         ddmg(&globalSerialNumber);
96         ddmg(&serverGeneration);
97         ddmg(&noPanoramiXExtension);
98         ddmg(&noRRExtension);
99         ddmg(&noCompositeExtension);
100         ddmg(&noRenderExtension);
101         ddmg(&dispatchException);
102         ddmg(&xf86Screens);
103         ddmg(&xf86DriverList);
104         ddmg(&xf86NumDrivers);
105         ddmg(&xf86configptr);
106         ddmg(&xf86DefaultModes);
107         ddmg(&xf86Info);
108         ddmg(&xf86ConfigDRI);
109         ddmg(&xf86Initialising);
110         ddmg(&serverClient);
111         ddmg(&XRT_WINDOW);
112         ddmg(&monitorResolution);
113         ddmg(&DPMSEnabled);
114         ddmg(&screenIsSaved);
115
116         ddmg(&LoadSubModule);
117         ddmg(&LoaderSymbol);
118         ddmg(&xf86LoaderCheckSymbol);
119         ddmg(&xf86DrvMsg);
120         ddmg(&xf86VDrvMsgVerb);
121         ddmg(&xf86Msg);
122         ddmg(&xf86MsgVerb);
123         ddmg(&xf86AddDriver);
124         ddmg(&GetSpritePosition);
125         ddmg(&XNFalloc);
126         ddmg(&XNFcalloc);
127         ddmg(&XNFrealloc);
128         ddmg(&xf86MatchDevice);
129         ddmg(&xf86LoadKernelModule);
130         ddmg(&xf86MatchPciInstances);
131         ddmg(&xf86CheckPciSlot);
132         ddmg(&xf86ConfigPciEntity);
133         ddmg(&xf86ComparePciBusString);
134         ddmg(&xf86ClaimPciSlot);
135         ddmg(&xf86GetPciInfoForEntity);
136         ddmg(&xf86GetEntityInfo);
137         ddmg(&xf86AllocateEntityPrivateIndex);
138         ddmg(&xf86GetEntityPrivate);
139         ddmg(&xf86SetEntitySharable);
140         ddmg(&xf86GetNumEntityInstances);
141         ddmg(&xf86GetDevFromEntity);
142         ddmg(&xf86AddBusDeviceToConfigure);
143         ddmg(&GetTimeInMillis);
144         ddmg(&xf86GetOptValBool);
145 }
146
147 #define MAKE_FUNC(name) \
148 int _X_EXPORT name() \
149 { \
150         NI(); \
151         return 0; \
152 } \
153 static void __attribute__((constructor)) c_##name(void) \
154 { \
155         ddmg(&name); \
156 }
157
158 MAKE_FUNC(xf86SetDGAMode)
159 MAKE_FUNC(GetSpriteCursor)
160 MAKE_FUNC(StandardMinorOpcode)
161
162 void
163 GetSpritePosition(struct _DeviceIntRec *pDev, int *px, int *py)
164 {
165         NI();
166 }
167
168 pointer
169 LoadSubModule(pointer _parent, const char *module,
170               const char **subdirlist, const char **patternlist,
171               pointer options, const XF86ModReqInfo * modreq,
172               int *errmaj, int *errmin)
173 {
174         void *ret;
175
176         printf("LoadSubModule '%s'\n", module);
177
178         if (module && strstr(module, "fglrxdrm"))
179                 module = "/usr/lib/xorg/modules/linux/libfglrxdrm.so";
180         ret = dlopen(module, RTLD_LAZY | RTLD_GLOBAL);
181         if (ret == NULL)
182                 fprintf(stderr, "LoadSubModule dlopen: %s\n", dlerror());
183
184         return ret;
185 }
186
187 void *
188 LoaderSymbol(const char *name)
189 {
190         void *ret = dlsym(NULL, name);
191         TRACE("'%s' %p\n", name, ret);
192         return ret;
193 }
194
195 Bool
196 xf86LoaderCheckSymbol(const char *name)
197 {
198         Bool ret;
199
200         ret = (dlsym(NULL, name) != NULL);
201         TRACE("'%s' %d\n", name, ret);
202         return ret;
203 }
204
205 int
206 xf86MatchDevice(const char *drivername, GDevPtr **sectlist)
207 {
208         GDevRec **list;
209
210         TRACE("'%s' %p\n", drivername, sectlist);
211
212         if (sectlist == NULL)
213                 goto out;
214
215         *sectlist = NULL;
216         list = malloc(2 * sizeof(list[0]));
217         if (list == NULL)
218                 return 0;
219         list[0] = &drec;
220         list[1] = NULL;
221         *sectlist = list;
222
223 out:
224         return 1;
225 }
226
227 int
228 xf86MatchPciInstances(const char *driverName, int vendorID,
229                       SymTabPtr chipsets, PciChipsets *PCIchipsets,
230                       GDevPtr *devList, int numDevs, DriverPtr drvp,
231                       int **foundEntities)
232 {
233         TRACE("'%s' %04x %p %p %p %d %p %p\n",
234                 driverName, vendorID, chipsets, PCIchipsets, devList, numDevs,
235                 drvp, foundEntities);
236
237         *foundEntities = malloc(sizeof(int));
238         if (*foundEntities == NULL)
239                 return 0;
240
241         (*foundEntities)[0] = 0;
242         return 1;
243 }
244
245 GDevPtr
246 xf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData, int chipset)
247 {
248         struct pci_device *pci = busData;
249
250         TRACE("'%s' %d %p %d\n", driver, bus, busData, chipset);
251
252         drec.driver = strdup(driver);
253         drec.identifier = strdup("fake_dev");
254         drec.busID = malloc(64);
255         snprintf(drec.busID, 64, "PCI:%d:%d:%d", pci->bus, pci->dev, pci->func);
256         drec.chipID = pci->device_id;
257         drec.chipRev = pci->revision;
258         drec.irq = -1;
259
260         drec.myScreenSection = calloc(1, sizeof(*drec.myScreenSection));
261
262         TRACE("ret busID '%s'\n", drec.busID);
263         return &drec;
264 }
265
266 Bool
267 xf86CheckPciSlot(const struct pci_device *d)
268 {
269         TRACE("%p\n", d);
270         return TRUE;
271 }
272
273 ScrnInfoPtr
274 xf86ConfigPciEntity(ScrnInfoPtr pScrn, int scrnFlag, int entityIndex,
275                           PciChipsets *p_chip, void *dummy, EntityProc init,
276                           EntityProc enter, EntityProc leave, pointer private)
277 {
278         ScrnInfoPtr screen;
279
280         TRACE("%p %x %d %p %p %p %p %p %p\n",
281                 pScrn, scrnFlag, entityIndex, p_chip, dummy, init,
282                 enter, leave, private);
283
284         screen = calloc(1, sizeof(*screen));
285         screen->entityList = calloc(1, sizeof(screen->entityList[0]));
286         screen->numEntities = 1;
287         // used by atiddxIsCrossDisplay_3
288         screen->confScreen = calloc(1, sizeof(*screen->confScreen));
289
290         xf86Screens = calloc(2, sizeof(xf86Screens[0]));
291         return (xf86Screens[0] = screen);
292 }
293
294 Bool
295 xf86ComparePciBusString(const char *busID, int bus, int device, int func)
296 {
297         TRACE("'%s' %d:%d:%d\n", busID, bus, device, func);
298         return TRUE;
299 }
300
301 static struct pci_device *cur_pci_dev;
302
303 int
304 xf86ClaimPciSlot(struct pci_device *d, DriverPtr drvp,
305                  int chipset, GDevPtr dev, Bool active)
306 {
307         TRACE("%p %p %d %p %d\n", d, drvp, chipset, dev, active);
308         cur_pci_dev = d;
309
310         return 0;
311 }
312
313 struct pci_device *
314 xf86GetPciInfoForEntity(int entityIndex)
315 {
316         TRACE("%d\n", entityIndex);
317
318         return cur_pci_dev;
319 }
320
321 EntityInfoPtr
322 xf86GetEntityInfo(int entityIndex)
323 {
324         EntityInfoRec *ret;
325
326         TRACE("%d\n", entityIndex);
327
328         ret = calloc(1, sizeof(*ret));
329         ret->device = &drec;
330         ret->location.id.pci = cur_pci_dev;
331
332         return ret;
333 }
334
335 static int numprivs;
336 static DevUnion *privs;
337
338 int
339 xf86AllocateEntityPrivateIndex(void)
340 {
341         int ret;
342
343         ret = numprivs++;
344         TRACE("numprivs=%d\n", numprivs);
345
346         privs = realloc(privs, numprivs * sizeof(DevUnion));
347         return ret;
348 }
349
350 DevUnion *
351 xf86GetEntityPrivate(int entityIndex, int privIndex)
352 {
353         DevUnion *ret = NULL;
354
355         if (entityIndex != 0 || (unsigned int)privIndex > (unsigned int)numprivs)
356                 ret = NULL;
357         else
358                 ret = &privs[privIndex];
359
360         TRACE("%d %d; ret=%p\n", entityIndex, privIndex, ret);
361         return ret;
362 }
363
364 void
365 xf86SetEntitySharable(int entityIndex)
366 {
367         TRACE("%d\n", entityIndex);
368 }
369
370 int
371 xf86GetNumEntityInstances(int entityIndex)
372 {
373         TRACE("%d\n", entityIndex);
374         return 1;
375 }
376
377 GDevPtr
378 xf86GetDevFromEntity(int entityIndex, int instance)
379 {
380         TRACE("%d %d\n", entityIndex, instance);
381         return &drec;
382 }
383
384 int
385 xf86LoadKernelModule(const char *modName)
386 {
387         TRACE("'%s'\n", modName);
388         return 1;
389 }
390
391 pointer
392 XNFalloc(unsigned long n)
393 {
394         return malloc(n);
395 }
396
397 pointer
398 XNFcalloc(unsigned long n)
399 {
400         return calloc(1, n);
401 }
402
403 void *
404 XNFrealloc(void *ptr, unsigned long amount)
405 {
406         return realloc(ptr, amount);
407 }
408
409 void
410 xf86DrvMsg(int scrnIndex, MessageType type, const char *format, ...)
411 {   
412         va_list ap;
413
414         printf("xf86DrvMsg: ");             
415         va_start(ap, format);                                        
416         vprintf(format, ap);             
417         va_end(ap);
418         fflush(stdout);
419 }   
420
421 void
422 xf86VDrvMsgVerb(int scrnIndex, MessageType type, int verb, const char *format,
423                 va_list args)
424 {
425         printf("xf86VDrvMsgVerb: ");             
426         vprintf(format, args);             
427         fflush(stdout);
428 }
429
430 void xf86Msg(MessageType type, const char *format, ...)
431 {
432         va_list ap;
433
434         printf("xf86Msg: ");             
435         va_start(ap, format);                                        
436         vprintf(format, ap);             
437         va_end(ap);
438         fflush(stdout);
439 }
440
441 void xf86MsgVerb(MessageType type, int verb, const char *format, ...)
442 {
443         va_list ap;
444
445         printf("xf86MsgVerb: ");             
446         va_start(ap, format);                                        
447         vprintf(format, ap);             
448         va_end(ap);
449         fflush(stdout);
450 }
451
452 CARD32
453 GetTimeInMillis(void)
454 {
455         struct timespec tp;
456         clock_gettime(CLOCK_MONOTONIC, &tp);
457         return tp.tv_sec * 1000 + tp.tv_nsec / 1000000;
458 }
459
460 Bool
461 xf86GetOptValBool(const OptionInfoRec *table, int token, Bool *value)
462 {
463         TRACE("%p/%s %d %p\n", table, table ? table->name : NULL, token, value);
464         return FALSE;
465 }
466
467 static DriverPtr g_driver;
468
469 void
470 xf86AddDriver(DriverPtr driver, pointer module, int flags)
471 {
472         TRACE("%p %p %x\n", driver, module, flags);             
473         g_driver = driver;
474 }
475
476 static void scan_pci(void)
477 {
478         static struct pci_slot_match match = {
479                 PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0
480         };
481         struct pci_device_iterator *iter;
482         struct pci_device *info;
483         int ret;
484
485         ret = pci_system_init();
486         if (ret != 0) {
487                 fprintf(stderr, "pci_system_init failed\n");
488                 return;
489         }
490
491         iter = pci_slot_match_iterator_create(&match);
492         while ((info = pci_device_next(iter)) != NULL) {
493                 if ((info->device_class & 0xff0000) != 0x30000)
494                         // not display
495                         continue;
496
497                 pci_device_probe(info);
498                 if (pci_device_is_boot_vga(info))
499                         break;
500         }
501         pci_iterator_destroy(iter);
502
503         if (info == NULL) {
504                 fprintf(stderr, "no display devices?\n");
505                 return;
506         }
507
508         if (info->vendor_id != 0x1002) {
509                 fprintf(stderr, "not AMD display? (%04x)\n",
510                         info->vendor_id);
511                 return;
512         }
513
514         //exit(1);
515 }
516
517 static int module_desc[64];
518
519 int main(int argc, char *argv[])
520 {
521         XF86ModuleData *mod_data;
522         ScrnInfoPtr screen = NULL;
523         pthread_mutex_t mutex;
524         int errmaj = 0, errmin = 0;
525         int retval = 1;
526         void *setup_ret;
527         void *mod;
528         int fd, ret;
529
530         // init pthreads
531         pthread_mutex_init(&mutex, NULL);
532
533 #if 0
534         // preload libpciaccess as it's not in fglrx's deps
535         mod = dlopen("libpciaccess.so", RTLD_LAZY | RTLD_GLOBAL);
536         if (mod == NULL)
537                 fprintf(stderr, "preload pciaccess: %s\n", dlerror());
538 #endif
539         // fglrx relies on pci_system_init() being called too
540         scan_pci();
541
542         mod = dlopen("/usr/lib/xorg/modules/drivers/fglrx_drv.so",
543                 RTLD_LAZY | RTLD_GLOBAL);
544         if (mod == NULL) {
545                 fprintf(stderr, "open module: %s\n", dlerror());
546                 return 1;
547         }
548
549         mod_data = dlsym(mod, "fglrxModuleData");
550         if (mod_data == NULL) {
551                 fprintf(stderr, "dlsym fglrxModuleData: %s\n", dlerror());
552                 goto out;
553         }
554
555         if (mod_data->vers == NULL) {
556                 fprintf(stderr, "mod_data->vers is NULL\n");
557                 goto out;
558         }
559
560         printf("name: %s\n", mod_data->vers->modname);
561         printf("vendor: %s\n", mod_data->vers->vendor);
562         printf("abiclass: %s\n", mod_data->vers->abiclass);
563         printf("moduleclass: %s\n", mod_data->vers->moduleclass);
564         printf("version: %u.%u.%u\n", mod_data->vers->majorversion,
565                 mod_data->vers->minorversion, mod_data->vers->patchlevel);
566         fflush(stdout);
567
568         // fglrx assumes descriptor 0 to be Xorg.log
569         fd = open("/var/log/Xorg.0.log", O_RDONLY);
570         if (fd == -1) {
571                 perror("open Xorg.0.log");
572                 goto out;
573         }
574         ret = dup2(fd, 0);
575         if (ret == -1) {
576                 perror("dup2");
577                 goto out;
578         }
579
580         if (mod_data->setup == NULL) {
581                 fprintf(stderr, "mod_data->setup is NULL\n");
582                 goto out;
583         }
584
585         setup_ret = mod_data->setup(module_desc, NULL, &errmaj, &errmin);
586         printf("setup: %p, errmaj %u, errmin %u\n", setup_ret, errmaj, errmin);
587         if (setup_ret == NULL) {
588                 fprintf(stderr, "setup() returned NULL\n");
589                 goto out;
590         }
591
592         if (g_driver == NULL) {
593                 fprintf(stderr, "setup() did not provide driver ptr\n");
594                 goto out;
595         }
596
597         printf("driverName: %s\n", g_driver->driverName);
598         if (g_driver->Probe == NULL) {
599                 fprintf(stderr, "Probe is NULL\n");
600                 goto out;
601         }
602
603         // #0  in xdl_xs111_atiddxPxEarlyCheck ()
604         // #1  in xdl_xs111_atiddxProbe ()
605         // #2  in atiddxProbe ()
606         ret = g_driver->Probe(g_driver, PROBE_DETECT);
607         printf("Probe(PROBE_DETECT): %d\n", ret);
608         if (!ret)
609                 goto out;
610
611         ret = g_driver->Probe(g_driver, PROBE_DEFAULT);
612         printf("Probe(PROBE_DEFAULT): %d\n", ret);
613         if (!ret)
614                 goto out;
615
616 #if 0
617         if (xf86Screens == NULL || xf86Screens[0] == NULL) {
618                 fprintf(stderr, "xf86Screens[0] did not get set\n");
619                 goto out;
620         }
621         screen = xf86Screens[0];
622         if (screen->PreInit == NULL) {
623                 fprintf(stderr, "screen->PreInit did not get set\n");
624                 goto out;
625         }
626         ret = screen->PreInit(screen, 0);
627         printf("PreInit: %d\n", ret);
628 #endif
629
630         retval = !ret;
631
632 out:
633         (void)screen;
634         dlclose(mod);
635         return retval;
636 }