devuart.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "../port/error.h"
  8. #include "../port/netif.h"
  9. enum
  10. {
  11. /* soft flow control chars */
  12. CTLS= 023,
  13. CTLQ= 021,
  14. };
  15. extern Dev uartdevtab;
  16. extern PhysUart* physuart[];
  17. static Uart* uartlist;
  18. static Uart** uart;
  19. static int uartnuart;
  20. static Dirtab *uartdir;
  21. static int uartndir;
  22. static Timer *uarttimer;
  23. struct Uartalloc {
  24. Lock;
  25. Uart *elist; /* list of enabled interfaces */
  26. } uartalloc;
  27. static void uartclock(void);
  28. static void uartflow(void*);
  29. /*
  30. * enable/disable uart and add/remove to list of enabled uarts
  31. */
  32. //static
  33. Uart*
  34. uartenable(Uart *p)
  35. {
  36. Uart **l;
  37. if (up == nil)
  38. return p; /* too soon; try again later */
  39. // return nil;
  40. if(p->iq == nil){
  41. if((p->iq = qopen(8*1024, 0, uartflow, p)) == nil)
  42. return nil;
  43. }
  44. else
  45. qreopen(p->iq);
  46. if(p->oq == nil){
  47. if((p->oq = qopen(8*1024, 0, uartkick, p)) == nil){
  48. qfree(p->iq);
  49. p->iq = nil;
  50. return nil;
  51. }
  52. }
  53. else
  54. qreopen(p->oq);
  55. p->ir = p->istage;
  56. p->iw = p->istage;
  57. p->ie = &p->istage[Stagesize];
  58. p->op = p->ostage;
  59. p->oe = p->ostage;
  60. p->hup_dsr = p->hup_dcd = 0;
  61. p->dsr = p->dcd = 0;
  62. /* assume we can send */
  63. p->cts = 1;
  64. p->ctsbackoff = 0;
  65. if (up) {
  66. if(p->bits == 0)
  67. uartctl(p, "l8");
  68. if(p->stop == 0)
  69. uartctl(p, "s1");
  70. if(p->parity == 0)
  71. uartctl(p, "pn");
  72. if(p->baud == 0)
  73. uartctl(p, "b9600");
  74. (*p->phys->enable)(p, 1);
  75. }
  76. /*
  77. * use ilock because uartclock can otherwise interrupt here
  78. * and would hang on an attempt to lock uartalloc.
  79. */
  80. ilock(&uartalloc);
  81. for(l = &uartalloc.elist; *l; l = &(*l)->elist){
  82. if(*l == p)
  83. break;
  84. }
  85. if(*l == 0){
  86. p->elist = uartalloc.elist;
  87. uartalloc.elist = p;
  88. }
  89. p->enabled = 1;
  90. iunlock(&uartalloc);
  91. return p;
  92. }
  93. static void
  94. uartdisable(Uart *p)
  95. {
  96. Uart **l;
  97. (*p->phys->disable)(p);
  98. ilock(&uartalloc);
  99. for(l = &uartalloc.elist; *l; l = &(*l)->elist){
  100. if(*l == p){
  101. *l = p->elist;
  102. break;
  103. }
  104. }
  105. p->enabled = 0;
  106. iunlock(&uartalloc);
  107. }
  108. void
  109. uartmouse(Uart* p, int (*putc)(Queue*, int), int setb1200)
  110. {
  111. qlock(p);
  112. if(p->opens++ == 0 && uartenable(p) == nil){
  113. qunlock(p);
  114. error(Enodev);
  115. }
  116. if(setb1200)
  117. uartctl(p, "b1200");
  118. p->putc = putc;
  119. p->special = 1;
  120. qunlock(p);
  121. }
  122. void
  123. uartsetmouseputc(Uart* p, int (*putc)(Queue*, int))
  124. {
  125. qlock(p);
  126. if(p->opens == 0 || p->special == 0){
  127. qunlock(p);
  128. error(Enodev);
  129. }
  130. p->putc = putc;
  131. qunlock(p);
  132. }
  133. static void
  134. setlength(int i)
  135. {
  136. Uart *p;
  137. if(i > 0){
  138. p = uart[i];
  139. if(p && p->opens && p->iq)
  140. uartdir[1+3*i].length = qlen(p->iq);
  141. } else for(i = 0; i < uartnuart; i++){
  142. p = uart[i];
  143. if(p && p->opens && p->iq)
  144. uartdir[1+3*i].length = qlen(p->iq);
  145. }
  146. }
  147. /*
  148. * set up the '#t' directory
  149. */
  150. static void
  151. uartreset(void)
  152. {
  153. int i;
  154. Dirtab *dp;
  155. Uart *p, *tail;
  156. tail = nil;
  157. for(i = 0; physuart[i] != nil; i++){
  158. if(physuart[i]->pnp == nil)
  159. continue;
  160. if((p = physuart[i]->pnp()) == nil)
  161. continue;
  162. if(uartlist != nil)
  163. tail->next = p;
  164. else
  165. uartlist = p;
  166. for(tail = p; tail->next != nil; tail = tail->next)
  167. uartnuart++;
  168. uartnuart++;
  169. }
  170. if(uartnuart)
  171. uart = xalloc(uartnuart*sizeof(Uart*));
  172. uartndir = 1 + 3*uartnuart;
  173. uartdir = xalloc(uartndir * sizeof(Dirtab));
  174. if (uart == nil || uartdir == nil)
  175. panic("uartreset: no memory");
  176. dp = uartdir;
  177. strcpy(dp->name, ".");
  178. mkqid(&dp->qid, 0, 0, QTDIR);
  179. dp->length = 0;
  180. dp->perm = DMDIR|0555;
  181. dp++;
  182. p = uartlist;
  183. for(i = 0; i < uartnuart; i++){
  184. /* 3 directory entries per port */
  185. snprint(dp->name, sizeof dp->name, "eia%d", i);
  186. dp->qid.path = NETQID(i, Ndataqid);
  187. dp->perm = 0660;
  188. dp++;
  189. snprint(dp->name, sizeof dp->name, "eia%dctl", i);
  190. dp->qid.path = NETQID(i, Nctlqid);
  191. dp->perm = 0660;
  192. dp++;
  193. snprint(dp->name, sizeof dp->name, "eia%dstatus", i);
  194. dp->qid.path = NETQID(i, Nstatqid);
  195. dp->perm = 0444;
  196. dp++;
  197. uart[i] = p;
  198. p->dev = i;
  199. if(p->console || p->special){
  200. if(uartenable(p) != nil){
  201. if(p->console && up){
  202. kbdq = p->iq;
  203. serialoq = p->oq;
  204. p->putc = kbdcr2nl;
  205. }
  206. p->opens++;
  207. }
  208. }
  209. p = p->next;
  210. }
  211. if(uartnuart){
  212. /*
  213. * at 115200 baud, the 1024 char buffer takes 56 ms to process,
  214. * processing it every 22 ms should be fine.
  215. */
  216. uarttimer = addclock0link(uartclock, 22);
  217. }
  218. }
  219. static Chan*
  220. uartattach(char *spec)
  221. {
  222. return devattach('t', spec);
  223. }
  224. static Walkqid*
  225. uartwalk(Chan *c, Chan *nc, char **name, int nname)
  226. {
  227. return devwalk(c, nc, name, nname, uartdir, uartndir, devgen);
  228. }
  229. static int
  230. uartstat(Chan *c, uchar *dp, int n)
  231. {
  232. if(NETTYPE(c->qid.path) == Ndataqid)
  233. setlength(NETID(c->qid.path));
  234. return devstat(c, dp, n, uartdir, uartndir, devgen);
  235. }
  236. static Chan*
  237. uartopen(Chan *c, int omode)
  238. {
  239. Uart *p;
  240. c = devopen(c, omode, uartdir, uartndir, devgen);
  241. switch(NETTYPE(c->qid.path)){
  242. case Nctlqid:
  243. case Ndataqid:
  244. p = uart[NETID(c->qid.path)];
  245. qlock(p);
  246. if(p->opens++ == 0 && uartenable(p) == nil){
  247. qunlock(p);
  248. c->flag &= ~COPEN;
  249. error(Enodev);
  250. }
  251. qunlock(p);
  252. break;
  253. }
  254. c->iounit = qiomaxatomic;
  255. return c;
  256. }
  257. static int
  258. uartdrained(void* arg)
  259. {
  260. Uart *p;
  261. p = arg;
  262. return qlen(p->oq) == 0 && p->op == p->oe;
  263. }
  264. static void
  265. uartdrainoutput(Uart *p)
  266. {
  267. if(!p->enabled || up == nil)
  268. return;
  269. p->drain = 1;
  270. if(waserror()){
  271. p->drain = 0;
  272. nexterror();
  273. }
  274. sleep(&p->r, uartdrained, p);
  275. poperror();
  276. }
  277. static void
  278. uartclose(Chan *c)
  279. {
  280. Uart *p;
  281. if(c->qid.type & QTDIR)
  282. return;
  283. if((c->flag & COPEN) == 0)
  284. return;
  285. switch(NETTYPE(c->qid.path)){
  286. case Ndataqid:
  287. case Nctlqid:
  288. p = uart[NETID(c->qid.path)];
  289. qlock(p);
  290. if(--(p->opens) == 0){
  291. qclose(p->iq);
  292. ilock(&p->rlock);
  293. p->ir = p->iw = p->istage;
  294. iunlock(&p->rlock);
  295. /*
  296. */
  297. qhangup(p->oq, nil);
  298. if(!waserror()){
  299. uartdrainoutput(p);
  300. poperror();
  301. }
  302. qclose(p->oq);
  303. uartdisable(p);
  304. p->dcd = p->dsr = p->dohup = 0;
  305. }
  306. qunlock(p);
  307. break;
  308. }
  309. }
  310. static long
  311. uartread(Chan *c, void *buf, long n, vlong off)
  312. {
  313. Uart *p;
  314. ulong offset = off;
  315. if(c->qid.type & QTDIR){
  316. setlength(-1);
  317. return devdirread(c, buf, n, uartdir, uartndir, devgen);
  318. }
  319. p = uart[NETID(c->qid.path)];
  320. switch(NETTYPE(c->qid.path)){
  321. case Ndataqid:
  322. return qread(p->iq, buf, n);
  323. case Nctlqid:
  324. return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE);
  325. case Nstatqid:
  326. return (*p->phys->status)(p, buf, n, offset);
  327. }
  328. return 0;
  329. }
  330. int
  331. uartctl(Uart *p, char *cmd)
  332. {
  333. char *f[16];
  334. int i, n, nf;
  335. nf = tokenize(cmd, f, nelem(f));
  336. for(i = 0; i < nf; i++){
  337. if(strncmp(f[i], "break", 5) == 0){
  338. (*p->phys->dobreak)(p, 0);
  339. continue;
  340. }
  341. n = atoi(f[i]+1);
  342. switch(*f[i]){
  343. case 'B':
  344. case 'b':
  345. uartdrainoutput(p);
  346. if((*p->phys->baud)(p, n) < 0)
  347. return -1;
  348. break;
  349. case 'C':
  350. case 'c':
  351. p->hup_dcd = n;
  352. break;
  353. case 'D':
  354. case 'd':
  355. uartdrainoutput(p);
  356. (*p->phys->dtr)(p, n);
  357. break;
  358. case 'E':
  359. case 'e':
  360. p->hup_dsr = n;
  361. break;
  362. case 'f':
  363. case 'F':
  364. if(p->oq != nil)
  365. qflush(p->oq);
  366. break;
  367. case 'H':
  368. case 'h':
  369. if(p->iq != nil)
  370. qhangup(p->iq, 0);
  371. if(p->oq != nil)
  372. qhangup(p->oq, 0);
  373. break;
  374. case 'i':
  375. case 'I':
  376. uartdrainoutput(p);
  377. (*p->phys->fifo)(p, n);
  378. break;
  379. case 'K':
  380. case 'k':
  381. uartdrainoutput(p);
  382. (*p->phys->dobreak)(p, n);
  383. break;
  384. case 'L':
  385. case 'l':
  386. uartdrainoutput(p);
  387. if((*p->phys->bits)(p, n) < 0)
  388. return -1;
  389. break;
  390. case 'm':
  391. case 'M':
  392. uartdrainoutput(p);
  393. (*p->phys->modemctl)(p, n);
  394. break;
  395. case 'n':
  396. case 'N':
  397. if(p->oq != nil)
  398. qnoblock(p->oq, n);
  399. break;
  400. case 'P':
  401. case 'p':
  402. uartdrainoutput(p);
  403. if((*p->phys->parity)(p, *(f[i]+1)) < 0)
  404. return -1;
  405. break;
  406. case 'Q':
  407. case 'q':
  408. if(p->iq != nil)
  409. qsetlimit(p->iq, n);
  410. if(p->oq != nil)
  411. qsetlimit(p->oq, n);
  412. break;
  413. case 'R':
  414. case 'r':
  415. uartdrainoutput(p);
  416. (*p->phys->rts)(p, n);
  417. break;
  418. case 'S':
  419. case 's':
  420. uartdrainoutput(p);
  421. if((*p->phys->stop)(p, n) < 0)
  422. return -1;
  423. break;
  424. case 'W':
  425. case 'w':
  426. if(uarttimer == nil || n < 1)
  427. return -1;
  428. uarttimer->tns = (vlong)n * 100000LL;
  429. break;
  430. case 'X':
  431. case 'x':
  432. if(p->enabled){
  433. ilock(&p->tlock);
  434. p->xonoff = n;
  435. iunlock(&p->tlock);
  436. }
  437. break;
  438. }
  439. }
  440. return 0;
  441. }
  442. static long
  443. uartwrite(Chan *c, void *buf, long n, vlong)
  444. {
  445. Uart *p;
  446. char *cmd;
  447. if(c->qid.type & QTDIR)
  448. error(Eperm);
  449. p = uart[NETID(c->qid.path)];
  450. switch(NETTYPE(c->qid.path)){
  451. case Ndataqid:
  452. qlock(p);
  453. if(waserror()){
  454. qunlock(p);
  455. nexterror();
  456. }
  457. n = qwrite(p->oq, buf, n);
  458. qunlock(p);
  459. poperror();
  460. break;
  461. case Nctlqid:
  462. cmd = malloc(n+1);
  463. memmove(cmd, buf, n);
  464. cmd[n] = 0;
  465. qlock(p);
  466. if(waserror()){
  467. qunlock(p);
  468. free(cmd);
  469. nexterror();
  470. }
  471. /* let output drain */
  472. if(uartctl(p, cmd) < 0)
  473. error(Ebadarg);
  474. qunlock(p);
  475. poperror();
  476. free(cmd);
  477. break;
  478. }
  479. return n;
  480. }
  481. static int
  482. uartwstat(Chan *c, uchar *dp, int n)
  483. {
  484. Dir d;
  485. Dirtab *dt;
  486. if(!iseve())
  487. error(Eperm);
  488. if(QTDIR & c->qid.type)
  489. error(Eperm);
  490. if(NETTYPE(c->qid.path) == Nstatqid)
  491. error(Eperm);
  492. dt = &uartdir[1 + 3 * NETID(c->qid.path)];
  493. n = convM2D(dp, n, &d, nil);
  494. if(n == 0)
  495. error(Eshortstat);
  496. if(d.mode != ~0UL)
  497. dt[0].perm = dt[1].perm = d.mode;
  498. return n;
  499. }
  500. void
  501. uartpower(int on)
  502. {
  503. Uart *p;
  504. for(p = uartlist; p != nil; p = p->next) {
  505. if(p->phys->power)
  506. (*p->phys->power)(p, on);
  507. }
  508. }
  509. Dev uartdevtab = {
  510. 't',
  511. "uart",
  512. uartreset,
  513. devinit,
  514. devshutdown,
  515. uartattach,
  516. uartwalk,
  517. uartstat,
  518. uartopen,
  519. devcreate,
  520. uartclose,
  521. uartread,
  522. devbread,
  523. uartwrite,
  524. devbwrite,
  525. devremove,
  526. uartwstat,
  527. uartpower,
  528. };
  529. /*
  530. * restart input if it's off
  531. */
  532. static void
  533. uartflow(void *v)
  534. {
  535. Uart *p;
  536. p = v;
  537. if(p->modem)
  538. (*p->phys->rts)(p, 1);
  539. }
  540. /*
  541. * put some bytes into the local queue to avoid calling
  542. * qconsume for every character
  543. */
  544. int
  545. uartstageoutput(Uart *p)
  546. {
  547. int n;
  548. n = qconsume(p->oq, p->ostage, Stagesize);
  549. if(n <= 0)
  550. // n = 0; /* experiment */
  551. return 0;
  552. p->op = p->ostage;
  553. p->oe = p->ostage + n;
  554. return n;
  555. }
  556. /*
  557. * restart output
  558. */
  559. void
  560. uartkick(void *v)
  561. {
  562. Uart *p = v;
  563. if(p->blocked)
  564. return;
  565. ilock(&p->tlock);
  566. (*p->phys->kick)(p);
  567. iunlock(&p->tlock);
  568. if(p->drain && uartdrained(p)){
  569. p->drain = 0;
  570. wakeup(&p->r);
  571. }
  572. }
  573. /*
  574. * Move data from the interrupt staging area to
  575. * the input Queue.
  576. */
  577. static void
  578. uartstageinput(Uart *p)
  579. {
  580. int n;
  581. uchar *ir, *iw;
  582. while(p->ir != p->iw){
  583. ir = p->ir;
  584. if(p->ir > p->iw){
  585. iw = p->ie;
  586. p->ir = p->istage;
  587. }
  588. else{
  589. iw = p->iw;
  590. p->ir = p->iw;
  591. }
  592. if((n = qproduce(p->iq, ir, iw - ir)) < 0){
  593. p->serr++;
  594. (*p->phys->rts)(p, 0);
  595. }
  596. else if(n == 0)
  597. p->berr++;
  598. }
  599. }
  600. /*
  601. * receive a character at interrupt time
  602. */
  603. void
  604. uartrecv(Uart *p, char ch)
  605. {
  606. uchar *next;
  607. /* software flow control */
  608. if(p->xonoff){
  609. if(ch == CTLS){
  610. p->blocked = 1;
  611. }else if(ch == CTLQ){
  612. p->blocked = 0;
  613. p->ctsbackoff = 2; /* clock gets output going again */
  614. }
  615. }
  616. /* receive the character */
  617. if(p->putc)
  618. p->putc(p->iq, ch);
  619. else if (p->iw) { /* maybe the line isn't enabled yet */
  620. ilock(&p->rlock);
  621. next = p->iw + 1;
  622. if(next == p->ie)
  623. next = p->istage;
  624. if(next == p->ir)
  625. uartstageinput(p);
  626. if(next != p->ir){
  627. *p->iw = ch;
  628. p->iw = next;
  629. }
  630. iunlock(&p->rlock);
  631. }
  632. }
  633. /*
  634. * we save up input characters till clock time to reduce
  635. * per character interrupt overhead.
  636. */
  637. static void
  638. uartclock(void)
  639. {
  640. Uart *p;
  641. ilock(&uartalloc);
  642. for(p = uartalloc.elist; p; p = p->elist){
  643. /* this hopefully amortizes cost of qproduce to many chars */
  644. if(p->iw != p->ir){
  645. ilock(&p->rlock);
  646. uartstageinput(p);
  647. iunlock(&p->rlock);
  648. }
  649. /* hang up if requested */
  650. if(p->dohup){
  651. qhangup(p->iq, 0);
  652. qhangup(p->oq, 0);
  653. p->dohup = 0;
  654. }
  655. /* this adds hysteresis to hardware/software flow control */
  656. if(p->ctsbackoff){
  657. ilock(&p->tlock);
  658. if(p->ctsbackoff){
  659. if(--(p->ctsbackoff) == 0)
  660. (*p->phys->kick)(p);
  661. }
  662. iunlock(&p->tlock);
  663. }
  664. uartkick(p); /* keep it moving */
  665. }
  666. iunlock(&uartalloc);
  667. }
  668. /*
  669. * polling console input, output
  670. */
  671. Uart* consuart;
  672. int
  673. uartgetc(void)
  674. {
  675. if(consuart == nil || consuart->phys->getc == nil)
  676. return -1;
  677. return consuart->phys->getc(consuart);
  678. }
  679. void
  680. uartputc(int c)
  681. {
  682. char c2;
  683. if(consuart == nil || consuart->phys->putc == nil) {
  684. c2 = c;
  685. _uartputs(&c2, 1);
  686. return;
  687. }
  688. consuart->phys->putc(consuart, c);
  689. }
  690. void
  691. uartputs(char *s, int n)
  692. {
  693. char *e;
  694. if(consuart == nil || consuart->phys->putc == nil) {
  695. _uartputs(s, n);
  696. return;
  697. }
  698. e = s+n;
  699. for(; s<e; s++){
  700. if(*s == '\n')
  701. consuart->phys->putc(consuart, '\r');
  702. consuart->phys->putc(consuart, *s);
  703. }
  704. }