pc.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  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 */
  145. /* the file server kernel will only see MAXMEG megabytes of RAM at most. */
  146. #define MAXMEG 1791 /* 1.75GB-1MB, to avoid overshooting 1.75GB */
  147. char mmap[MAXMEG+2];
  148. Mconf mconf;
  149. static void
  150. mconfinit(void)
  151. {
  152. long x, i, j;
  153. ulong ktop;
  154. Mbank *mbp;
  155. uchar *bda;
  156. /*
  157. * size memory above 1 meg. Kernel sits at 1 meg. We
  158. * only recognize MB size chunks.
  159. */
  160. memset(mmap, ' ', sizeof(mmap));
  161. x = 0x12345678;
  162. for(i = 1; i <= MAXMEG; i++){
  163. /*
  164. * write the first & last word in a megabyte of memory
  165. */
  166. *mapaddr(KZERO|(i*MB)) = x;
  167. *mapaddr(KZERO|((i+1)*MB-BY2WD)) = x;
  168. /*
  169. * write the first and last word in all previous megs to
  170. * handle address wrap around
  171. */
  172. for(j = 1; j < i; j++){
  173. *mapaddr(KZERO|(j*MB)) = ~x;
  174. *mapaddr(KZERO|((j+1)*MB-BY2WD)) = ~x;
  175. }
  176. /*
  177. * check for correct value
  178. */
  179. if(*mapaddr(KZERO|(i*MB)) == x && *mapaddr(KZERO|((i+1)*MB-BY2WD)) == x)
  180. mmap[i] = 'x';
  181. x += 0x3141526;
  182. }
  183. /*
  184. * bank[0] goes from the end of the bootstrap structures to ~640k.
  185. * want to use this up first for ialloc because sparemem
  186. * will want a large contiguous chunk.
  187. */
  188. mbp = mconf.bank;
  189. mbp->base = PADDR(CPU0MACH+BY2PG);
  190. bda = (uchar*)(KZERO|0x400);
  191. mbp->limit = ((bda[0x14]<<8)|bda[0x13])*1024;
  192. mbp++;
  193. /*
  194. * bank[1] usually goes from the end of kernel bss to the end of memory
  195. */
  196. ktop = PGROUND((ulong)end);
  197. ktop = PADDR(ktop);
  198. mbp->base = ktop;
  199. for(i = 1; mmap[i] == 'x'; i++)
  200. ;
  201. mbp->limit = i*MB;
  202. mconf.topofmem = mbp->limit;
  203. mbp++;
  204. /*
  205. * Look for any other chunks of memory.
  206. */
  207. for(; i <= MAXMEG; i++){
  208. if(mmap[i] == 'x'){
  209. mbp->base = i*MB;
  210. for(j = i+1; mmap[j] == 'x'; j++)
  211. ;
  212. mbp->limit = j*MB;
  213. mconf.topofmem = j*MB;
  214. mbp++;
  215. if((mbp - mconf.bank) >= MAXBANK)
  216. break;
  217. }
  218. }
  219. mconf.nbank = mbp - mconf.bank;
  220. }
  221. ulong
  222. meminit(void)
  223. {
  224. conf.nmach = 1;
  225. mconfinit();
  226. mmuinit();
  227. trapinit();
  228. /*
  229. * This is not really right, but the port code assumes
  230. * a linear memory array and this is as close as we can
  231. * get to satisfying that.
  232. * Dancing around the 'port' code is all just an ugly hack
  233. * anyway.
  234. */
  235. return mconf.topofmem;
  236. }
  237. void
  238. userinit(void (*f)(void), void *arg, char *text)
  239. {
  240. User *p;
  241. p = newproc();
  242. /*
  243. * Kernel Stack.
  244. * The -4 is because the path sched()->gotolabel()->init0()->f()
  245. * uses a stack location without creating any local space.
  246. */
  247. p->sched.pc = (ulong)init0;
  248. p->sched.sp = (ulong)p->stack + sizeof(p->stack) - 4;
  249. p->start = f;
  250. p->text = text;
  251. p->arg = arg;
  252. dofilter(p->time+0, C0a, C0b, 1);
  253. dofilter(p->time+1, C1a, C1b, 1);
  254. dofilter(p->time+2, C2a, C2b, 1);
  255. ready(p);
  256. }
  257. static int useuart;
  258. static void (*intrputs)(char*, int);
  259. static int
  260. pcgetc(void)
  261. {
  262. int c;
  263. if(c = kbdgetc())
  264. return c;
  265. if(useuart)
  266. return uartgetc();
  267. return 0;
  268. }
  269. static void
  270. pcputc(int c)
  271. {
  272. if(predawn)
  273. cgaputc(c);
  274. if(useuart)
  275. uartputc(c);
  276. }
  277. static void
  278. pcputs(char* s, int n)
  279. {
  280. if(!predawn)
  281. cgaputs(s, n);
  282. if(intrputs)
  283. (*intrputs)(s, n);
  284. }
  285. void
  286. consinit(void (*puts)(char*, int))
  287. {
  288. char *p;
  289. int baud, port;
  290. kbdinit();
  291. consgetc = pcgetc;
  292. consputc = pcputc;
  293. consputs = pcputs;
  294. intrputs = puts;
  295. if((p = getconf("console")) == 0 || cistrcmp(p, "cga") == 0)
  296. return;
  297. port = strtoul(p, 0, 0);
  298. baud = 0;
  299. if(p = getconf("baud"))
  300. baud = strtoul(p, 0, 0);
  301. if(baud == 0)
  302. baud = 9600;
  303. uartspecial(port, kbdchar, conschar, baud);
  304. useuart = 1;
  305. }
  306. void
  307. consreset(void)
  308. {
  309. }
  310. void
  311. firmware(void)
  312. {
  313. char *p;
  314. /*
  315. * Always called splhi().
  316. */
  317. if((p = getconf("reset")) && cistrcmp(p, "manual") == 0){
  318. predawn = 1;
  319. print("\nHit Reset\n");
  320. for(;;);
  321. }
  322. pcireset();
  323. i8042reset();
  324. }
  325. int
  326. isaconfig(char *class, int ctlrno, ISAConf *isa)
  327. {
  328. char cc[NAMELEN], *p, *q, *r;
  329. int n;
  330. sprint(cc, "%s%d", class, ctlrno);
  331. for(n = 0; n < nconf; n++){
  332. if(cistrncmp(confname[n], cc, NAMELEN))
  333. continue;
  334. isa->nopt = 0;
  335. p = confval[n];
  336. while(*p){
  337. while(*p == ' ' || *p == '\t')
  338. p++;
  339. if(*p == '\0')
  340. break;
  341. if(cistrncmp(p, "type=", 5) == 0){
  342. p += 5;
  343. for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
  344. if(*p == '\0' || *p == ' ' || *p == '\t')
  345. break;
  346. *q = *p++;
  347. }
  348. *q = '\0';
  349. }
  350. else if(cistrncmp(p, "port=", 5) == 0)
  351. isa->port = strtoul(p+5, &p, 0);
  352. else if(cistrncmp(p, "irq=", 4) == 0)
  353. isa->irq = strtoul(p+4, &p, 0);
  354. else if(cistrncmp(p, "dma=", 4) == 0)
  355. isa->dma = strtoul(p+4, &p, 0);
  356. else if(cistrncmp(p, "mem=", 4) == 0)
  357. isa->mem = strtoul(p+4, &p, 0);
  358. else if(cistrncmp(p, "size=", 5) == 0)
  359. isa->size = strtoul(p+5, &p, 0);
  360. else if(cistrncmp(p, "freq=", 5) == 0)
  361. isa->freq = strtoul(p+5, &p, 0);
  362. else if(isa->nopt < NISAOPT){
  363. r = isa->opt[isa->nopt];
  364. while(*p && *p != ' ' && *p != '\t'){
  365. *r++ = *p++;
  366. if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1)
  367. break;
  368. }
  369. *r = '\0';
  370. isa->nopt++;
  371. }
  372. while(*p && *p != ' ' && *p != '\t')
  373. p++;
  374. }
  375. return 1;
  376. }
  377. return 0;
  378. }
  379. void
  380. lockinit(void)
  381. {
  382. }
  383. void
  384. launchinit(void)
  385. {
  386. }
  387. void
  388. lights(int, int)
  389. {
  390. }
  391. /* in assembly language
  392. Float
  393. famd(Float a, int b, int c, int d)
  394. {
  395. return ((a+b) * c) / d;
  396. }
  397. ulong
  398. fdf(Float a, int b)
  399. {
  400. return a / b;
  401. }
  402. */