devuart.c 13 KB

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