1 /* 2 * This part takes care of locking except for initialization and 3 * other threads created by the hw dep. drivers. 4 */ 5 6 #include <u.h> 7 #include <libc.h> 8 #include <ctype.h> 9 #include <thread.h> 10 #include "usb.h" 11 #include "usbfs.h" 12 #include "serial.h" 13 #include "prolific.h" 14 #include "ucons.h" 15 #include "ftdi.h" 16 #include "silabs.h" 17 18 int serialdebug; 19 20 enum { 21 /* Qids. Maintain order (relative to dirtabs structs) */ 22 Qroot = 0, 23 Qctl, 24 Qdata, 25 Qmax, 26 }; 27 28 typedef struct Dirtab Dirtab; 29 struct Dirtab { 30 char *name; 31 int mode; 32 }; 33 34 static Dirtab dirtab[] = { 35 [Qroot] "/", DMDIR|0555, 36 [Qdata] "%s", 0660, 37 [Qctl] "%sctl", 0664, 38 }; 39 40 static int sdebug; 41 42 static void 43 serialfatal(Serial *ser) 44 { 45 Serialport *p; 46 int i; 47 48 dsprint(2, "serial: fatal error, detaching\n"); 49 devctl(ser->dev, "detach"); 50 51 for(i = 0; i < ser->nifcs; i++){ 52 p = &ser->p[i]; 53 usbfsdel(&p->fs); 54 if(p->w4data != nil) 55 chanclose(p->w4data); 56 if(p->gotdata != nil) 57 chanclose(p->gotdata); 58 if(p->readc) 59 chanclose(p->readc); 60 } 61 } 62 63 /* I sleep with the lock... only way to drain in general */ 64 static void 65 serialdrain(Serialport *p) 66 { 67 Serial *ser; 68 uint baud, pipesize; 69 70 ser = p->s; 71 baud = p->baud; 72 73 if(p->baud == ~0) 74 return; 75 if(ser->maxwtrans < 256) 76 pipesize = 256; 77 else 78 pipesize = ser->maxwtrans; 79 /* wait for the at least 256-byte pipe to clear */ 80 sleep(10 + pipesize/((1 + baud)*1000)); 81 if(ser->clearpipes != nil) 82 ser->clearpipes(p); 83 } 84 85 int 86 serialreset(Serial *ser) 87 { 88 Serialport *p; 89 int i, res; 90 91 res = 0; 92 /* cmd for reset */ 93 for(i = 0; i < ser->nifcs; i++){ 94 p = &ser->p[i]; 95 serialdrain(p); 96 } 97 if(ser->reset != nil) 98 res = ser->reset(ser, nil); 99 return res; 100 } 101 102 /* call this if something goes wrong, must be qlocked */ 103 int 104 serialrecover(Serial *ser, Serialport *p, Dev *ep, char *err) 105 { 106 if(p != nil) 107 dprint(2, "serial[%d], %s: %s, level %d\n", p->interfc, 108 p->name, err, ser->recover); 109 else 110 dprint(2, "serial[%s], global error, level %d\n", 111 ser->p[0].name, ser->recover); 112 ser->recover++; 113 if(strstr(err, "detached") != nil) 114 return -1; 115 if(ser->recover < 3){ 116 if(p != nil){ 117 if(ep != nil){ 118 if(ep == p->epintr) 119 unstall(ser->dev, p->epintr, Ein); 120 if(ep == p->epin) 121 unstall(ser->dev, p->epin, Ein); 122 if(ep == p->epout) 123 unstall(ser->dev, p->epout, Eout); 124 return 0; 125 } 126 127 if(p->epintr != nil) 128 unstall(ser->dev, p->epintr, Ein); 129 if(p->epin != nil) 130 unstall(ser->dev, p->epin, Ein); 131 if(p->epout != nil) 132 unstall(ser->dev, p->epout, Eout); 133 } 134 return 0; 135 } 136 if(ser->recover > 4 && ser->recover < 8) 137 serialfatal(ser); 138 if(ser->recover > 8){ 139 ser->reset(ser, p); 140 return 0; 141 } 142 if(serialreset(ser) < 0) 143 return -1; 144 return 0; 145 } 146 147 static int 148 serialctl(Serialport *p, char *cmd) 149 { 150 Serial *ser; 151 int c, i, n, nf, nop, nw, par, drain, set, lines; 152 char *f[16]; 153 uchar x; 154 155 ser = p->s; 156 drain = set = lines = 0; 157 nf = tokenize(cmd, f, nelem(f)); 158 for(i = 0; i < nf; i++){ 159 if(strncmp(f[i], "break", 5) == 0){ 160 if(ser->setbreak != nil) 161 ser->setbreak(p, 1); 162 continue; 163 } 164 165 nop = 0; 166 n = atoi(f[i]+1); 167 c = *f[i]; 168 if (isascii(c) && isupper(c)) 169 c = tolower(c); 170 switch(c){ 171 case 'b': 172 drain++; 173 p->baud = n; 174 set++; 175 break; 176 case 'c': 177 p->dcd = n; 178 // lines++; 179 ++nop; 180 break; 181 case 'd': 182 p->dtr = n; 183 lines++; 184 break; 185 case 'e': 186 p->dsr = n; 187 // lines++; 188 ++nop; 189 break; 190 case 'f': /* flush the pipes */ 191 drain++; 192 break; 193 case 'h': /* hangup?? */ 194 p->rts = p->dtr = 0; 195 lines++; 196 fprint(2, "serial: %c, unsure ctl\n", c); 197 break; 198 case 'i': 199 ++nop; 200 break; 201 case 'k': 202 drain++; 203 ser->setbreak(p, 1); 204 sleep(n); 205 ser->setbreak(p, 0); 206 break; 207 case 'l': 208 drain++; 209 p->bits = n; 210 set++; 211 break; 212 case 'm': 213 drain++; 214 if(ser->modemctl != nil) 215 ser->modemctl(p, n); 216 if(n == 0) 217 p->cts = 0; 218 break; 219 case 'n': 220 p->blocked = n; 221 ++nop; 222 break; 223 case 'p': /* extended... */ 224 if(strlen(f[i]) != 2) 225 return -1; 226 drain++; 227 par = f[i][1]; 228 if(par == 'n') 229 p->parity = 0; 230 else if(par == 'o') 231 p->parity = 1; 232 else if(par == 'e') 233 p->parity = 2; 234 else if(par == 'm') /* mark parity */ 235 p->parity = 3; 236 else if(par == 's') /* space parity */ 237 p->parity = 4; 238 else 239 return -1; 240 set++; 241 break; 242 case 'q': 243 // drain++; 244 p->limit = n; 245 ++nop; 246 break; 247 case 'r': 248 drain++; 249 p->rts = n; 250 lines++; 251 break; 252 case 's': 253 drain++; 254 p->stop = n; 255 set++; 256 break; 257 case 'w': 258 /* ?? how do I put this */ 259 p->timer = n * 100000LL; 260 ++nop; 261 break; 262 case 'x': 263 if(n == 0) 264 x = CTLS; 265 else 266 x = CTLQ; 267 if(ser->wait4write != nil) 268 nw = ser->wait4write(p, &x, 1); 269 else 270 nw = write(p->epout->dfd, &x, 1); 271 if(nw != 1){ 272 serialrecover(ser, p, p->epout, ""); 273 return -1; 274 } 275 break; 276 } 277 /* 278 * don't print. the condition is harmless and the print 279 * splatters all over the display. 280 */ 281 USED(nop); 282 if (0 && nop) 283 fprint(2, "serial: %c, unsupported nop ctl\n", c); 284 } 285 if(drain) 286 serialdrain(p); 287 if(lines && !set){ 288 if(ser->sendlines != nil && ser->sendlines(p) < 0) 289 return -1; 290 } else if(set){ 291 if(ser->setparam != nil && ser->setparam(p) < 0) 292 return -1; 293 } 294 ser->recover = 0; 295 return 0; 296 } 297 298 char *pformat = "noems"; 299 300 char * 301 serdumpst(Serialport *p, char *buf, int bufsz) 302 { 303 char *e, *s; 304 Serial *ser; 305 306 ser = p->s; 307 308 e = buf + bufsz; 309 s = seprint(buf, e, "b%d ", p->baud); 310 s = seprint(s, e, "c%d ", p->dcd); /* unimplemented */ 311 s = seprint(s, e, "d%d ", p->dtr); 312 s = seprint(s, e, "e%d ", p->dsr); /* unimplemented */ 313 s = seprint(s, e, "l%d ", p->bits); 314 s = seprint(s, e, "m%d ", p->mctl); 315 if(p->parity >= 0 || p->parity < strlen(pformat)) 316 s = seprint(s, e, "p%c ", pformat[p->parity]); 317 else 318 s = seprint(s, e, "p%c ", '?'); 319 s = seprint(s, e, "r%d ", p->rts); 320 s = seprint(s, e, "s%d ", p->stop); 321 s = seprint(s, e, "i%d ", p->fifo); 322 s = seprint(s, e, "\ndev(%d) ", 0); 323 s = seprint(s, e, "type(%d) ", ser->type); 324 s = seprint(s, e, "framing(%d) ", p->nframeerr); 325 s = seprint(s, e, "overruns(%d) ", p->novererr); 326 s = seprint(s, e, "berr(%d) ", p->nbreakerr); 327 s = seprint(s, e, " serr(%d)\n", p->nparityerr); 328 return s; 329 } 330 331 static int 332 serinit(Serialport *p) 333 { 334 int res; 335 res = 0; 336 Serial *ser; 337 338 ser = p->s; 339 340 if(ser->init != nil) 341 res = ser->init(p); 342 if(ser->getparam != nil) 343 ser->getparam(p); 344 p->nframeerr = p->nparityerr = p->nbreakerr = p->novererr = 0; 345 346 return res; 347 } 348 349 static int 350 dwalk(Usbfs *fs, Fid *fid, char *name) 351 { 352 int i; 353 char *dname; 354 Qid qid; 355 Serialport *p; 356 357 qid = fid->qid; 358 if((qid.type & QTDIR) == 0){ 359 werrstr("walk in non-directory"); 360 return -1; 361 } 362 363 if(strcmp(name, "..") == 0){ 364 /* must be /eiaU%d; i.e. our root dir. */ 365 fid->qid.path = Qroot | fs->qid; 366 fid->qid.vers = 0; 367 fid->qid.type = QTDIR; 368 return 0; 369 } 370 371 p = fs->aux; 372 for(i = 1; i < nelem(dirtab); i++){ 373 dname = smprint(dirtab[i].name, p->name); 374 if(strcmp(name, dname) == 0){ 375 qid.path = i | fs->qid; 376 qid.vers = 0; 377 qid.type = dirtab[i].mode >> 24; 378 fid->qid = qid; 379 free(dname); 380 return 0; 381 } else 382 free(dname); 383 } 384 werrstr(Enotfound); 385 return -1; 386 } 387 388 static void 389 dostat(Usbfs *fs, int path, Dir *d) 390 { 391 Dirtab *t; 392 Serialport *p; 393 394 t = &dirtab[path]; 395 d->qid.path = path; 396 d->qid.type = t->mode >> 24; 397 d->mode = t->mode; 398 p = fs->aux; 399 400 if(strcmp(t->name, "/") == 0) 401 d->name = t->name; 402 else 403 snprint(d->name, Namesz, t->name, p->fs.name); 404 d->length = 0; 405 } 406 407 static int 408 dstat(Usbfs *fs, Qid qid, Dir *d) 409 { 410 int path; 411 412 path = qid.path & ~fs->qid; 413 dostat(fs, path, d); 414 d->qid.path |= fs->qid; 415 return 0; 416 } 417 418 static int 419 dopen(Usbfs *fs, Fid *fid, int) 420 { 421 ulong path; 422 Serialport *p; 423 424 path = fid->qid.path & ~fs->qid; 425 p = fs->aux; 426 switch(path){ /* BUG: unneeded? */ 427 case Qdata: 428 dsprint(2, "serial, opened data\n"); 429 break; 430 case Qctl: 431 dsprint(2, "serial, opened ctl\n"); 432 if(p->isjtag) 433 return 0; 434 serialctl(p, "l8 i1"); /* default line parameters */ 435 break; 436 } 437 return 0; 438 } 439 440 441 static void 442 filldir(Usbfs *fs, Dir *d, Dirtab *tab, int i, void *v) 443 { 444 Serialport *p; 445 446 p = v; 447 d->qid.path = i | fs->qid; 448 d->mode = tab->mode; 449 if((d->mode & DMDIR) != 0) 450 d->qid.type = QTDIR; 451 else 452 d->qid.type = QTFILE; 453 sprint(d->name, tab->name, p->name); /* hope it fits */ 454 } 455 456 static int 457 dirgen(Usbfs *fs, Qid, int i, Dir *d, void *p) 458 { 459 i++; /* skip root */ 460 if(i >= nelem(dirtab)) 461 return -1; 462 filldir(fs, d, &dirtab[i], i, p); 463 return 0; 464 } 465 466 enum { 467 Serbufsize = 256, 468 }; 469 470 static long 471 dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset) 472 { 473 int dfd; 474 long rcount; 475 ulong path; 476 char *e, *buf, *err; /* change */ 477 Qid q; 478 Serialport *p; 479 Serial *ser; 480 static int errrun, good; 481 482 q = fid->qid; 483 path = fid->qid.path & ~fs->qid; 484 p = fs->aux; 485 ser = p->s; 486 487 buf = emallocz(Serbufsize, 1); 488 err = emallocz(Serbufsize, 1); 489 qlock(ser); 490 switch(path){ 491 case Qroot: 492 count = usbdirread(fs, q, data, count, offset, dirgen, p); 493 break; 494 case Qdata: 495 if(count > ser->maxread) 496 count = ser->maxread; 497 498 dsprint(2, "serial: reading from data\n"); 499 do { 500 err[0] = 0; 501 dfd = p->epin->dfd; 502 if(usbdebug >= 3) 503 dsprint(2, "serial: reading: %ld\n", count); 504 505 assert(count > 0); 506 if(ser->wait4data != nil) 507 rcount = ser->wait4data(p, data, count); 508 else{ 509 qunlock(ser); 510 rcount = read(dfd, data, count); 511 qlock(ser); 512 } 513 /* 514 * if we encounter a long run of continuous read 515 * errors, do something drastic so that our caller 516 * doesn't just spin its wheels forever. 517 */ 518 if(rcount < 0) { 519 snprint(err, Serbufsize, "%r"); 520 ++errrun; 521 sleep(20); 522 if (good > 0 && errrun > 10000) { 523 /* the line has been dropped; give up */ 524 qunlock(ser); 525 fprint(2, "%s: line %s is gone: %r\n", 526 argv0, p->fs.name); 527 threadexitsall("serial line gone"); 528 } 529 } else { 530 errrun = 0; 531 good++; 532 } 533 if(usbdebug >= 3) 534 dsprint(2, "serial: read: %s %ld\n", err, rcount); 535 } while(rcount < 0 && strstr(err, "timed out") != nil); 536 537 dsprint(2, "serial: read from bulk %ld, %10.10s\n", rcount, err); 538 if(rcount < 0){ 539 dsprint(2, "serial: need to recover, data read %ld %r\n", 540 count); 541 serialrecover(ser, p, p->epin, err); 542 } 543 dsprint(2, "serial: read from bulk %ld\n", rcount); 544 count = rcount; 545 break; 546 case Qctl: 547 if(offset != 0 || p->isjtag) 548 count = 0; 549 else { 550 e = serdumpst(p, buf, Serbufsize); 551 count = usbreadbuf(data, count, 0, buf, e - buf); 552 } 553 break; 554 } 555 if(count >= 0) 556 ser->recover = 0; 557 qunlock(ser); 558 free(err); 559 free(buf); 560 return count; 561 } 562 563 static long 564 altwrite(Serialport *p, uchar *buf, long count) 565 { 566 int nw, dfd; 567 char err[128]; 568 Serial *ser; 569 570 ser = p->s; 571 do{ 572 dsprint(2, "serial: write to bulk %ld\n", count); 573 574 if(ser->wait4write != nil) 575 /* unlocked inside later */ 576 nw = ser->wait4write(p, buf, count); 577 else{ 578 dfd = p->epout->dfd; 579 qunlock(ser); 580 nw = write(dfd, buf, count); 581 qlock(ser); 582 } 583 rerrstr(err, sizeof err); 584 dsprint(2, "serial: written %s %d\n", err, nw); 585 } while(nw < 0 && strstr(err, "timed out") != nil); 586 587 if(nw != count){ 588 dsprint(2, "serial: need to recover, status in write %d %r\n", 589 nw); 590 snprint(err, sizeof err, "%r"); 591 serialrecover(p->s, p, p->epout, err); 592 } 593 return nw; 594 } 595 596 static long 597 dwrite(Usbfs *fs, Fid *fid, void *buf, long count, vlong) 598 { 599 ulong path; 600 char *cmd; 601 Serialport *p; 602 Serial *ser; 603 604 p = fs->aux; 605 ser = p->s; 606 path = fid->qid.path & ~fs->qid; 607 608 qlock(ser); 609 switch(path){ 610 case Qdata: 611 count = altwrite(p, (uchar *)buf, count); 612 break; 613 case Qctl: 614 if(p->isjtag) 615 break; 616 cmd = emallocz(count+1, 1); 617 memmove(cmd, buf, count); 618 cmd[count] = 0; 619 if(serialctl(p, cmd) < 0){ 620 qunlock(ser); 621 werrstr(Ebadctl); 622 free(cmd); 623 return -1; 624 } 625 free(cmd); 626 break; 627 default: 628 qunlock(ser); 629 werrstr(Eperm); 630 return -1; 631 } 632 if(count >= 0) 633 ser->recover = 0; 634 else 635 serialrecover(ser, p, p->epout, "writing"); 636 qunlock(ser); 637 return count; 638 } 639 640 static int 641 openeps(Serialport *p, int epin, int epout, int epintr) 642 { 643 Serial *ser; 644 645 ser = p->s; 646 p->epin = openep(ser->dev, epin); 647 if(p->epin == nil){ 648 fprint(2, "serial: openep %d: %r\n", epin); 649 return -1; 650 } 651 if(epout == epin){ 652 incref(p->epin); 653 p->epout = p->epin; 654 }else 655 p->epout = openep(ser->dev, epout); 656 if(p->epout == nil){ 657 fprint(2, "serial: openep %d: %r\n", epout); 658 closedev(p->epin); 659 return -1; 660 } 661 662 if(!p->isjtag){ 663 devctl(p->epin, "timeout 1000"); 664 devctl(p->epout, "timeout 1000"); 665 } 666 667 if(ser->hasepintr){ 668 p->epintr = openep(ser->dev, epintr); 669 if(p->epintr == nil){ 670 fprint(2, "serial: openep %d: %r\n", epintr); 671 closedev(p->epin); 672 closedev(p->epout); 673 return -1; 674 } 675 opendevdata(p->epintr, OREAD); 676 devctl(p->epintr, "timeout 1000"); 677 } 678 679 if(ser->seteps!= nil) 680 ser->seteps(p); 681 if(p->epin == p->epout) 682 opendevdata(p->epin, ORDWR); 683 else{ 684 opendevdata(p->epin, OREAD); 685 opendevdata(p->epout, OWRITE); 686 } 687 if(p->epin->dfd < 0 ||p->epout->dfd < 0 || 688 (ser->hasepintr && p->epintr->dfd < 0)){ 689 fprint(2, "serial: open i/o ep data: %r\n"); 690 closedev(p->epin); 691 closedev(p->epout); 692 if(ser->hasepintr) 693 closedev(p->epintr); 694 return -1; 695 } 696 return 0; 697 } 698 699 static int 700 findendpoints(Serial *ser, int ifc) 701 { 702 int i, epin, epout, epintr; 703 Ep *ep, **eps; 704 705 epintr = epin = epout = -1; 706 707 /* 708 * interfc 0 means start from the start which is equiv to 709 * iterate through endpoints probably, could be done better 710 */ 711 eps = ser->dev->usb->conf[0]->iface[ifc]->ep; 712 713 for(i = 0; i < Niface; i++){ 714 if((ep = eps[i]) == nil) 715 continue; 716 if(ser->hasepintr && ep->type == Eintr && 717 ep->dir == Ein && epintr == -1) 718 epintr = ep->id; 719 if(ep->type == Ebulk){ 720 if((ep->dir == Ein || ep->dir == Eboth) && epin == -1) 721 epin = ep->id; 722 if((ep->dir == Eout || ep->dir == Eboth) && epout == -1) 723 epout = ep->id; 724 } 725 } 726 dprint(2, "serial[%d]: ep ids: in %d out %d intr %d\n", ifc, epin, epout, epintr); 727 if(epin == -1 || epout == -1 || (ser->hasepintr && epintr == -1)) 728 return -1; 729 730 if(openeps(&ser->p[ifc], epin, epout, epintr) < 0) 731 return -1; 732 733 dprint(2, "serial: ep in %s out %s\n", ser->p[ifc].epin->dir, ser->p[ifc].epout->dir); 734 if(ser->hasepintr) 735 dprint(2, "serial: ep intr %s\n", ser->p[ifc].epintr->dir); 736 737 if(usbdebug > 1 || serialdebug > 2){ 738 devctl(ser->p[ifc].epin, "debug 1"); 739 devctl(ser->p[ifc].epout, "debug 1"); 740 if(ser->hasepintr) 741 devctl(ser->p[ifc].epintr, "debug 1"); 742 devctl(ser->dev, "debug 1"); 743 } 744 return 0; 745 } 746 747 /* keep in sync with main.c */ 748 static int 749 usage(void) 750 { 751 werrstr("usage: usb/serial [-dD] [-m mtpt] [-s srv]"); 752 return -1; 753 } 754 755 static void 756 serdevfree(void *a) 757 { 758 Serial *ser = a; 759 Serialport *p; 760 int i; 761 762 if(ser == nil) 763 return; 764 765 for(i = 0; i < ser->nifcs; i++){ 766 p = &ser->p[i]; 767 768 if(ser->hasepintr) 769 closedev(p->epintr); 770 closedev(p->epin); 771 closedev(p->epout); 772 p->epintr = p->epin = p->epout = nil; 773 if(p->w4data != nil) 774 chanfree(p->w4data); 775 if(p->gotdata != nil) 776 chanfree(p->gotdata); 777 if(p->readc) 778 chanfree(p->readc); 779 780 } 781 free(ser); 782 } 783 784 static Usbfs serialfs = { 785 .walk = dwalk, 786 .open = dopen, 787 .read = dread, 788 .write= dwrite, 789 .stat = dstat, 790 }; 791 792 static void 793 serialfsend(Usbfs *fs) 794 { 795 Serialport *p; 796 797 p = fs->aux; 798 799 if(p->w4data != nil) 800 chanclose(p->w4data); 801 if(p->gotdata != nil) 802 chanclose(p->gotdata); 803 if(p->readc) 804 chanclose(p->readc); 805 } 806 807 int 808 serialmain(Dev *dev, int argc, char* argv[]) 809 { 810 Serial *ser; 811 Serialport *p; 812 char buf[50]; 813 int i, devid; 814 815 devid = dev->id; 816 ARGBEGIN{ 817 case 'd': 818 serialdebug++; 819 break; 820 case 'N': 821 devid = atoi(EARGF(usage())); 822 break; 823 default: 824 return usage(); 825 }ARGEND 826 if(argc != 0) 827 return usage(); 828 829 ser = dev->aux = emallocz(sizeof(Serial), 1); 830 ser->maxrtrans = ser->maxwtrans = sizeof ser->p[0].data; 831 ser->maxread = ser->maxwrite = sizeof ser->p[0].data; 832 ser->dev = dev; 833 dev->free = serdevfree; 834 ser->jtag = -1; 835 ser->nifcs = 1; 836 837 snprint(buf, sizeof buf, "vid %#06x did %#06x", 838 dev->usb->vid, dev->usb->did); 839 if(plmatch(buf) == 0){ 840 ser->hasepintr = 1; 841 ser->Serialops = plops; 842 } else if(uconsmatch(buf) == 0) 843 ser->Serialops = uconsops; 844 else if(ftmatch(ser, buf) == 0) 845 ser->Serialops = ftops; 846 else if(slmatch(buf) == 0) 847 ser->Serialops = slops; 848 else { 849 werrstr("serial: no serial devices found"); 850 return -1; 851 } 852 for(i = 0; i < ser->nifcs; i++){ 853 p = &ser->p[i]; 854 p->interfc = i; 855 p->s = ser; 856 p->fs = serialfs; 857 if(i == ser->jtag){ 858 p->isjtag++; 859 } 860 if(findendpoints(ser, i) < 0){ 861 werrstr("serial: no endpoints found for ifc %d", i); 862 return -1; 863 } 864 p->w4data = chancreate(sizeof(ulong), 0); 865 p->gotdata = chancreate(sizeof(ulong), 0); 866 } 867 868 qlock(ser); 869 serialreset(ser); 870 for(i = 0; i < ser->nifcs; i++){ 871 p = &ser->p[i]; 872 dprint(2, "serial: valid interface, calling serinit\n"); 873 if(serinit(p) < 0){ 874 dprint(2, "serial: serinit: %r\n"); 875 return -1; 876 } 877 878 dsprint(2, "serial: adding interface %d, %p\n", p->interfc, p); 879 if(p->isjtag){ 880 snprint(p->name, sizeof p->name, "jtag"); 881 dsprint(2, "serial: JTAG interface %d %p\n", i, p); 882 snprint(p->fs.name, sizeof p->fs.name, "jtag%d.%d", devid, i); 883 } else { 884 snprint(p->name, sizeof p->name, "eiaU"); 885 if(i == 0) 886 snprint(p->fs.name, sizeof p->fs.name, "eiaU%d", devid); 887 else 888 snprint(p->fs.name, sizeof p->fs.name, "eiaU%d.%d", devid, i); 889 } 890 fprint(2, "%s...", p->fs.name); 891 p->fs.dev = dev; 892 incref(dev); 893 p->fs.aux = p; 894 p->fs.end = serialfsend; 895 usbfsadd(&p->fs); 896 } 897 898 qunlock(ser); 899 return 0; 900 } 901