devcec.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  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. /*
  10. * Coraid ethernet console — serial replacement.
  11. */
  12. #include "u.h"
  13. #include "../port/lib.h"
  14. #include "mem.h"
  15. #include "dat.h"
  16. #include "fns.h"
  17. #include "io.h"
  18. #include "ureg.h"
  19. #include "../port/error.h"
  20. #include "../port/netif.h"
  21. extern Dev cecdevtab;
  22. enum {
  23. Namelen = 128,
  24. Ncbuf = 8192,
  25. Ncmask = Ncbuf-1,
  26. Nconns = 20,
  27. Size = READSTR,
  28. };
  29. enum {
  30. Hdrsz = 18,
  31. Tinita = 0,
  32. Tinitb,
  33. Tinitc,
  34. Tdata,
  35. Tack,
  36. Tdiscover,
  37. Toffer,
  38. Treset,
  39. Tlast,
  40. Cunused = 0,
  41. Cinitb,
  42. Clogin,
  43. Copen,
  44. };
  45. static char *cstate[] = {
  46. "unused",
  47. "initb",
  48. "login",
  49. "open"
  50. };
  51. typedef struct {
  52. Chan *dc;
  53. Chan *cc;
  54. Dev *d;
  55. uint8_t ea[6];
  56. char path[32];
  57. } If;
  58. typedef struct {
  59. uint8_t dst[6];
  60. uint8_t src[6];
  61. uint8_t etype[2];
  62. uint8_t type;
  63. uint8_t conn;
  64. uint8_t seq;
  65. uint8_t len;
  66. uint8_t data[0x100];
  67. } Pkt;
  68. typedef struct {
  69. QLock;
  70. Lock;
  71. unsigned char ea[6]; /* along with cno, the key to the connection */
  72. unsigned char cno; /* connection number on remote host */
  73. unsigned char stalled; /* cectimer needs to kick it */
  74. int state; /* connection state */
  75. int idle; /* idle ticks */
  76. int to; /* ticks to timeout */
  77. int retries; /* remaining retries */
  78. Block *bp; /* unacked message */
  79. If *ifc; /* interface for this connection */
  80. unsigned char sndseq; /* sequence number of last sent message */
  81. unsigned char rcvseq; /* sequence number of last rcv'd message */
  82. char cbuf[Ncbuf]; /* curcular buffer */
  83. int r, w; /* indexes into cbuf */
  84. int pwi; /* index into passwd; */
  85. char passwd[32]; /* password typed by connection */
  86. } Conn;
  87. extern int parseether(uint8_t *, char *);
  88. extern Chan *chandial(char *, char *, char *, Chan **);
  89. enum {
  90. Qdir = 0,
  91. Qstat,
  92. Qctl,
  93. Qdbg,
  94. Qcfg,
  95. CMreset,
  96. CMsetshelf,
  97. CMsetname,
  98. CMtraceon,
  99. CMtraceoff,
  100. CMsetpasswd,
  101. CMcecon,
  102. CMcecoff,
  103. CMwrite,
  104. };
  105. static If ifs[4];
  106. static char name[Namelen];
  107. static int shelf = -1;
  108. static Conn conn[Nconns];
  109. static int tflag;
  110. static char passwd[Namelen];
  111. static int xmit;
  112. static int rsnd;
  113. static Rendez trendez;
  114. static int tcond;
  115. static uint8_t broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  116. static Dirtab cecdir[] = {
  117. ".", { Qdir, 0, QTDIR }, 0, DMDIR | 0555,
  118. "cecstat", { Qstat}, 1, 0444,
  119. "cecctl", { Qctl}, 1, 0777,
  120. // "cecctl", { Qctl}, 1, 0664,
  121. "cecdbg", { Qdbg }, 1, 0444,
  122. "ceccfg", { Qcfg }, 1, 0444,
  123. };
  124. static Cmdtab ceccmd[] = {
  125. CMsetname, "name", 2,
  126. CMtraceon, "traceon", 1,
  127. CMtraceoff, "traceoff", 1,
  128. CMsetpasswd, "password", 2,
  129. CMcecon, "cecon", 2,
  130. CMcecoff, "cecoff", 2,
  131. CMsetshelf, "shelf", 2,
  132. CMwrite, "write", -1,
  133. };
  134. /*
  135. * Avoid outputting debugging to ourselves. Assumes a serial port.
  136. */
  137. static int
  138. cecprint(char *fmt, ...)
  139. {
  140. char buf[PRINTSIZE];
  141. int n;
  142. va_list arg;
  143. va_start(arg, fmt);
  144. n = vseprint(buf, buf+sizeof buf, fmt, arg)-buf;
  145. va_end(arg);
  146. uartputs(buf, n);
  147. return n;
  148. }
  149. static void
  150. getaddr(char *path, uint8_t *ea)
  151. {
  152. Proc *up = externup();
  153. char buf[6*2];
  154. int n;
  155. Chan *c;
  156. snprint(up->genbuf, sizeof up->genbuf, "%s/addr", path);
  157. c = namec(up->genbuf, Aopen, OREAD, 0);
  158. if(waserror()) {
  159. cclose(c);
  160. nexterror();
  161. }
  162. n = c->dev->read(c, buf, sizeof buf, 0);
  163. if(n != sizeof buf)
  164. error("getaddr");
  165. if(parseether(ea, buf) < 0)
  166. error("parseether failure");
  167. poperror();
  168. cclose(c);
  169. }
  170. static char *types[Tlast+1] = {
  171. "Tinita", "Tinitb", "Tinitc", "Tdata", "Tack",
  172. "Tdiscover", "Toffer", "Treset", "*GOK*",
  173. };
  174. static int
  175. cbget(Conn *cp)
  176. {
  177. int c;
  178. if(cp->r == cp->w)
  179. return -1;
  180. c = cp->cbuf[cp->r];
  181. cp->r = cp->r+1 & Ncmask;
  182. return c;
  183. }
  184. static void
  185. cbput(Conn *cp, int c)
  186. {
  187. if(cp->r == (cp->w+1 & Ncmask))
  188. return;
  189. cp->cbuf[cp->w] = c;
  190. cp->w = cp->w+1 & Ncmask;
  191. }
  192. static void
  193. trace(Block *bp)
  194. {
  195. uint type;
  196. Pkt *p;
  197. if(tflag == 0)
  198. return;
  199. p = (Pkt *)bp->rp;
  200. type = p->type;
  201. if(type > Treset)
  202. type = Treset+1;
  203. cecprint("%E > %E) seq %d, type %s, len %d, conn %d\n",
  204. p->src, p->dst, p->seq, types[type], p->len, p->conn);
  205. }
  206. static Block*
  207. sethdr(If *ifc, uint8_t *ea, Pkt **npp, int len)
  208. {
  209. Block *bp;
  210. Pkt *np;
  211. len += Hdrsz;
  212. if(len < 60)
  213. len = 60;
  214. bp = allocb(len);
  215. bp->wp = bp->rp+len;
  216. np = (Pkt *)bp->rp;
  217. memmove(np->dst, ea, 6);
  218. memmove(np->src, ifc->ea, 6);
  219. np->etype[0] = 0xbc;
  220. np->etype[1] = 0xbc;
  221. np->seq = 0;
  222. *npp = np;
  223. return bp;
  224. }
  225. static void
  226. send(Conn *cp, Block *bp)
  227. {
  228. Block *nbp;
  229. if(cp->bp != nil)
  230. panic("cecsend: cp->bp not nil\n");
  231. nbp = allocb(BLEN(bp));
  232. memmove(nbp->wp, bp->rp, BLEN(bp));
  233. nbp->wp += BLEN(bp);
  234. cp->bp = nbp;
  235. trace(bp);
  236. cp->ifc->d->bwrite(cp->ifc->dc, bp, 0);
  237. xmit++;
  238. cp->to = 4;
  239. cp->retries = 3;
  240. xmit++;
  241. }
  242. static void
  243. senddata(Conn *cp, void *data, int len)
  244. {
  245. Block *bp;
  246. Pkt *p;
  247. bp = sethdr(cp->ifc, cp->ea, &p, len);
  248. memmove(p->data, data, len);
  249. p->len = len;
  250. p->seq = ++cp->sndseq;
  251. p->conn = cp->cno;
  252. p->type = Tdata;
  253. send(cp, bp);
  254. }
  255. static void
  256. resend(Conn *cp)
  257. {
  258. Block *nbp;
  259. rsnd++;
  260. nbp = allocb(BLEN(cp->bp));
  261. memmove(nbp->wp, cp->bp->rp, BLEN(cp->bp));
  262. nbp->wp += BLEN(cp->bp);
  263. trace(nbp);
  264. cp->ifc->d->bwrite(cp->ifc->dc, nbp, 0);
  265. cp->to = 4;
  266. }
  267. #if 0
  268. static void
  269. reset(If *ifc, uint8_t conn)
  270. {
  271. Block *bp;
  272. Pkt *p;
  273. bp = sethdr(ifc, ifc->ea, &p, 0);
  274. p->type = Treset;
  275. p->conn = conn;
  276. trace(bp);
  277. ifc->d->bwrite(ifc->dc, bp, 0);
  278. }
  279. #endif
  280. static void
  281. ack(Conn *cp)
  282. {
  283. if(cp->bp)
  284. freeb(cp->bp);
  285. cp->bp = 0;
  286. cp->to = 0;
  287. cp->retries = 0;
  288. }
  289. static void
  290. start(Conn *cp)
  291. {
  292. char buf[250];
  293. int n, c;
  294. if(cp->bp)
  295. return;
  296. ilock(cp);
  297. for(n = 0; n < sizeof buf; n++){
  298. if((c = cbget(cp)) == -1)
  299. break;
  300. buf[n] = c;
  301. }
  302. iunlock(cp);
  303. if(n != 0)
  304. senddata(cp, buf, n);
  305. }
  306. static void
  307. cecputs(char *str, int n)
  308. {
  309. int i, c, wake;
  310. Conn *cp;
  311. wake = 0;
  312. for(cp = conn; cp < conn+Nconns; cp++){
  313. ilock(cp);
  314. if(cp->state == Copen){
  315. for (i = 0; i < n; i++){
  316. c = str[i];
  317. if(c == 0)
  318. continue; /* BOTCH */
  319. if(c == '\n')
  320. cbput(cp, '\r');
  321. cbput(cp, c);
  322. }
  323. cp->stalled = 1;
  324. wake = 1;
  325. }
  326. iunlock(cp);
  327. }
  328. if(wake){
  329. tcond = 1;
  330. wakeup(&trendez);
  331. }
  332. }
  333. static void
  334. conputs(Conn *c, char *s)
  335. {
  336. for(; *s; s++)
  337. cbput(c, *s);
  338. }
  339. static int
  340. icansleep(void* v)
  341. {
  342. return tcond != 0;
  343. }
  344. static void
  345. cectimer(void * v)
  346. {
  347. Conn *cp;
  348. for(;;){
  349. tsleep(&trendez, icansleep, 0, 250);
  350. tcond = 0;
  351. for(cp = conn; cp < conn + Nconns; cp++){
  352. qlock(cp);
  353. if(cp->bp != nil){
  354. if(--cp->to <= 0){
  355. if(--cp->retries <= 0){
  356. freeb(cp->bp);
  357. cp->bp = 0;
  358. // cp->state = Cunused;
  359. }else
  360. resend(cp);
  361. }
  362. }else if(cp->stalled){
  363. cp->stalled = 0;
  364. start(cp);
  365. }
  366. qunlock(cp);
  367. }
  368. }
  369. }
  370. #if 0
  371. static int
  372. cecqlen(void* v)
  373. {
  374. int n;
  375. Conn *c;
  376. n = 0;
  377. for(c = conn; c < conn+Nconns; c++){
  378. if(!canqlock(c))
  379. continue;
  380. if(c->bp)
  381. n += BLEN(c->bp);
  382. if(c->r > c->w)
  383. n += c->r-c->w;
  384. else
  385. n += c->w-c->r;
  386. qunlock(c);
  387. }
  388. if(n){
  389. tcond = 1;
  390. wakeup(&trendez);
  391. }
  392. return n;
  393. }
  394. #endif
  395. static void
  396. discover(If *ifc, Pkt *p)
  397. {
  398. uint8_t *addr;
  399. Block *bp;
  400. Pkt *np;
  401. if(p)
  402. addr = p->src;
  403. else
  404. addr = broadcast;
  405. bp = sethdr(ifc, addr, &np, 0);
  406. np->type = Toffer;
  407. np->len = snprint((char *)np->data, sizeof np->data, "%d %s",
  408. shelf, name);
  409. trace(bp);
  410. ifc->d->bwrite(ifc->dc, bp, 0);
  411. }
  412. static Conn*
  413. connidx(int cno)
  414. {
  415. Conn *c;
  416. for(c = conn; c < conn + Nconns; c++)
  417. if(cno == c->cno){
  418. qlock(c);
  419. return c;
  420. }
  421. return nil;
  422. }
  423. static Conn*
  424. findconn(uint8_t *ea, uint8_t cno)
  425. {
  426. Conn *cp, *ncp;
  427. ncp = nil;
  428. for(cp = conn; cp < conn + Nconns; cp++){
  429. if(ncp == nil && cp->state == Cunused)
  430. ncp = cp;
  431. if(memcmp(ea, cp->ea, 6) == 0 && cno == cp->cno){
  432. qlock(cp);
  433. return cp;
  434. }
  435. }
  436. if(ncp != nil)
  437. qlock(ncp);
  438. return ncp;
  439. }
  440. static void
  441. checkpw(Conn *cp, char *str, int len)
  442. {
  443. int i, c;
  444. if(passwd[0] == 0)
  445. return;
  446. for(i = 0; i < len; i++){
  447. c = str[i];
  448. if(c != '\n' && c != '\r'){
  449. if(cp->pwi < (sizeof cp->passwd)-1)
  450. cp->passwd[cp->pwi++] = c;
  451. cbput(cp, '#');
  452. cecprint("%c", c);
  453. continue;
  454. }
  455. /* is newline; check password */
  456. cp->passwd[cp->pwi] = 0;
  457. if(strcmp(cp->passwd, passwd) == 0){
  458. cp->state = Copen;
  459. cp->pwi = 0;
  460. print("\r\n%E logged in\r\n", cp->ea);
  461. }else{
  462. conputs(cp, "\r\nBad password\r\npassword: ");
  463. cp->pwi = 0;
  464. }
  465. }
  466. start(cp);
  467. }
  468. static void
  469. incoming(Conn *cp, If *ifc, Pkt *p)
  470. {
  471. int i;
  472. Block *bp;
  473. Pkt *np;
  474. /* ack it no matter what its sequence number */
  475. bp = sethdr(ifc, p->src, &np, 0);
  476. np->type = Tack;
  477. np->seq = p->seq;
  478. np->conn = cp->cno;
  479. np->len = 0;
  480. trace(bp);
  481. ifc->d->bwrite(ifc->dc, bp, 0);
  482. if(cp->state == Cunused){
  483. /* connection */
  484. discover(ifc, p);
  485. return;
  486. }
  487. if(p->seq == cp->rcvseq)
  488. return;
  489. cp->rcvseq = p->seq;
  490. if(cp->state == Copen){
  491. for (i = 0; i < p->len; i++)
  492. kbdcr2nl(nil, (char)p->data[i]);
  493. }else if(cp->state == Clogin)
  494. checkpw(cp, (char *)p->data, p->len);
  495. }
  496. static void
  497. inita(Conn *ncp, If *ifc, Pkt *p)
  498. {
  499. Block *bp;
  500. Pkt *np;
  501. ncp->ifc = ifc;
  502. ncp->state = Cinitb;
  503. memmove(ncp->ea, p->src, 6);
  504. ncp->cno = p->conn;
  505. bp = sethdr(ifc, p->src, &np, 0);
  506. np->type = Tinitb;
  507. np->conn = ncp->cno;
  508. np->len = 0;
  509. send(ncp, bp);
  510. }
  511. static void
  512. cecrdr(void *vp)
  513. {
  514. Proc *up = externup();
  515. Block *bp;
  516. Conn *cp;
  517. If *ifc;
  518. Pkt *p;
  519. ifc = vp;
  520. if(waserror())
  521. goto exit;
  522. discover(ifc, 0);
  523. for(;;){
  524. bp = ifc->d->bread(ifc->dc, 1514, 0); // do we care about making the MTU non magic?
  525. if(bp == nil)
  526. nexterror();
  527. p = (Pkt *)bp->rp;
  528. if(p->etype[0] != 0xbc || p->etype[1] != 0xbc){
  529. freeb(bp);
  530. continue;
  531. }
  532. trace(bp);
  533. cp = findconn(p->src, p->conn);
  534. if(cp == nil){
  535. cecprint("cec: out of connection structures\n");
  536. freeb(bp);
  537. continue;
  538. }
  539. if (waserror()){
  540. freeb(bp);
  541. qunlock(cp);
  542. continue;
  543. }
  544. switch(p->type){
  545. case Tinita:
  546. if(cp->bp){
  547. cecprint("cec: reset with bp!? ask quanstro\n");
  548. freeb(cp->bp);
  549. cp->bp = 0;
  550. }
  551. inita(cp, ifc, p);
  552. break;
  553. case Tinitb:
  554. cecprint("cec: unexpected initb\n");
  555. break;
  556. case Tinitc:
  557. if(cp->state == Cinitb){
  558. ack(cp);
  559. if(cp->passwd[0]){
  560. cp->state = Clogin;
  561. conputs(cp, "password: ");
  562. start(cp);
  563. }else
  564. cp->state = Copen;
  565. }
  566. break;
  567. case Tdata:
  568. incoming(cp, ifc, p);
  569. break;
  570. case Tack:
  571. if(cp->state == Clogin || cp->state == Copen){
  572. ack(cp);
  573. start(cp);
  574. }
  575. break;
  576. case Tdiscover:
  577. discover(ifc, p);
  578. break;
  579. case Toffer:
  580. // cecprint("cec: unexpected offer\n"); from ourselves.
  581. break;
  582. case Treset:
  583. if(cp->bp)
  584. freeb(cp->bp);
  585. cp->bp = 0;
  586. cp->state = Cunused;
  587. break;
  588. default:
  589. cecprint("bad cec type: %d\n", p->type);
  590. break;
  591. }
  592. nexterror();
  593. }
  594. exit:
  595. for(cp = conn; cp < conn+nelem(conn); cp++)
  596. if(cp->ifc == ifc){
  597. if(cp->bp)
  598. freeb(cp->bp);
  599. memset(cp, 0, sizeof *cp);
  600. break;
  601. }
  602. memset(ifc, 0, sizeof *ifc);
  603. pexit("cec exiting", 1);
  604. }
  605. static Chan *
  606. cecattach(char *spec)
  607. {
  608. Chan *c;
  609. static QLock q;
  610. static int inited;
  611. qlock(&q);
  612. if(inited == 0){
  613. kproc("cectimer", cectimer, nil);
  614. inited++;
  615. }
  616. qunlock(&q);
  617. c = devattach(L'©', spec);
  618. c->qid.path = Qdir;
  619. return c;
  620. }
  621. static Walkqid*
  622. cecwalk(Chan *c, Chan *nc, char **name, int nname)
  623. {
  624. return devwalk(c, nc, name, nname, cecdir, nelem(cecdir), devgen);
  625. }
  626. static int32_t
  627. cecstat(Chan *c, uint8_t *dp, int32_t n)
  628. {
  629. return devstat(c, dp, n, cecdir, nelem(cecdir), devgen);
  630. }
  631. static Chan*
  632. cecopen(Chan *c, int omode)
  633. {
  634. return devopen(c, omode, cecdir, nelem(cecdir), devgen);
  635. }
  636. static void
  637. cecclose(Chan* c)
  638. {
  639. }
  640. static int32_t
  641. cecread(Chan *c, void *a, int32_t n, int64_t offset)
  642. {
  643. char *p;
  644. int j;
  645. Conn *cp;
  646. If *ifc;
  647. switch((int)c->qid.path){
  648. case Qdir:
  649. return devdirread(c, a, n, cecdir, nelem(cecdir), devgen);
  650. case Qstat:
  651. p = smalloc(Size);
  652. j = 0;
  653. for(cp = conn; cp < conn+Nconns; cp++)
  654. if(cp->state != Cunused)
  655. j += snprint(p+j, Size-j,
  656. "%E %3d %-6s %12d %d %d %.8lux\n",
  657. cp->ea, cp->cno, cstate[cp->state], cp->idle,
  658. cp->to, cp->retries, (uintptr_t)cp->bp);
  659. n = readstr(offset, a, n, p);
  660. free(p);
  661. return n;
  662. case Qdbg:
  663. cecprint("xmit %d, rsnd %d\n", xmit, rsnd);
  664. return 0;
  665. case Qcfg:
  666. case Qctl:
  667. p = smalloc(Size);
  668. j = 0;
  669. for(ifc = ifs; ifc < ifs+nelem(ifs); ifc++)
  670. if(ifc->d)
  671. j += snprint(p+j, Size-j, "%s\n", ifc->path);
  672. n = readstr(offset, a, n, p);
  673. free(p);
  674. return n;
  675. }
  676. error(Egreg);
  677. return 0;
  678. }
  679. /*
  680. static void
  681. cecfixup(void)
  682. {
  683. char *p;
  684. int len;
  685. p = malloc(128*1024);
  686. snprint(p, 6, "write ");
  687. len = readfile("/dev/kmesg", p+6, 128*1024-6);
  688. writefile("#©/cecctl", p, len+6);
  689. free(p);
  690. }
  691. */
  692. static void
  693. cecon(char *path)
  694. {
  695. Proc *up = externup();
  696. char buf[64];
  697. uint8_t ea[6];
  698. Chan *dc, *cc;
  699. If *ifc, *nifc;
  700. nifc = nil;
  701. for(ifc = ifs; ifc < ifs+nelem(ifs); ifc++)
  702. if(ifc->d == nil)
  703. nifc = ifc;
  704. else if(strcmp(ifc->path, path) == 0)
  705. return;
  706. ifc = nifc;
  707. if(ifc == nil)
  708. error("out of interface structures");
  709. getaddr(path, ea);
  710. snprint(buf, sizeof buf, "%s!0xbcbc", path);
  711. dc = chandial(buf, nil, nil, &cc);
  712. if(dc == nil || cc == nil){
  713. if (cc)
  714. cclose(cc);
  715. if (dc)
  716. cclose(dc);
  717. snprint(up->genbuf, sizeof up->genbuf, "can't dial %s", buf);
  718. error(up->genbuf);
  719. }
  720. ifc->d = cc->dev;
  721. ifc->cc = cc;
  722. ifc->dc = dc;
  723. strncpy(ifc->path, path, sizeof ifc->path);
  724. memmove(ifc->ea, ea, 6);
  725. snprint(up->genbuf, sizeof up->genbuf, "cec:%s", path);
  726. kproc(up->genbuf, cecrdr, ifc);
  727. }
  728. static void
  729. cecoff(char *path)
  730. {
  731. int all, n;
  732. If *ifc, *e;
  733. all = strcmp(path, "*") == 0;
  734. n = 0;
  735. ifc = ifs;
  736. e = ifc+nelem(ifs);
  737. for(; ifc < e; ifc++)
  738. if(ifc->d && (all || strcmp(path, ifc->path) == 0)){
  739. cclose(ifc->cc);
  740. cclose(ifc->dc);
  741. memset(ifc, 0, sizeof *ifc);
  742. n++;
  743. }
  744. if(all + n == 0)
  745. error("cec not found");
  746. }
  747. static void
  748. rst(Conn *c)
  749. {
  750. if(c == nil)
  751. error("no such index");
  752. if(c->bp)
  753. freeb(c->bp);
  754. c->bp = 0;
  755. c->state = Cunused;
  756. qunlock(c);
  757. }
  758. static int32_t
  759. cecwrite(Chan *c, void *a, int32_t n, int64_t mm)
  760. {
  761. Proc *up = externup();
  762. Cmdbuf *cb;
  763. Cmdtab *cp;
  764. if(c->qid.path == Qctl){
  765. cb = parsecmd(a, n);
  766. if(waserror()){
  767. free(cb);
  768. nexterror();
  769. }
  770. cp = lookupcmd(cb, ceccmd, nelem(ceccmd));
  771. switch(cp->index){
  772. case CMsetname:
  773. strecpy(name, name+sizeof name-1, cb->f[1]);
  774. break;
  775. case CMtraceon:
  776. tflag = 1;
  777. break;
  778. case CMtraceoff:
  779. tflag = 0;
  780. break;
  781. case CMsetpasswd:
  782. strcpy(passwd, cb->f[1]);
  783. break;
  784. case CMcecon:
  785. cecon(cb->f[1]);
  786. break;
  787. case CMcecoff:
  788. cecoff(cb->f[1]);
  789. break;
  790. case CMsetshelf:
  791. shelf = atoi(cb->f[1]);
  792. break;
  793. case CMwrite:
  794. cecputs((char*)a+6,n-6);
  795. break;
  796. case CMreset:
  797. rst(connidx(atoi(cb->f[1])));
  798. break;
  799. default:
  800. cmderror(cb, "bad control message");
  801. break;
  802. }
  803. free(cb);
  804. poperror();
  805. return n;
  806. }
  807. error(Egreg);
  808. return 0;
  809. }
  810. static void
  811. cecinit(void)
  812. {
  813. addconsdev(nil, cecputs, -1, 0);
  814. }
  815. Dev cecdevtab = {
  816. .dc = L'©',
  817. .name = "cec",
  818. .reset = devreset,
  819. .init = cecinit,
  820. .shutdown = devshutdown,
  821. .attach = cecattach,
  822. .walk = cecwalk,
  823. .stat = cecstat,
  824. .open = cecopen,
  825. .create = devcreate,
  826. .close = cecclose,
  827. .read = cecread,
  828. .bread = devbread,
  829. .write = cecwrite,
  830. .bwrite = devbwrite,
  831. .remove = devremove,
  832. .wstat = devwstat,
  833. .power = devpower,
  834. .config = devconfig,
  835. };