db.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <ndb.h>
  5. #include "pci.h"
  6. #include "vga.h"
  7. static Ndb*
  8. dbopen(char* dbname)
  9. {
  10. Ndb *db;
  11. if((db = ndbopen(dbname)) == 0)
  12. error("dbopen: %s: %r\n", dbname);
  13. return db;
  14. }
  15. static void
  16. addattr(Attr** app, Ndbtuple* t)
  17. {
  18. Attr *attr, *l;
  19. attr = alloc(sizeof(Attr));
  20. attr->attr = alloc(strlen(t->attr)+1);
  21. strcpy(attr->attr, t->attr);
  22. attr->val = alloc(strlen(t->val)+1);
  23. strcpy(attr->val, t->val);
  24. for(l = *app; l; l = l->next)
  25. app = &l->next;
  26. *app = attr;
  27. }
  28. char*
  29. dbattr(Attr* ap, char* attr)
  30. {
  31. while(ap){
  32. if(strcmp(ap->attr, attr) == 0)
  33. return ap->val;
  34. ap = ap->next;
  35. }
  36. return 0;
  37. }
  38. static Ctlr*
  39. addctlr(Vga* vga, char* val)
  40. {
  41. Ctlr **ctlr;
  42. char name[Namelen+1], *p;
  43. int i;
  44. /*
  45. * A controller name may have an extension on the end
  46. * following a '-' which can be used as a speed grade or
  47. * subtype. Do the match without the extension.
  48. * The linked copy of the controller struct gets the
  49. * full name with extension.
  50. */
  51. strncpy(name, val, Namelen);
  52. name[Namelen] = 0;
  53. if(p = strchr(name, '-'))
  54. *p = 0;
  55. for(i = 0; ctlrs[i]; i++){
  56. if(strcmp(ctlrs[i]->name, name))
  57. continue;
  58. for(ctlr = &vga->link; *ctlr; ctlr = &((*ctlr)->link))
  59. ;
  60. *ctlr = alloc(sizeof(Ctlr));
  61. **ctlr = *ctlrs[i];
  62. strncpy((*ctlr)->name, val, Namelen);
  63. return *ctlr;
  64. }
  65. fprint(2, "dbctlr: unknown controller \"%s\" ctlr\n", val);
  66. return 0;
  67. }
  68. int
  69. dbbios(Vga *vga, Ndbtuple *tuple)
  70. {
  71. char *bios, *p, *string;
  72. int len;
  73. long offset, offset1;
  74. Ndbtuple *t;
  75. for(t = tuple->entry; t; t = t->entry){
  76. if((offset = strtol(t->attr, 0, 0)) == 0)
  77. continue;
  78. string = t->val;
  79. len = strlen(string);
  80. if(p = strchr(t->attr, '-')) {
  81. if((offset1 = strtol(p+1, 0, 0)) < offset+len)
  82. continue;
  83. } else
  84. offset1 = offset+len;
  85. if(vga->offset) {
  86. if(offset > vga->offset || vga->offset+len > offset1)
  87. continue;
  88. offset = vga->offset;
  89. offset1 = offset+len;
  90. }
  91. for(; offset+len<=offset1; offset++) {
  92. if(vga->bios)
  93. bios = vga->bios;
  94. else
  95. bios = readbios(len, offset);
  96. if(strncmp(bios, string, len) == 0){
  97. if(vga->bios == 0){
  98. vga->bios = alloc(len+1);
  99. strncpy(vga->bios, bios, len);
  100. }
  101. addattr(&vga->attr, t);
  102. return 1;
  103. }
  104. }
  105. }
  106. return 0;
  107. }
  108. int
  109. dbpci(Vga *vga, Ndbtuple *tuple)
  110. {
  111. int did, vid;
  112. Ndbtuple *t, *td;
  113. Pcidev *pci;
  114. for(t = tuple->entry; t; t = t->entry){
  115. if(strcmp(t->attr, "vid") != 0 || (vid=atoi(t->val)) == 0)
  116. continue;
  117. for(td = t->line; td != t; td = td->line){
  118. if(strcmp(td->attr, "did") != 0)
  119. continue;
  120. if(strcmp(td->val, "*") == 0)
  121. did = 0;
  122. else if((did=atoi(td->val)) == 0)
  123. continue;
  124. for(pci=nil; pci=pcimatch(pci, vid, did);)
  125. if((pci->ccru>>8) == 3)
  126. break;
  127. if(pci == nil)
  128. continue;
  129. vga->pci = pci;
  130. addattr(&vga->attr, t);
  131. addattr(&vga->attr, td);
  132. return 1;
  133. }
  134. }
  135. return 0;
  136. }
  137. static void
  138. save(Vga *vga, Ndbtuple *tuple)
  139. {
  140. Ctlr *c;
  141. Ndbtuple *t;
  142. for(t = tuple->entry; t; t = t->entry){
  143. if(strcmp(t->attr, "ctlr") == 0){
  144. vga->ctlr = addctlr(vga, t->val);
  145. if(strcmp(t->val, "vesa") == 0)
  146. vga->vesa = vga->ctlr;
  147. }else if(strcmp(t->attr, "ramdac") == 0)
  148. vga->ramdac = addctlr(vga, t->val);
  149. else if(strcmp(t->attr, "clock") == 0)
  150. vga->clock = addctlr(vga, t->val);
  151. else if(strcmp(t->attr, "hwgc") == 0)
  152. vga->hwgc = addctlr(vga, t->val);
  153. else if(strcmp(t->attr, "link") == 0){
  154. c = addctlr(vga, t->val);
  155. if(strcmp(t->val, "vesa") == 0)
  156. vga->vesa = c;
  157. }else if(strcmp(t->attr, "linear") == 0)
  158. vga->linear = strtol(t->val, 0, 0);
  159. else if(strcmp(t->attr, "membw") == 0)
  160. vga->membw = strtol(t->val, 0, 0)*1000000;
  161. else if(strcmp(t->attr, "vid")==0 || strcmp(t->attr, "did")==0)
  162. {}
  163. else if(strtol(t->attr, 0, 0) == 0)
  164. addattr(&vga->attr, t);
  165. }
  166. }
  167. int
  168. dbctlr(char* name, Vga* vga)
  169. {
  170. Ndb *db;
  171. Ndbs s;
  172. Ndbtuple *tuple;
  173. Ndbtuple *pcituple;
  174. db = dbopen(name);
  175. /*
  176. * Search vgadb for a matching BIOS string or PCI id.
  177. * If we have both, the BIOS string wins.
  178. */
  179. pcituple = nil;
  180. for(tuple = ndbsearch(db, &s, "ctlr", ""); tuple; tuple = ndbsnext(&s, "ctlr", "")){
  181. if(!pcituple && dbpci(vga, tuple))
  182. pcituple = tuple;
  183. if(dbbios(vga, tuple)){
  184. save(vga, tuple);
  185. if(pcituple && pcituple != tuple)
  186. ndbfree(pcituple);
  187. ndbfree(tuple);
  188. ndbclose(db);
  189. return 1;
  190. }
  191. if(tuple != pcituple)
  192. ndbfree(tuple);
  193. }
  194. if(pcituple){
  195. save(vga, pcituple);
  196. ndbfree(pcituple);
  197. }
  198. ndbclose(db);
  199. if(pcituple)
  200. return 1;
  201. return 0;
  202. }
  203. static int
  204. dbmonitor(Ndb* db, Mode* mode, char* type, char* size)
  205. {
  206. Ndbs s;
  207. Ndbtuple *t, *tuple;
  208. char *p, attr[Namelen+1], val[Namelen+1], buf[2*Namelen+1];
  209. int clock, x, i;
  210. /*
  211. * Clock rate hack.
  212. * If the size is 'XxYxZ@NMHz' then override the database entry's
  213. * 'clock=' with 'N*1000000'.
  214. */
  215. clock = 0;
  216. strcpy(buf, size);
  217. if(p = strchr(buf, '@')){
  218. *p++ = 0;
  219. if((clock = strtol(p, &p, 0)) && strcmp(p, "MHz") == 0)
  220. clock *= 1000000;
  221. }
  222. memset(mode, 0, sizeof(Mode));
  223. if((p = strchr(buf, 'x')) && (p = strchr(p+1, 'x'))){
  224. *p++ = 0;
  225. mode->z = atoi(p);
  226. }
  227. strcpy(attr, type);
  228. strcpy(val, buf);
  229. if(p = ndbgetvalue(db, &s, attr, "", "videobw", nil)){
  230. mode->videobw = atol(p)*1000000UL;
  231. free(p);
  232. }
  233. if(mode->x == 0 && ((mode->x = strtol(val, &p, 0)) == 0 || *p++ != 'x'))
  234. return 0;
  235. if(mode->y == 0 && (mode->y = strtol(p, &p, 0)) == 0)
  236. return 0;
  237. i = 0;
  238. buggery:
  239. if((tuple = ndbsearch(db, &s, attr, val)) == 0)
  240. return 0;
  241. for(t = tuple->entry; t; t = t->entry){
  242. if(strcmp(t->attr, "clock") == 0 && mode->frequency == 0)
  243. mode->frequency = strtod(t->val, 0)*1000000;
  244. else if(strcmp(t->attr, "defaultclock") == 0 && mode->deffrequency == 0)
  245. mode->deffrequency = strtod(t->val, 0)*1000000;
  246. else if(strcmp(t->attr, "ht") == 0 && mode->ht == 0)
  247. mode->ht = strtol(t->val, 0, 0);
  248. else if(strcmp(t->attr, "shb") == 0 && mode->shb == 0)
  249. mode->shb = strtol(t->val, 0, 0);
  250. else if(strcmp(t->attr, "ehb") == 0 && mode->ehb == 0)
  251. mode->ehb = strtol(t->val, 0, 0);
  252. else if(strcmp(t->attr, "shs") == 0 && mode->shs == 0)
  253. mode->shs = strtol(t->val, 0, 0);
  254. else if(strcmp(t->attr, "ehs") == 0 && mode->ehs == 0)
  255. mode->ehs = strtol(t->val, 0, 0);
  256. else if(strcmp(t->attr, "vt") == 0 && mode->vt == 0)
  257. mode->vt = strtol(t->val, 0, 0);
  258. else if(strcmp(t->attr, "vrs") == 0 && mode->vrs == 0)
  259. mode->vrs = strtol(t->val, 0, 0);
  260. else if(strcmp(t->attr, "vre") == 0 && mode->vre == 0)
  261. mode->vre = strtol(t->val, 0, 0);
  262. else if(strcmp(t->attr, "hsync") == 0)
  263. mode->hsync = *t->val;
  264. else if(strcmp(t->attr, "vsync") == 0)
  265. mode->vsync = *t->val;
  266. else if(strcmp(t->attr, "interlace") == 0)
  267. mode->interlace = *t->val;
  268. else if(strcmp(t->attr, "include") == 0 /*&& strcmp(t->val, val) != 0*/){
  269. strcpy(attr, t->attr);
  270. strcpy(val, t->val);
  271. ndbfree(tuple);
  272. if(i++ > 5)
  273. error("dbmonitor: implausible include depth at %s=%s\n", attr, val);
  274. goto buggery;
  275. }
  276. else if(strcmp(t->attr, "include") == 0){
  277. print("warning: bailed out of infinite loop in attr %s=%s\n", attr, val);
  278. }
  279. else
  280. addattr(&mode->attr, t);
  281. }
  282. ndbfree(tuple);
  283. if((x = strtol(size, &p, 0)) == 0 || x != mode->x || *p++ != 'x')
  284. return 0;
  285. if((x = strtol(p, &p, 0)) == 0 || x != mode->y || *p++ != 'x')
  286. return 0;
  287. if((x = strtol(p, &p, 0)) == 0 || x != mode->z)
  288. return 0;
  289. if(clock)
  290. mode->frequency = clock;
  291. return 1;
  292. }
  293. Mode*
  294. dbmode(char* name, char* type, char* size)
  295. {
  296. Ndb *db;
  297. Ndbs s;
  298. Ndbtuple *t, *tuple;
  299. Mode *mode;
  300. char attr[Namelen+1];
  301. ulong videobw;
  302. db = dbopen(name);
  303. mode = alloc(sizeof(Mode));
  304. strcpy(attr, type);
  305. videobw = 0;
  306. /*
  307. * Look for the attr=size entry.
  308. */
  309. if(dbmonitor(db, mode, attr, size)){
  310. strcpy(mode->type, type);
  311. strcpy(mode->size, size);
  312. ndbclose(db);
  313. return mode;
  314. }
  315. if(mode->videobw && videobw == 0) /* we at least found that; save it away */
  316. videobw = mode->videobw;
  317. /*
  318. * Not found. Look for an attr="" entry and then
  319. * for an alias=attr within.
  320. */
  321. buggery:
  322. for(tuple = ndbsearch(db, &s, attr, ""); tuple; tuple = ndbsnext(&s, attr, "")){
  323. for(t = tuple->entry; t; t = t->entry){
  324. if(strcmp(t->attr, "alias"))
  325. continue;
  326. strcpy(attr, t->val);
  327. if(dbmonitor(db, mode, attr, size)){
  328. strcpy(mode->type, type);
  329. strcpy(mode->size, size);
  330. ndbfree(tuple);
  331. ndbclose(db);
  332. if(videobw)
  333. mode->videobw = videobw;
  334. return mode;
  335. }
  336. /*
  337. * Found an alias but no match for size,
  338. * restart looking for attr="" with the
  339. * new attr.
  340. */
  341. ndbfree(tuple);
  342. goto buggery;
  343. }
  344. ndbfree(tuple);
  345. }
  346. free(mode);
  347. ndbclose(db);
  348. return 0;
  349. }
  350. void
  351. dbdumpmode(Mode* mode)
  352. {
  353. Attr *attr;
  354. Bprint(&stdout, "dbdumpmode\n");
  355. Bprint(&stdout, "type=%s, size=%s\n", mode->type, mode->size);
  356. Bprint(&stdout, "frequency=%d\n", mode->frequency);
  357. Bprint(&stdout, "x=%d (0x%X), y=%d (0x%X), z=%d (0x%X)\n",
  358. mode->x, mode->x, mode->y, mode->y, mode->z, mode->z);
  359. Bprint(&stdout, "ht=%d (0x%X), shb=%d (0x%X), ehb=%d (0x%X)\n",
  360. mode->ht, mode->ht, mode->shb, mode->shb, mode->ehb, mode->ehb);
  361. Bprint(&stdout, "shs=%d (0x%X), ehs=%d (0x%X)\n",
  362. mode->shs, mode->shs, mode->ehs, mode->ehs);
  363. Bprint(&stdout, "vt=%d (0x%X), vrs=%d (0x%X), vre=%d (0x%X)\n",
  364. mode->vt, mode->vt, mode->vrs, mode->vrs, mode->vre, mode->vre);
  365. Bprint(&stdout, "hsync=%d, vsync=%d, interlace=%d\n",
  366. mode->hsync, mode->vsync, mode->interlace);
  367. for(attr = mode->attr; attr; attr = attr->next)
  368. Bprint(&stdout, "mode->attr: %s=%s\n", attr->attr, attr->val);
  369. }