main.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868
  1. #include <u.h>
  2. #include <libc.h>
  3. #include "dat.h"
  4. #include "fns.h"
  5. /* for fs */
  6. #include <auth.h>
  7. #include <fcall.h>
  8. #include <thread.h>
  9. #include <9p.h>
  10. #include <386/include/ureg.h>
  11. enum {
  12. MEMSIZE = 0x100000,
  13. RMBUF = 0x9000,
  14. RMCODE = 0x8000,
  15. PITHZ = 1193182,
  16. PITNS = 1000000000/PITHZ,
  17. };
  18. static Cpu cpu;
  19. static unsigned char memory[MEMSIZE+4];
  20. static unsigned char pageregtmp[0x10];
  21. static int portfd[5];
  22. static int realmemfd;
  23. static int cputrace;
  24. static int porttrace;
  25. static Pit pit[3];
  26. static unsigned char rtcaddr;
  27. static long long pitclock;
  28. static void
  29. startclock(void)
  30. {
  31. print_func_entry();
  32. pitclock = nsec();
  33. print_func_exit();
  34. }
  35. static void
  36. runclock(void)
  37. {
  38. print_func_entry();
  39. long long now, dt;
  40. now = nsec();
  41. dt = now - pitclock;
  42. if(dt >= PITNS){
  43. clockpit(pit, dt/PITNS);
  44. pitclock = now;
  45. }
  46. print_func_exit();
  47. }
  48. static unsigned long
  49. gw1(unsigned char *p)
  50. {
  51. print_func_entry();
  52. print_func_exit();
  53. return p[0];
  54. }
  55. static unsigned long
  56. gw2(unsigned char *p)
  57. {
  58. print_func_entry();
  59. print_func_exit();
  60. return (unsigned long)p[0] | (unsigned long)p[1]<<8;
  61. }
  62. static unsigned long
  63. gw4(unsigned char *p)
  64. {
  65. print_func_entry();
  66. print_func_exit();
  67. return (unsigned long)p[0] | (unsigned long)p[1]<<8 | (unsigned long)p[2]<<16 | (unsigned long)p[3]<<24;
  68. }
  69. static unsigned long (*gw[9])(unsigned char *p) = {
  70. [1] gw1,
  71. [2] gw2,
  72. [4] gw4,
  73. [8] gw4,
  74. };
  75. static void
  76. pw1(unsigned char *p, unsigned long w)
  77. {
  78. print_func_entry();
  79. p[0] = w & 0xFF;
  80. print_func_exit();
  81. }
  82. static void
  83. pw2(unsigned char *p, unsigned long w)
  84. {
  85. print_func_entry();
  86. p[0] = w & 0xFF;
  87. p[1] = (w>>8) & 0xFF;
  88. print_func_exit();
  89. }
  90. static void
  91. pw4(unsigned char *p, unsigned long w)
  92. {
  93. print_func_entry();
  94. p[0] = w & 0xFF;
  95. p[1] = (w>>8) & 0xFF;
  96. p[2] = (w>>16) & 0xFF;
  97. p[3] = (w>>24) & 0xFF;
  98. print_func_exit();
  99. }
  100. static void (*pw[5])(unsigned char *p, unsigned long w) = {
  101. [1] pw1,
  102. [2] pw2,
  103. [4] pw4,
  104. };
  105. static unsigned long
  106. rbad(void *aux, unsigned long off, int len)
  107. {
  108. print_func_entry();
  109. fprint(2, "bad mem read %.5lux\n", off);
  110. trap(&cpu, EMEM);
  111. /* not reached */
  112. print_func_exit();
  113. return 0;
  114. }
  115. static void
  116. wbad(void *aux, unsigned long off, unsigned long w, int len)
  117. {
  118. print_func_entry();
  119. fprint(2, "bad mem write %.5lux\n", off);
  120. trap(&cpu, EMEM);
  121. print_func_exit();
  122. }
  123. static unsigned long
  124. rmem(void *aux, unsigned long off, int len)
  125. {
  126. print_func_entry();
  127. print_func_exit();
  128. return gw[len](memory + off);
  129. }
  130. static void
  131. wmem(void *aux, unsigned long off, unsigned long w, int len)
  132. {
  133. print_func_entry();
  134. pw[len](memory + off, w);
  135. print_func_exit();
  136. }
  137. static unsigned long
  138. rrealmem(void *aux, unsigned long off, int len)
  139. {
  140. print_func_entry();
  141. unsigned char data[4];
  142. if(pread(realmemfd, data, len, off) != len){
  143. fprint(2, "bad real mem read %.5lux: %r\n", off);
  144. trap(&cpu, EMEM);
  145. }
  146. print_func_exit();
  147. return gw[len](data);
  148. }
  149. static void
  150. wrealmem(void *aux, unsigned long off, unsigned long w, int len)
  151. {
  152. print_func_entry();
  153. unsigned char data[4];
  154. pw[len](data, w);
  155. if(pwrite(realmemfd, data, len, off) != len){
  156. fprint(2, "bad real mem write %.5lux: %r\n", off);
  157. trap(&cpu, EMEM);
  158. }
  159. print_func_exit();
  160. }
  161. static unsigned long
  162. rport(void *aux, unsigned long p, int len)
  163. {
  164. print_func_entry();
  165. unsigned char data[4];
  166. unsigned long w;
  167. switch(p){
  168. case 0x20: /* PIC 1 */
  169. case 0x21:
  170. w = 0;
  171. break;
  172. case 0x40:
  173. case 0x41:
  174. case 0x42:
  175. case 0x43:
  176. runclock();
  177. w = rpit(pit, p - 0x40);
  178. break;
  179. case 0x60: /* keyboard data output buffer */
  180. w = 0;
  181. break;
  182. case 0x61: /* keyboard controller port b */
  183. runclock();
  184. w = pit[2].out<<5 | pit[2].gate;
  185. break;
  186. case 0x62: /* PPI (XT only) */
  187. runclock();
  188. w = pit[2].out<<5;
  189. break;
  190. case 0x63: /* PPI (XT only) read dip switches */
  191. w = 0;
  192. break;
  193. case 0x65: /* A20 gate */
  194. w = 1 << 2;
  195. break;
  196. case 0x70: /* RTC addr */
  197. w = rtcaddr;
  198. break;
  199. case 0x71: /* RTC data */
  200. w = 0xFF;
  201. break;
  202. case 0x80: /* extra dma registers (temp) */
  203. case 0x84:
  204. case 0x85:
  205. case 0x86:
  206. case 0x88:
  207. case 0x8c:
  208. case 0x8d:
  209. case 0x8e:
  210. w = pageregtmp[p-0x80];
  211. break;
  212. case 0x92: /* A20 gate (system control port a) */
  213. w = 1 << 1;
  214. break;
  215. case 0xa0: /* PIC 2 */
  216. case 0xa1:
  217. w = 0;
  218. break;
  219. default:
  220. if(pread(portfd[len], data, len, p) != len){
  221. fprint(2, "bad %d bit port read %.4lux: %r\n", len*8, p);
  222. trap(&cpu, EIO);
  223. }
  224. w = gw[len](data);
  225. }
  226. if(porttrace)
  227. fprint(2, "rport %.4lux %.*lux\n", p, len<<1, w);
  228. print_func_exit();
  229. return w;
  230. }
  231. static void
  232. wport(void *aux, unsigned long p, unsigned long w, int len)
  233. {
  234. print_func_entry();
  235. unsigned char data[4];
  236. if(porttrace)
  237. fprint(2, "wport %.4lux %.*lux\n", p, len<<1, w);
  238. switch(p){
  239. case 0x20: /* PIC 1 */
  240. case 0x21:
  241. break;
  242. case 0x40:
  243. case 0x41:
  244. case 0x42:
  245. case 0x43:
  246. runclock();
  247. wpit(pit, p - 0x40, w);
  248. break;
  249. case 0x60: /* keyboard controller data port */
  250. break;
  251. case 0x61: /* keyboard controller port B */
  252. setgate(&pit[2], w & 1);
  253. break;
  254. case 0x62: /* PPI (XT only) */
  255. case 0x63:
  256. case 0x64: /* KB controller input buffer (ISA, EISA) */
  257. case 0x65: /* A20 gate (bit 2) */
  258. break;
  259. case 0x70: /* RTC addr */
  260. rtcaddr = w & 0xFF;
  261. break;
  262. case 0x71: /* RTC data */
  263. break;
  264. case 0x80:
  265. case 0x84:
  266. case 0x85:
  267. case 0x86:
  268. case 0x88:
  269. case 0x8c:
  270. case 0x8d:
  271. case 0x8e:
  272. pageregtmp[p-0x80] = w & 0xFF;
  273. break;
  274. case 0x92: /* system control port a */
  275. case 0x94: /* system port enable setup register */
  276. case 0x96:
  277. break;
  278. case 0xA0: /* PIC 2 */
  279. case 0xA1:
  280. break;
  281. default:
  282. pw[len](data, w);
  283. if(pwrite(portfd[len], data, len, p) != len){
  284. fprint(2, "bad %d bit port write %.4lux: %r\n", len*8, p);
  285. trap(&cpu, EIO);
  286. }
  287. }
  288. print_func_exit();
  289. }
  290. static Bus memio[] = {
  291. /* 0 */ memory, rmem, wmem, /* RAM: IVT, BIOS data area */
  292. /* 1 */ memory, rmem, wmem, /* custom */
  293. /* 2 */ nil, rbad, wbad,
  294. /* 3 */ nil, rbad, wbad,
  295. /* 4 */ nil, rbad, wbad,
  296. /* 5 */ nil, rbad, wbad,
  297. /* 6 */ nil, rbad, wbad,
  298. /* 7 */ nil, rbad, wbad,
  299. /* 8 */ nil, rbad, wbad,
  300. /* 9 */ memory, rmem, wmem, /* RAM: extended BIOS data area */
  301. /* A */ nil, rrealmem, wrealmem, /* RAM: VGA framebuffer */
  302. /* B */ nil, rrealmem, wrealmem, /* RAM: VGA framebuffer */
  303. /* C */ memory, rmem, wmem, /* ROM: VGA BIOS */
  304. /* D */ nil, rbad, wbad,
  305. /* E */ memory, rmem, wmem, /* ROM: BIOS */
  306. /* F */ memory, rmem, wbad, /* ROM: BIOS */
  307. };
  308. static Bus portio = {
  309. nil, rport, wport,
  310. };
  311. static void
  312. cpuinit(void)
  313. {
  314. print_func_entry();
  315. int i;
  316. fmtinstall('I', instfmt);
  317. fmtinstall('J', flagfmt);
  318. fmtinstall('C', cpufmt);
  319. if((portfd[1] = open("#P/iob", ORDWR)) < 0)
  320. sysfatal("open iob: %r");
  321. if((portfd[2] = open("#P/iow", ORDWR)) < 0)
  322. sysfatal("open iow: %r");
  323. if((portfd[4] = open("#P/iol", ORDWR)) < 0)
  324. sysfatal("open iol: %r");
  325. if((realmemfd = open("#P/realmodemem", ORDWR)) < 0)
  326. sysfatal("open realmodemem: %r");
  327. for(i=0; i<nelem(memio); i++){
  328. unsigned long off;
  329. if(memio[i].r != rmem)
  330. continue;
  331. off = (unsigned long)i << 16;
  332. seek(realmemfd, off, 0);
  333. if(readn(realmemfd, memory + off, 0x10000) != 0x10000)
  334. sysfatal("read real mem %lux: %r\n", off);
  335. }
  336. cpu.ic = 0;
  337. cpu.mem = memio;
  338. cpu.port = &portio;
  339. cpu.alen = cpu.olen = cpu.slen = 2;
  340. print_func_exit();
  341. }
  342. static char Ebusy[] = "device is busy";
  343. static char Eintr[] = "interrupted";
  344. static char Eperm[] = "permission denied";
  345. static char Eio[] = "i/o error";
  346. static char Emem[] = "bad memory access";
  347. static char Enonexist[] = "file does not exist";
  348. static char Ebadspec[] = "bad attach specifier";
  349. static char Ewalk[] = "walk in non directory";
  350. static char Ebadureg[] = "write a Ureg";
  351. static char Ebadoff[] = "invalid offset";
  352. static char Ebadtrap[] = "bad trap";
  353. static char *trapstr[] = {
  354. [EDIV0] "division by zero",
  355. [EDEBUG] "debug exception",
  356. [ENMI] "not maskable interrupt",
  357. [EBRK] "breakpoint",
  358. [EINTO] "into overflow",
  359. [EBOUND] "bounds check",
  360. [EBADOP] "bad opcode",
  361. [ENOFPU] "no fpu installed",
  362. [EDBLF] "double fault",
  363. [EFPUSEG] "fpu segment overflow",
  364. [EBADTSS] "invalid task state segment",
  365. [ENP] "segment not present",
  366. [ESTACK] "stack fault",
  367. [EGPF] "general protection fault",
  368. [EPF] "page fault",
  369. };
  370. static int flushed(void *);
  371. #define GETUREG(x) gw[sizeof(u->x)]((unsigned char*)&u->x)
  372. #define PUTUREG(x,y) pw[sizeof(u->x)]((unsigned char*)&u->x,y)
  373. static char*
  374. realmode(Cpu *cpu, struct Ureg *u, void *r)
  375. {
  376. print_func_entry();
  377. char *err;
  378. int i;
  379. /* N.B. it wasy always 16 bits in the kernel. */
  380. cpu->reg[RDI] = GETUREG(di) & 0xffff;
  381. cpu->reg[RSI] = GETUREG(si);
  382. cpu->reg[RBP] = GETUREG(bp);
  383. cpu->reg[RBX] = GETUREG(bx);
  384. cpu->reg[RDX] = GETUREG(dx);
  385. cpu->reg[RCX] = GETUREG(cx);
  386. cpu->reg[RAX] = GETUREG(ax);
  387. // cpu->reg[RGS] = GETUREG(gs);
  388. // cpu->reg[RFS] = GETUREG(fs);
  389. cpu->reg[RES] = GETUREG(di) >> 16;
  390. // cpu->reg[RDS] = GETUREG(ds);
  391. cpu->reg[RFL] = GETUREG(flags);
  392. // if(i = GETUREG(trap)){
  393. // cpu->reg[RSS] = 0x0000;
  394. // cpu->reg[RSP] = 0x7C00;
  395. // cpu->reg[RCS] = (RMCODE>>4)&0xF000;
  396. // cpu->reg[RIP] = RMCODE & 0xFFFF;
  397. // memory[RMCODE] = 0xf4; /* HLT instruction */
  398. // if(intr(cpu, i) < 0)
  399. // return Ebadtrap;
  400. // } else {
  401. cpu->reg[RSS] = GETUREG(ss);
  402. cpu->reg[RSP] = GETUREG(sp);
  403. cpu->reg[RCS] = GETUREG(cs);
  404. cpu->reg[RIP] = GETUREG(pc);
  405. // }
  406. startclock();
  407. for(;;){
  408. if(cputrace)
  409. fprint(2, "%C\n", cpu);
  410. switch(i = xec(cpu, (porttrace | cputrace) ? 1 : 100000)){
  411. case -1:
  412. if(flushed(r)){
  413. err = Eintr;
  414. break;
  415. }
  416. runclock();
  417. continue;
  418. /* normal interrupts */
  419. default:
  420. if(intr(cpu, i) < 0){
  421. err = Ebadtrap;
  422. break;
  423. }
  424. continue;
  425. /* pseudo-interrupts */
  426. case EHALT:
  427. err = nil;
  428. break;
  429. case EIO:
  430. err = Eio;
  431. break;
  432. case EMEM:
  433. err = Emem;
  434. break;
  435. /* processor traps */
  436. case EDIV0:
  437. case EDEBUG:
  438. case ENMI:
  439. case EBRK:
  440. case EINTO:
  441. case EBOUND:
  442. case EBADOP:
  443. case ENOFPU:
  444. case EDBLF:
  445. case EFPUSEG:
  446. case EBADTSS:
  447. case ENP:
  448. case ESTACK:
  449. case EGPF:
  450. case EPF:
  451. //PUTUREG(trap, i);
  452. err = trapstr[i];
  453. break;
  454. }
  455. break;
  456. }
  457. if(err)
  458. fprint(2, "%s\n%C\n", err, cpu);
  459. PUTUREG(di, cpu->reg[RDI]);
  460. PUTUREG(si, cpu->reg[RSI]);
  461. PUTUREG(bp, cpu->reg[RBP]);
  462. PUTUREG(bx, cpu->reg[RBX]);
  463. PUTUREG(dx, cpu->reg[RDX]);
  464. PUTUREG(cx, cpu->reg[RCX]);
  465. PUTUREG(ax, cpu->reg[RAX]);
  466. PUTUREG(gs, cpu->reg[RGS]);
  467. PUTUREG(fs, cpu->reg[RFS]);
  468. PUTUREG(es, cpu->reg[RES]);
  469. PUTUREG(ds, cpu->reg[RDS]);
  470. PUTUREG(flags, cpu->reg[RFL]);
  471. PUTUREG(pc, cpu->reg[RIP]);
  472. PUTUREG(cs, cpu->reg[RCS]);
  473. PUTUREG(sp, cpu->reg[RSP]);
  474. PUTUREG(ss, cpu->reg[RSS]);
  475. print_func_exit();
  476. return err;
  477. }
  478. enum {
  479. Qroot,
  480. Qcall,
  481. Qmem,
  482. Nqid,
  483. };
  484. static struct Qtab {
  485. char *name;
  486. int mode;
  487. int type;
  488. int length;
  489. } qtab[Nqid] = {
  490. "/",
  491. DMDIR|0555,
  492. QTDIR,
  493. 0,
  494. "realmode",
  495. 0666,
  496. 0,
  497. 0,
  498. "realmodemem",
  499. 0666,
  500. 0,
  501. MEMSIZE,
  502. };
  503. static int
  504. fillstat(unsigned long qid, Dir *d)
  505. {
  506. print_func_entry();
  507. struct Qtab *t;
  508. memset(d, 0, sizeof(Dir));
  509. d->uid = "realemu";
  510. d->gid = "realemu";
  511. d->muid = "";
  512. d->qid = (Qid){qid, 0, 0};
  513. d->atime = time(0);
  514. t = qtab + qid;
  515. d->name = t->name;
  516. d->qid.type = t->type;
  517. d->mode = t->mode;
  518. d->length = t->length;
  519. print_func_exit();
  520. return 1;
  521. }
  522. static void
  523. fsattach(Req *r)
  524. {
  525. print_func_entry();
  526. char *spec;
  527. spec = r->ifcall.aname;
  528. if(spec && spec[0]){
  529. respond(r, Ebadspec);
  530. print_func_exit();
  531. return;
  532. }
  533. r->fid->qid = (Qid){Qroot, 0, QTDIR};
  534. r->ofcall.qid = r->fid->qid;
  535. respond(r, nil);
  536. print_func_exit();
  537. }
  538. static void
  539. fsstat(Req *r)
  540. {
  541. print_func_entry();
  542. fillstat((unsigned long)r->fid->qid.path, &r->d);
  543. r->d.name = estrdup9p(r->d.name);
  544. r->d.uid = estrdup9p(r->d.uid);
  545. r->d.gid = estrdup9p(r->d.gid);
  546. r->d.muid = estrdup9p(r->d.muid);
  547. respond(r, nil);
  548. print_func_exit();
  549. }
  550. static char*
  551. fswalk1(Fid *fid, char *name, Qid *qid)
  552. {
  553. print_func_entry();
  554. int i;
  555. unsigned long path;
  556. path = fid->qid.path;
  557. switch(path){
  558. case Qroot:
  559. if (strcmp(name, "..") == 0) {
  560. *qid = (Qid){Qroot, 0, QTDIR};
  561. fid->qid = *qid;
  562. print_func_exit();
  563. return nil;
  564. }
  565. for(i = fid->qid.path; i<Nqid; i++){
  566. if(strcmp(name, qtab[i].name) != 0)
  567. continue;
  568. *qid = (Qid){i, 0, 0};
  569. fid->qid = *qid;
  570. print_func_exit();
  571. return nil;
  572. }
  573. print_func_exit();
  574. return Enonexist;
  575. default:
  576. print_func_exit();
  577. return Ewalk;
  578. }
  579. }
  580. static void
  581. fsopen(Req *r)
  582. {
  583. print_func_entry();
  584. static int need[4] = { 4, 2, 6, 1 };
  585. struct Qtab *t;
  586. int n;
  587. t = qtab + r->fid->qid.path;
  588. n = need[r->ifcall.mode & 3];
  589. if((n & t->mode) != n)
  590. respond(r, Eperm);
  591. else
  592. respond(r, nil);
  593. print_func_exit();
  594. }
  595. static int
  596. readtopdir(Fid *fid, unsigned char *buf, long off, int cnt, int blen)
  597. {
  598. print_func_entry();
  599. int i, m, n;
  600. long pos;
  601. Dir d;
  602. n = 0;
  603. pos = 0;
  604. for (i = 1; i < Nqid; i++){
  605. fillstat(i, &d);
  606. m = convD2M(&d, &buf[n], blen-n);
  607. if(off <= pos){
  608. if(m <= BIT16SZ || m > cnt)
  609. break;
  610. n += m;
  611. cnt -= m;
  612. }
  613. pos += m;
  614. }
  615. print_func_exit();
  616. return n;
  617. }
  618. static Channel *reqchan;
  619. static void
  620. cpuproc(void *data)
  621. {
  622. print_func_entry();
  623. static struct Ureg rmu;
  624. unsigned long path;
  625. long long o;
  626. unsigned long n;
  627. char *p;
  628. Req *r;
  629. threadsetname("cpuproc");
  630. while(r = recvp(reqchan)){
  631. if(flushed(r)){
  632. respond(r, Eintr);
  633. continue;
  634. }
  635. path = r->fid->qid.path;
  636. p = r->ifcall.data;
  637. n = r->ifcall.count;
  638. o = r->ifcall.offset;
  639. switch(((int)r->ifcall.type<<8)|path){
  640. case (Tread<<8) | Qmem:
  641. readbuf(r, memory, MEMSIZE);
  642. respond(r, nil);
  643. break;
  644. case (Tread<<8) | Qcall:
  645. readbuf(r, &rmu, sizeof rmu);
  646. respond(r, nil);
  647. break;
  648. case (Twrite<<8) | Qmem:
  649. if(o < 0 || o >= MEMSIZE || o+n > MEMSIZE){
  650. respond(r, Ebadoff);
  651. break;
  652. }
  653. memmove(memory + o, p, n);
  654. r->ofcall.count = n;
  655. respond(r, nil);
  656. break;
  657. case (Twrite<<8) | Qcall:
  658. if(n != sizeof rmu){
  659. fprint(2, "n is %d, sizeof(rmu) %d: %s\n", n, sizeof(rmu), Ebadureg);
  660. respond(r, Ebadureg);
  661. break;
  662. }
  663. memmove(&rmu, p, n);
  664. if(p = realmode(&cpu, &rmu, r)){
  665. respond(r, p);
  666. break;
  667. }
  668. r->ofcall.count = n;
  669. respond(r, nil);
  670. break;
  671. }
  672. }
  673. print_func_exit();
  674. }
  675. static Channel *flushchan;
  676. static int
  677. flushed(void *r)
  678. {
  679. print_func_entry();
  680. print_func_exit();
  681. return nbrecvp(flushchan) == r;
  682. }
  683. static void
  684. fsflush(Req *r)
  685. {
  686. print_func_entry();
  687. nbsendp(flushchan, r->oldreq);
  688. respond(r, nil);
  689. print_func_exit();
  690. }
  691. static void
  692. dispatch(Req *r)
  693. {
  694. print_func_entry();
  695. if(!nbsendp(reqchan, r))
  696. respond(r, Ebusy);
  697. print_func_exit();
  698. }
  699. static void
  700. fsread(Req *r)
  701. {
  702. print_func_entry();
  703. switch((unsigned long)r->fid->qid.path){
  704. case Qroot:
  705. r->ofcall.count = readtopdir(r->fid, (void*)r->ofcall.data, r->ifcall.offset,
  706. r->ifcall.count, r->ifcall.count);
  707. respond(r, nil);
  708. break;
  709. default:
  710. dispatch(r);
  711. }
  712. print_func_exit();
  713. }
  714. static void
  715. fsend(Srv* srv)
  716. {
  717. print_func_entry();
  718. threadexitsall(nil);
  719. print_func_exit();
  720. }
  721. static Srv fs = {
  722. .attach= fsattach,
  723. .walk1= fswalk1,
  724. .open= fsopen,
  725. .read= fsread,
  726. .write= dispatch,
  727. .stat= fsstat,
  728. .flush= fsflush,
  729. .end= fsend,
  730. };
  731. static void
  732. usage(void)
  733. {
  734. print_func_entry();
  735. fprint(2, "usgae:\t%s [-Dpt] [-s srvname] [-m mountpoint]\n", argv0);
  736. exits("usage");
  737. print_func_exit();
  738. }
  739. void
  740. threadmain(int argc, char *argv[])
  741. {
  742. char *mnt = "/dev";
  743. char *srv = nil;
  744. ARGBEGIN{
  745. case 'D':
  746. chatty9p++;
  747. break;
  748. case 'p':
  749. porttrace = 1;
  750. break;
  751. case 't':
  752. cputrace = 1;
  753. break;
  754. case 'x':
  755. set_printx(1);
  756. break;
  757. case 's':
  758. srv = EARGF(usage());
  759. mnt = nil;
  760. break;
  761. case 'm':
  762. mnt = EARGF(usage());
  763. break;
  764. default:
  765. usage();
  766. }ARGEND
  767. cpuinit();
  768. reqchan = chancreate(sizeof(Req*), 8);
  769. flushchan = chancreate(sizeof(Req*), 8);
  770. procrfork(cpuproc, nil, 16*1024, RFNAMEG|RFNOTEG);
  771. threadpostmountsrv(&fs, srv, mnt, MBEFORE);
  772. }