pc.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. #include "all.h"
  2. #include "mem.h"
  3. #include "io.h"
  4. #include "ureg.h"
  5. /*
  6. * Where configuration info is left for the loaded programme.
  7. * This will turn into a structure as more is done by the boot loader
  8. * (e.g. why parse the .ini file twice?).
  9. * There are 1024 bytes available at CONFADDR.
  10. */
  11. #define BOOTLINE ((char*)CONFADDR)
  12. #define BOOTLINELEN 64
  13. #define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
  14. #define BOOTARGSLEN (1024-BOOTLINELEN)
  15. #define MAXCONF 32
  16. #define KADDR(a) ((void*)((ulong)(a)|KZERO))
  17. char bootdisk[NAMELEN];
  18. char *confname[MAXCONF];
  19. char *confval[MAXCONF];
  20. int nconf;
  21. static int isoldbcom;
  22. int
  23. getcfields(char* lp, char** fields, int n, char* sep)
  24. {
  25. int i;
  26. for(i = 0; lp && *lp && i < n; i++){
  27. while(*lp && strchr(sep, *lp) != 0)
  28. *lp++ = 0;
  29. if(*lp == 0)
  30. break;
  31. fields[i] = lp;
  32. while(*lp && strchr(sep, *lp) == 0){
  33. if(*lp == '\\' && *(lp+1) == '\n')
  34. *lp++ = ' ';
  35. lp++;
  36. }
  37. }
  38. return i;
  39. }
  40. static void
  41. options(void)
  42. {
  43. uchar *bda;
  44. long i, n;
  45. char *cp, *line[MAXCONF], *p, *q;
  46. if(strncmp(BOOTARGS, "ZORT 0\r\n", 8)){
  47. isoldbcom = 1;
  48. memmove(BOOTARGS, KADDR(1024), BOOTARGSLEN);
  49. memmove(BOOTLINE, KADDR(0x100), BOOTLINELEN);
  50. bda = KADDR(0x400);
  51. bda[0x13] = 639;
  52. bda[0x14] = 639>>8;
  53. }
  54. /*
  55. * parse configuration args from dos file plan9.ini
  56. */
  57. cp = BOOTARGS; /* where b.com leaves its config */
  58. cp[BOOTARGSLEN-1] = 0;
  59. /*
  60. * Strip out '\r', change '\t' -> ' '.
  61. */
  62. p = cp;
  63. for(q = cp; *q; q++){
  64. if(*q == '\r')
  65. continue;
  66. if(*q == '\t')
  67. *q = ' ';
  68. *p++ = *q;
  69. }
  70. *p = 0;
  71. n = getcfields(cp, line, MAXCONF, "\n");
  72. for(i = 0; i < n; i++){
  73. if(*line[i] == '#')
  74. continue;
  75. cp = strchr(line[i], '=');
  76. if(cp == 0)
  77. continue;
  78. *cp++ = 0;
  79. if(cp - line[i] >= NAMELEN+1)
  80. *(line[i]+NAMELEN-1) = 0;
  81. confname[nconf] = line[i];
  82. confval[nconf] = cp;
  83. nconf++;
  84. }
  85. }
  86. /*
  87. * Vecinit is the first hook we have into configuring the machine,
  88. * so we do it all here. A pox on special fileserver code.
  89. * We do more in meminit below.
  90. */
  91. void
  92. vecinit(void)
  93. {
  94. options();
  95. }
  96. int
  97. cistrcmp(char* a, char* b)
  98. {
  99. int ac, bc;
  100. for(;;){
  101. ac = *a++;
  102. bc = *b++;
  103. if(ac >= 'A' && ac <= 'Z')
  104. ac = 'a' + (ac - 'A');
  105. if(bc >= 'A' && bc <= 'Z')
  106. bc = 'a' + (bc - 'A');
  107. ac -= bc;
  108. if(ac)
  109. return ac;
  110. if(bc == 0)
  111. break;
  112. }
  113. return 0;
  114. }
  115. int
  116. cistrncmp(char *a, char *b, int n)
  117. {
  118. unsigned ac, bc;
  119. while(n > 0){
  120. ac = *a++;
  121. bc = *b++;
  122. n--;
  123. if(ac >= 'A' && ac <= 'Z')
  124. ac = 'a' + (ac - 'A');
  125. if(bc >= 'A' && bc <= 'Z')
  126. bc = 'a' + (bc - 'A');
  127. ac -= bc;
  128. if(ac)
  129. return ac;
  130. if(bc == 0)
  131. break;
  132. }
  133. return 0;
  134. }
  135. char*
  136. getconf(char *name)
  137. {
  138. int i;
  139. for(i = 0; i < nconf; i++)
  140. if(cistrcmp(confname[i], name) == 0)
  141. return confval[i];
  142. return 0;
  143. }
  144. /* memory map; this kernel will see MAXMEG megabytes of RAM at most. */
  145. #ifndef MAXMEG
  146. #define MAXMEG 1791 /* 1.75GB-1MB, to avoid overshooting into PCI space */
  147. #endif
  148. char mmap[MAXMEG+2];
  149. Mconf mconf;
  150. static void
  151. mconfinit(void)
  152. {
  153. long x, i, j;
  154. ulong ktop;
  155. Mbank *mbp;
  156. uchar *bda;
  157. /*
  158. * size memory above 1 meg. Kernel sits at 1 meg. We
  159. * only recognize MB size chunks.
  160. */
  161. memset(mmap, ' ', sizeof(mmap));
  162. x = 0x12345678;
  163. for(i = 1; i <= MAXMEG; i++){
  164. /*
  165. * write the first & last word in a megabyte of memory
  166. */
  167. *mapaddr(KZERO|(i*MB)) = x;
  168. *mapaddr(KZERO|((i+1)*MB-BY2WD)) = x;
  169. /*
  170. * write the first and last word in all previous megs to
  171. * handle address wrap around
  172. */
  173. for(j = 1; j < i; j++){
  174. *mapaddr(KZERO|(j*MB)) = ~x;
  175. *mapaddr(KZERO|((j+1)*MB-BY2WD)) = ~x;
  176. }
  177. /*
  178. * check for correct value
  179. */
  180. if(*mapaddr(KZERO|(i*MB)) == x && *mapaddr(KZERO|((i+1)*MB-BY2WD)) == x)
  181. mmap[i] = 'x';
  182. x += 0x3141526;
  183. }
  184. /*
  185. * bank[0] goes from the end of the bootstrap structures to ~640k.
  186. * want to use this up first for ialloc because sparemem
  187. * will want a large contiguous chunk.
  188. */
  189. mbp = mconf.bank;
  190. mbp->base = PADDR(CPU0MACH+BY2PG);
  191. bda = (uchar*)(KZERO|0x400);
  192. mbp->limit = ((bda[0x14]<<8)|bda[0x13])*1024;
  193. mbp++;
  194. /*
  195. * bank[1] usually goes from the end of kernel bss to the end of memory
  196. */
  197. ktop = PGROUND((ulong)end);
  198. ktop = PADDR(ktop);
  199. mbp->base = ktop;
  200. for(i = 1; mmap[i] == 'x'; i++)
  201. ;
  202. mbp->limit = i*MB;
  203. mconf.topofmem = mbp->limit;
  204. mbp++;
  205. /*
  206. * Look for any other chunks of memory.
  207. */
  208. for(; i <= MAXMEG; i++){
  209. if(mmap[i] == 'x'){
  210. mbp->base = i*MB;
  211. for(j = i+1; mmap[j] == 'x'; j++)
  212. ;
  213. mbp->limit = j*MB;
  214. mconf.topofmem = j*MB;
  215. mbp++;
  216. if((mbp - mconf.bank) >= MAXBANK)
  217. break;
  218. }
  219. }
  220. mconf.nbank = mbp - mconf.bank;
  221. }
  222. ulong
  223. meminit(void)
  224. {
  225. conf.nmach = 1;
  226. mconfinit();
  227. mmuinit();
  228. trapinit();
  229. /*
  230. * This is not really right, but the port code assumes
  231. * a linear memory array and this is as close as we can
  232. * get to satisfying that.
  233. * Dancing around the 'port' code is all just an ugly hack
  234. * anyway.
  235. */
  236. return mconf.topofmem;
  237. }
  238. void
  239. userinit(void (*f)(void), void *arg, char *text)
  240. {
  241. User *p;
  242. p = newproc();
  243. /*
  244. * Kernel Stack.
  245. * The -4 is because the path sched()->gotolabel()->init0()->f()
  246. * uses a stack location without creating any local space.
  247. */
  248. p->sched.pc = (ulong)init0;
  249. p->sched.sp = (ulong)p->stack + sizeof(p->stack) - 4;
  250. p->start = f;
  251. p->text = text;
  252. p->arg = arg;
  253. dofilter(p->time+0, C0a, C0b, 1);
  254. dofilter(p->time+1, C1a, C1b, 1);
  255. dofilter(p->time+2, C2a, C2b, 1);
  256. ready(p);
  257. }
  258. static int useuart;
  259. static void (*intrputs)(char*, int);
  260. static int
  261. pcgetc(void)
  262. {
  263. int c;
  264. if(c = kbdgetc())
  265. return c;
  266. if(useuart)
  267. return uartgetc();
  268. return 0;
  269. }
  270. static void
  271. pcputc(int c)
  272. {
  273. if(predawn)
  274. cgaputc(c);
  275. if(useuart)
  276. uartputc(c);
  277. }
  278. static void
  279. pcputs(char* s, int n)
  280. {
  281. if(!predawn)
  282. cgaputs(s, n);
  283. if(intrputs)
  284. (*intrputs)(s, n);
  285. }
  286. void
  287. consinit(void (*puts)(char*, int))
  288. {
  289. char *p;
  290. int baud, port;
  291. kbdinit();
  292. consgetc = pcgetc;
  293. consputc = pcputc;
  294. consputs = pcputs;
  295. intrputs = puts;
  296. if((p = getconf("console")) == 0 || cistrcmp(p, "cga") == 0)
  297. return;
  298. port = strtoul(p, 0, 0);
  299. baud = 0;
  300. if(p = getconf("baud"))
  301. baud = strtoul(p, 0, 0);
  302. if(baud == 0)
  303. baud = 9600;
  304. uartspecial(port, kbdchar, conschar, baud);
  305. useuart = 1;
  306. }
  307. void
  308. consreset(void)
  309. {
  310. }
  311. void
  312. firmware(void)
  313. {
  314. char *p;
  315. /*
  316. * Always called splhi().
  317. */
  318. if((p = getconf("reset")) && cistrcmp(p, "manual") == 0){
  319. predawn = 1;
  320. print("\nHit Reset\n");
  321. for(;;);
  322. }
  323. pcireset();
  324. i8042reset();
  325. }
  326. int
  327. isaconfig(char *class, int ctlrno, ISAConf *isa)
  328. {
  329. char cc[NAMELEN], *p, *q, *r;
  330. int n;
  331. sprint(cc, "%s%d", class, ctlrno);
  332. for(n = 0; n < nconf; n++){
  333. if(cistrncmp(confname[n], cc, NAMELEN))
  334. continue;
  335. isa->nopt = 0;
  336. p = confval[n];
  337. while(*p){
  338. while(*p == ' ' || *p == '\t')
  339. p++;
  340. if(*p == '\0')
  341. break;
  342. if(cistrncmp(p, "type=", 5) == 0){
  343. p += 5;
  344. for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
  345. if(*p == '\0' || *p == ' ' || *p == '\t')
  346. break;
  347. *q = *p++;
  348. }
  349. *q = '\0';
  350. }
  351. else if(cistrncmp(p, "port=", 5) == 0)
  352. isa->port = strtoul(p+5, &p, 0);
  353. else if(cistrncmp(p, "irq=", 4) == 0)
  354. isa->irq = strtoul(p+4, &p, 0);
  355. else if(cistrncmp(p, "dma=", 4) == 0)
  356. isa->dma = strtoul(p+4, &p, 0);
  357. else if(cistrncmp(p, "mem=", 4) == 0)
  358. isa->mem = strtoul(p+4, &p, 0);
  359. else if(cistrncmp(p, "size=", 5) == 0)
  360. isa->size = strtoul(p+5, &p, 0);
  361. else if(cistrncmp(p, "freq=", 5) == 0)
  362. isa->freq = strtoul(p+5, &p, 0);
  363. else if(isa->nopt < NISAOPT){
  364. r = isa->opt[isa->nopt];
  365. while(*p && *p != ' ' && *p != '\t'){
  366. *r++ = *p++;
  367. if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
  368. break;
  369. }
  370. *r = '\0';
  371. isa->nopt++;
  372. }
  373. while(*p && *p != ' ' && *p != '\t')
  374. p++;
  375. }
  376. return 1;
  377. }
  378. return 0;
  379. }
  380. void
  381. lockinit(void)
  382. {
  383. }
  384. void
  385. launchinit(void)
  386. {
  387. }
  388. void
  389. lights(int, int)
  390. {
  391. }
  392. /* in assembly language
  393. Float
  394. famd(Float a, int b, int c, int d)
  395. {
  396. return ((a+b) * c) / d;
  397. }
  398. ulong
  399. fdf(Float a, int b)
  400. {
  401. return a / b;
  402. }
  403. */