Initial commit
[fireglload.git] / main.c
CommitLineData
4c793154 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
38static 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..
87extern void ddmg(void *g);
88
89static 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) \
148int _X_EXPORT name() \
149{ \
150 NI(); \
151 return 0; \
152} \
153static void __attribute__((constructor)) c_##name(void) \
154{ \
155 ddmg(&name); \
156}
157
158MAKE_FUNC(xf86SetDGAMode)
159MAKE_FUNC(GetSpriteCursor)
160MAKE_FUNC(StandardMinorOpcode)
161
162void
163GetSpritePosition(struct _DeviceIntRec *pDev, int *px, int *py)
164{
165 NI();
166}
167
168pointer
169LoadSubModule(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
187void *
188LoaderSymbol(const char *name)
189{
190 void *ret = dlsym(NULL, name);
191 TRACE("'%s' %p\n", name, ret);
192 return ret;
193}
194
195Bool
196xf86LoaderCheckSymbol(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
205int
206xf86MatchDevice(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
223out:
224 return 1;
225}
226
227int
228xf86MatchPciInstances(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
245GDevPtr
246xf86AddBusDeviceToConfigure(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
266Bool
267xf86CheckPciSlot(const struct pci_device *d)
268{
269 TRACE("%p\n", d);
270 return TRUE;
271}
272
273ScrnInfoPtr
274xf86ConfigPciEntity(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
294Bool
295xf86ComparePciBusString(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
301static struct pci_device *cur_pci_dev;
302
303int
304xf86ClaimPciSlot(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
313struct pci_device *
314xf86GetPciInfoForEntity(int entityIndex)
315{
316 TRACE("%d\n", entityIndex);
317
318 return cur_pci_dev;
319}
320
321EntityInfoPtr
322xf86GetEntityInfo(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
335static int numprivs;
336static DevUnion *privs;
337
338int
339xf86AllocateEntityPrivateIndex(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
350DevUnion *
351xf86GetEntityPrivate(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
364void
365xf86SetEntitySharable(int entityIndex)
366{
367 TRACE("%d\n", entityIndex);
368}
369
370int
371xf86GetNumEntityInstances(int entityIndex)
372{
373 TRACE("%d\n", entityIndex);
374 return 1;
375}
376
377GDevPtr
378xf86GetDevFromEntity(int entityIndex, int instance)
379{
380 TRACE("%d %d\n", entityIndex, instance);
381 return &drec;
382}
383
384int
385xf86LoadKernelModule(const char *modName)
386{
387 TRACE("'%s'\n", modName);
388 return 1;
389}
390
391pointer
392XNFalloc(unsigned long n)
393{
394 return malloc(n);
395}
396
397pointer
398XNFcalloc(unsigned long n)
399{
400 return calloc(1, n);
401}
402
403void *
404XNFrealloc(void *ptr, unsigned long amount)
405{
406 return realloc(ptr, amount);
407}
408
409void
410xf86DrvMsg(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
421void
422xf86VDrvMsgVerb(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
430void 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
441void 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
452CARD32
453GetTimeInMillis(void)
454{
455 struct timespec tp;
456 clock_gettime(CLOCK_MONOTONIC, &tp);
457 return tp.tv_sec * 1000 + tp.tv_nsec / 1000000;
458}
459
460Bool
461xf86GetOptValBool(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
467static DriverPtr g_driver;
468
469void
470xf86AddDriver(DriverPtr driver, pointer module, int flags)
471{
472 TRACE("%p %p %x\n", driver, module, flags);
473 g_driver = driver;
474}
475
476static 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
517static int module_desc[64];
518
519int 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
632out:
633 (void)screen;
634 dlclose(mod);
635 return retval;
636}