1 /* $NetBSD: irframe_tty.c,v 1.16 2001/12/14 12:56:58 augustss Exp $ */ 2 3 /* 4 * TODO 5 * Test dongle code. 6 */ 7 8 /* 9 * Copyright (c) 2001 The NetBSD Foundation, Inc. 10 * All rights reserved. 11 * 12 * This code is derived from software contributed to The NetBSD Foundation 13 * by Lennart Augustsson (lennart@augustsson.net) and Tommy Bohlin 14 * (tommy@gatespace.com). 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. All advertising materials mentioning features or use of this software 25 * must display the following acknowledgement: 26 * This product includes software developed by the NetBSD 27 * Foundation, Inc. and its contributors. 28 * 4. Neither the name of The NetBSD Foundation nor the names of its 29 * contributors may be used to endorse or promote products derived 30 * from this software without specific prior written permission. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 33 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 34 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 35 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 36 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 37 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 38 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 39 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 40 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 41 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGE. 43 */ 44 45 /* 46 * Loosely based on ppp_tty.c. 47 * Framing and dongle handling written by Tommy Bohlin. 48 */ 49 50 #include <sys/param.h> 51 #include <sys/proc.h> 52 #include <sys/ioctl.h> 53 #include <sys/tty.h> 54 #include <sys/kernel.h> 55 #include <sys/lock.h> 56 #include <sys/malloc.h> 57 #include <sys/conf.h> 58 #include <sys/systm.h> 59 #include <sys/device.h> 60 #include <sys/file.h> 61 #include <sys/vnode.h> 62 #include <sys/poll.h> 63 64 #include <dev/ir/ir.h> 65 #include <dev/ir/sir.h> 66 #include <dev/ir/irdaio.h> 67 #include <dev/ir/irframevar.h> 68 69 /* Macros to clear/set/test flags. */ 70 #define SET(t, f) (t) |= (f) 71 #define CLR(t, f) (t) &= ~(f) 72 #define ISSET(t, f) ((t) & (f)) 73 74 #ifdef IRFRAMET_DEBUG 75 #define DPRINTF(x) if (irframetdebug) printf x 76 #define Static 77 int irframetdebug = 0; 78 #else 79 #define DPRINTF(x) 80 #define Static static 81 #endif 82 83 /*****/ 84 85 /* Max size with framing. */ 86 #define MAX_IRDA_FRAME (2*IRDA_MAX_FRAME_SIZE + IRDA_MAX_EBOFS + 4) 87 88 struct frame { 89 u_char *buf; 90 u_int len; 91 }; 92 #define MAXFRAMES 8 93 94 struct irframet_softc { 95 struct irframe_softc sc_irp; 96 struct tty *sc_tp; 97 98 int sc_dongle; 99 int sc_dongle_private; 100 101 int sc_state; 102 #define IRT_RSLP 0x01 /* waiting for data (read) */ 103 #if 0 104 #define IRT_WSLP 0x02 /* waiting for data (write) */ 105 #define IRT_CLOSING 0x04 /* waiting for output to drain */ 106 #endif 107 struct lock sc_wr_lk; 108 109 struct irda_params sc_params; 110 111 u_char* sc_inbuf; 112 int sc_framestate; 113 #define FRAME_OUTSIDE 0 114 #define FRAME_INSIDE 1 115 #define FRAME_ESCAPE 2 116 int sc_inchars; 117 int sc_inFCS; 118 struct callout sc_timeout; 119 120 u_int sc_nframes; 121 u_int sc_framei; 122 u_int sc_frameo; 123 struct frame sc_frames[MAXFRAMES]; 124 struct selinfo sc_rsel; 125 }; 126 127 /* line discipline methods */ 128 int irframetopen(dev_t dev, struct tty *tp); 129 int irframetclose(struct tty *tp, int flag); 130 int irframetioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, 131 struct proc *); 132 int irframetinput(int c, struct tty *tp); 133 int irframetstart(struct tty *tp); 134 135 /* pseudo device init */ 136 void irframettyattach(int); 137 138 /* irframe methods */ 139 Static int irframet_open(void *h, int flag, int mode, struct proc *p); 140 Static int irframet_close(void *h, int flag, int mode, struct proc *p); 141 Static int irframet_read(void *h, struct uio *uio, int flag); 142 Static int irframet_write(void *h, struct uio *uio, int flag); 143 Static int irframet_poll(void *h, int events, struct proc *p); 144 Static int irframet_set_params(void *h, struct irda_params *params); 145 Static int irframet_get_speeds(void *h, int *speeds); 146 Static int irframet_get_turnarounds(void *h, int *times); 147 148 /* internal */ 149 Static int irt_write_frame(struct tty *tp, u_int8_t *buf, size_t len); 150 Static int irt_putc(struct tty *tp, int c); 151 Static void irt_frame(struct irframet_softc *sc, u_char *buf, u_int len); 152 Static void irt_timeout(void *v); 153 Static void irt_setspeed(struct tty *tp, u_int speed); 154 Static void irt_setline(struct tty *tp, u_int line); 155 Static void irt_delay(struct tty *tp, u_int delay); 156 157 Static const struct irframe_methods irframet_methods = { 158 irframet_open, irframet_close, irframet_read, irframet_write, 159 irframet_poll, irframet_set_params, 160 irframet_get_speeds, irframet_get_turnarounds 161 }; 162 163 Static void irts_none(struct tty *tp, u_int speed); 164 Static void irts_tekram(struct tty *tp, u_int speed); 165 Static void irts_jeteye(struct tty *tp, u_int speed); 166 Static void irts_actisys(struct tty *tp, u_int speed); 167 Static void irts_litelink(struct tty *tp, u_int speed); 168 Static void irts_girbil(struct tty *tp, u_int speed); 169 170 #define NORMAL_SPEEDS (IRDA_SPEEDS_SIR & ~IRDA_SPEED_2400) 171 #define TURNT_POS (IRDA_TURNT_10000 | IRDA_TURNT_5000 | IRDA_TURNT_1000 | \ 172 IRDA_TURNT_500 | IRDA_TURNT_100 | IRDA_TURNT_50 | IRDA_TURNT_10) 173 Static const struct dongle { 174 void (*setspeed)(struct tty *tp, u_int speed); 175 u_int speedmask; 176 u_int turnmask; 177 } irt_dongles[DONGLE_MAX] = { 178 /* Indexed by dongle number from irdaio.h */ 179 { irts_none, IRDA_SPEEDS_SIR, IRDA_TURNT_10000 }, 180 { irts_tekram, IRDA_SPEEDS_SIR, IRDA_TURNT_10000 }, 181 { irts_jeteye, IRDA_SPEED_9600|IRDA_SPEED_19200|IRDA_SPEED_115200, 182 IRDA_TURNT_10000 }, 183 { irts_actisys, NORMAL_SPEEDS & ~IRDA_SPEED_38400, TURNT_POS }, 184 { irts_actisys, NORMAL_SPEEDS, TURNT_POS }, 185 { irts_litelink, NORMAL_SPEEDS, TURNT_POS }, 186 { irts_girbil, IRDA_SPEEDS_SIR, IRDA_TURNT_10000 | IRDA_TURNT_5000 }, 187 }; 188 189 void 190 irframettyattach(int n) 191 { 192 } 193 194 /* 195 * Line specific open routine for async tty devices. 196 * Attach the given tty to the first available irframe unit. 197 * Called from device open routine or ttioctl. 198 */ 199 /* ARGSUSED */ 200 int 201 irframetopen(dev_t dev, struct tty *tp) 202 { 203 struct proc *p = curproc; /* XXX */ 204 struct irframet_softc *sc; 205 int error, s; 206 207 DPRINTF(("%s\n", __FUNCTION__)); 208 209 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 210 return (error); 211 212 s = spltty(); 213 214 DPRINTF(("%s: linesw=%p disc=%s\n", __FUNCTION__, tp->t_linesw, 215 tp->t_linesw->l_name)); 216 if (strcmp(tp->t_linesw->l_name, "irframe") == 0) { /* XXX */ 217 sc = (struct irframet_softc *)tp->t_sc; 218 DPRINTF(("%s: sc=%p sc_tp=%p\n", __FUNCTION__, sc, sc->sc_tp)); 219 if (sc != NULL) { 220 splx(s); 221 return (EBUSY); 222 } 223 } 224 225 tp->t_sc = irframe_alloc(sizeof (struct irframet_softc), 226 &irframet_methods, tp); 227 sc = (struct irframet_softc *)tp->t_sc; 228 sc->sc_tp = tp; 229 printf("%s attached at tty%02d\n", sc->sc_irp.sc_dev.dv_xname, 230 minor(tp->t_dev)); 231 232 DPRINTF(("%s: set sc=%p\n", __FUNCTION__, sc)); 233 234 ttyflush(tp, FREAD | FWRITE); 235 236 sc->sc_dongle = DONGLE_NONE; 237 sc->sc_dongle_private = 0; 238 239 splx(s); 240 241 return (0); 242 } 243 244 /* 245 * Line specific close routine, called from device close routine 246 * and from ttioctl. 247 * Detach the tty from the irframe unit. 248 * Mimics part of ttyclose(). 249 */ 250 int 251 irframetclose(struct tty *tp, int flag) 252 { 253 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 254 int s; 255 256 DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp)); 257 258 s = spltty(); 259 ttyflush(tp, FREAD | FWRITE); 260 tp->t_linesw = linesw[0]; /* default line discipline */ 261 if (sc != NULL) { 262 tp->t_sc = NULL; 263 printf("%s detached from tty%02d\n", sc->sc_irp.sc_dev.dv_xname, 264 minor(tp->t_dev)); 265 266 if (sc->sc_tp == tp) 267 irframe_dealloc(&sc->sc_irp.sc_dev); 268 } 269 splx(s); 270 return (0); 271 } 272 273 /* 274 * Line specific (tty) ioctl routine. 275 * This discipline requires that tty device drivers call 276 * the line specific l_ioctl routine from their ioctl routines. 277 */ 278 /* ARGSUSED */ 279 int 280 irframetioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, 281 struct proc *p) 282 { 283 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 284 int error; 285 int d; 286 287 DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp)); 288 289 if (sc == NULL || tp != sc->sc_tp) 290 return (-1); 291 292 error = 0; 293 switch (cmd) { 294 case IRFRAMETTY_GET_DEVICE: 295 *(int *)data = sc->sc_irp.sc_dev.dv_unit; 296 break; 297 case IRFRAMETTY_GET_DONGLE: 298 *(int *)data = sc->sc_dongle; 299 break; 300 case IRFRAMETTY_SET_DONGLE: 301 d = *(int *)data; 302 if (d < 0 || d >= DONGLE_MAX) 303 return (EINVAL); 304 sc->sc_dongle = d; 305 break; 306 default: 307 error = EINVAL; 308 break; 309 } 310 311 return (error); 312 } 313 314 /* 315 * Start output on async tty interface. 316 * Called at spltty or higher. 317 */ 318 int 319 irframetstart(struct tty *tp) 320 { 321 /*struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc;*/ 322 323 DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp)); 324 325 if (tp->t_oproc != NULL) 326 (*tp->t_oproc)(tp); 327 328 return (0); 329 } 330 331 void 332 irt_frame(struct irframet_softc *sc, u_char *buf, u_int len) 333 { 334 DPRINTF(("%s: nframe=%d framei=%d frameo=%d\n", 335 __FUNCTION__, sc->sc_nframes, sc->sc_framei, sc->sc_frameo)); 336 337 if (sc->sc_nframes >= MAXFRAMES) { 338 #ifdef IRFRAMET_DEBUG 339 printf("%s: dropped frame\n", __FUNCTION__); 340 #endif 341 return; 342 } 343 if (sc->sc_frames[sc->sc_framei].buf == NULL) 344 return; 345 memcpy(sc->sc_frames[sc->sc_framei].buf, buf, len); 346 sc->sc_frames[sc->sc_framei].len = len; 347 sc->sc_framei = (sc->sc_framei+1) % MAXFRAMES; 348 sc->sc_nframes++; 349 if (sc->sc_state & IRT_RSLP) { 350 sc->sc_state &= ~IRT_RSLP; 351 DPRINTF(("%s: waking up reader\n", __FUNCTION__)); 352 wakeup(sc->sc_frames); 353 } 354 selwakeup(&sc->sc_rsel); 355 } 356 357 void 358 irt_timeout(void *v) 359 { 360 struct irframet_softc *sc = v; 361 362 #ifdef IRFRAMET_DEBUG 363 if (sc->sc_framestate != FRAME_OUTSIDE) 364 printf("%s: input frame timeout\n", __FUNCTION__); 365 #endif 366 sc->sc_framestate = FRAME_OUTSIDE; 367 } 368 369 int 370 irframetinput(int c, struct tty *tp) 371 { 372 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 373 374 c &= 0xff; 375 376 #if IRFRAMET_DEBUG 377 if (irframetdebug > 1) 378 DPRINTF(("%s: tp=%p c=0x%02x\n", __FUNCTION__, tp, c)); 379 #endif 380 381 if (sc == NULL || tp != (struct tty *)sc->sc_tp) 382 return (0); 383 384 if (sc->sc_inbuf == NULL) 385 return (0); 386 387 switch (c) { 388 case SIR_BOF: 389 DPRINTF(("%s: BOF\n", __FUNCTION__)); 390 sc->sc_framestate = FRAME_INSIDE; 391 sc->sc_inchars = 0; 392 sc->sc_inFCS = INITFCS; 393 break; 394 case SIR_EOF: 395 DPRINTF(("%s: EOF state=%d inchars=%d fcs=0x%04x\n", 396 __FUNCTION__, 397 sc->sc_framestate, sc->sc_inchars, sc->sc_inFCS)); 398 if (sc->sc_framestate == FRAME_INSIDE && 399 sc->sc_inchars >= 4 && sc->sc_inFCS == GOODFCS) { 400 irt_frame(sc, sc->sc_inbuf, sc->sc_inchars - 2); 401 } else if (sc->sc_framestate != FRAME_OUTSIDE) { 402 #ifdef IRFRAMET_DEBUG 403 printf("%s: malformed input frame\n", __FUNCTION__); 404 #endif 405 } 406 sc->sc_framestate = FRAME_OUTSIDE; 407 break; 408 case SIR_CE: 409 DPRINTF(("%s: CE\n", __FUNCTION__)); 410 if (sc->sc_framestate == FRAME_INSIDE) 411 sc->sc_framestate = FRAME_ESCAPE; 412 break; 413 default: 414 #if IRFRAMET_DEBUG 415 if (irframetdebug > 1) 416 DPRINTF(("%s: c=0x%02x, inchar=%d state=%d\n", __FUNCTION__, c, 417 sc->sc_inchars, sc->sc_state)); 418 #endif 419 if (sc->sc_framestate != FRAME_OUTSIDE) { 420 if (sc->sc_framestate == FRAME_ESCAPE) { 421 sc->sc_framestate = FRAME_INSIDE; 422 c ^= SIR_ESC_BIT; 423 } 424 if (sc->sc_inchars < sc->sc_params.maxsize + 2) { 425 sc->sc_inbuf[sc->sc_inchars++] = c; 426 sc->sc_inFCS = updateFCS(sc->sc_inFCS, c); 427 } else { 428 sc->sc_framestate = FRAME_OUTSIDE; 429 #ifdef IRFRAMET_DEBUG 430 printf("%s: input frame overrun\n", 431 __FUNCTION__); 432 #endif 433 } 434 } 435 break; 436 } 437 438 #if 1 439 if (sc->sc_framestate != FRAME_OUTSIDE) { 440 callout_reset(&sc->sc_timeout, hz/20, irt_timeout, sc); 441 } 442 #endif 443 444 return (0); 445 } 446 447 448 /*** irframe methods ***/ 449 450 int 451 irframet_open(void *h, int flag, int mode, struct proc *p) 452 { 453 struct tty *tp = h; 454 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 455 456 DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp)); 457 458 sc->sc_params.speed = 0; 459 sc->sc_params.ebofs = IRDA_DEFAULT_EBOFS; 460 sc->sc_params.maxsize = 0; 461 sc->sc_framestate = FRAME_OUTSIDE; 462 sc->sc_nframes = 0; 463 sc->sc_framei = 0; 464 sc->sc_frameo = 0; 465 callout_init(&sc->sc_timeout); 466 lockinit(&sc->sc_wr_lk, PZERO, "irfrtl", 0, 0); 467 468 return (0); 469 } 470 471 int 472 irframet_close(void *h, int flag, int mode, struct proc *p) 473 { 474 struct tty *tp = h; 475 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 476 int i, s; 477 478 DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp)); 479 480 callout_stop(&sc->sc_timeout); 481 s = splir(); 482 if (sc->sc_inbuf != NULL) { 483 free(sc->sc_inbuf, M_DEVBUF); 484 sc->sc_inbuf = NULL; 485 } 486 for (i = 0; i < MAXFRAMES; i++) { 487 if (sc->sc_frames[i].buf != NULL) { 488 free(sc->sc_frames[i].buf, M_DEVBUF); 489 sc->sc_frames[i].buf = NULL; 490 } 491 } 492 splx(s); 493 494 return (0); 495 } 496 497 int 498 irframet_read(void *h, struct uio *uio, int flag) 499 { 500 struct tty *tp = h; 501 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 502 int error = 0; 503 int s; 504 505 DPRINTF(("%s: resid=%d, iovcnt=%d, offset=%ld\n", 506 __FUNCTION__, uio->uio_resid, uio->uio_iovcnt, 507 (long)uio->uio_offset)); 508 DPRINTF(("%s: nframe=%d framei=%d frameo=%d\n", 509 __FUNCTION__, sc->sc_nframes, sc->sc_framei, sc->sc_frameo)); 510 511 512 s = splir(); 513 while (sc->sc_nframes == 0) { 514 if (flag & IO_NDELAY) { 515 splx(s); 516 return (EWOULDBLOCK); 517 } 518 sc->sc_state |= IRT_RSLP; 519 DPRINTF(("%s: sleep\n", __FUNCTION__)); 520 error = tsleep(sc->sc_frames, PZERO | PCATCH, "irtrd", 0); 521 DPRINTF(("%s: woke, error=%d\n", __FUNCTION__, error)); 522 if (error) { 523 sc->sc_state &= ~IRT_RSLP; 524 break; 525 } 526 } 527 528 /* Do just one frame transfer per read */ 529 if (!error) { 530 if (uio->uio_resid < sc->sc_frames[sc->sc_frameo].len) { 531 DPRINTF(("%s: uio buffer smaller than frame size " 532 "(%d < %d)\n", __FUNCTION__, uio->uio_resid, 533 sc->sc_frames[sc->sc_frameo].len)); 534 error = EINVAL; 535 } else { 536 DPRINTF(("%s: moving %d bytes\n", __FUNCTION__, 537 sc->sc_frames[sc->sc_frameo].len)); 538 error = uiomove(sc->sc_frames[sc->sc_frameo].buf, 539 sc->sc_frames[sc->sc_frameo].len, uio); 540 DPRINTF(("%s: error=%d\n", __FUNCTION__, error)); 541 } 542 sc->sc_frameo = (sc->sc_frameo+1) % MAXFRAMES; 543 sc->sc_nframes--; 544 } 545 splx(s); 546 547 return (error); 548 } 549 550 int 551 irt_putc(struct tty *tp, int c) 552 { 553 int s; 554 int error; 555 556 #if IRFRAMET_DEBUG 557 if (irframetdebug > 3) 558 DPRINTF(("%s: tp=%p c=0x%02x cc=%d\n", __FUNCTION__, tp, c, 559 tp->t_outq.c_cc)); 560 #endif 561 if (tp->t_outq.c_cc > tp->t_hiwat) { 562 irframetstart(tp); 563 s = spltty(); 564 /* 565 * This can only occur if FLUSHO is set in t_lflag, 566 * or if ttstart/oproc is synchronous (or very fast). 567 */ 568 if (tp->t_outq.c_cc <= tp->t_hiwat) { 569 splx(s); 570 goto go; 571 } 572 SET(tp->t_state, TS_ASLEEP); 573 error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout, 0); 574 splx(s); 575 if (error) 576 return (error); 577 } 578 go: 579 if (putc(c, &tp->t_outq) < 0) { 580 printf("irframe: putc failed\n"); 581 return (EIO); 582 } 583 return (0); 584 } 585 586 int 587 irframet_write(void *h, struct uio *uio, int flag) 588 { 589 struct tty *tp = h; 590 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 591 u_int8_t buf[MAX_IRDA_FRAME]; 592 int n; 593 594 DPRINTF(("%s: resid=%d, iovcnt=%d, offset=%ld\n", 595 __FUNCTION__, uio->uio_resid, uio->uio_iovcnt, 596 (long)uio->uio_offset)); 597 598 n = irda_sir_frame(buf, MAX_IRDA_FRAME, uio, sc->sc_params.ebofs); 599 if (n < 0) { 600 #ifdef IRFRAMET_DEBUG 601 printf("%s: irda_sir_frame() error=%d\n", __FUNCTION__, -n); 602 #endif 603 return (-n); 604 } 605 return (irt_write_frame(tp, buf, n)); 606 } 607 608 int 609 irt_write_frame(struct tty *tp, u_int8_t *buf, size_t len) 610 { 611 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 612 int error, i; 613 614 DPRINTF(("%s: tp=%p len=%d\n", __FUNCTION__, tp, len)); 615 616 lockmgr(&sc->sc_wr_lk, LK_EXCLUSIVE, NULL); 617 error = 0; 618 for (i = 0; !error && i < len; i++) 619 error = irt_putc(tp, buf[i]); 620 lockmgr(&sc->sc_wr_lk, LK_RELEASE, NULL); 621 622 irframetstart(tp); 623 624 DPRINTF(("%s: done, error=%d\n", __FUNCTION__, error)); 625 626 return (error); 627 } 628 629 int 630 irframet_poll(void *h, int events, struct proc *p) 631 { 632 struct tty *tp = h; 633 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 634 int revents = 0; 635 int s; 636 637 DPRINTF(("%s: sc=%p\n", __FUNCTION__, sc)); 638 639 s = splir(); 640 /* XXX is this a good check? */ 641 if (events & (POLLOUT | POLLWRNORM)) 642 if (tp->t_outq.c_cc <= tp->t_lowat) 643 revents |= events & (POLLOUT | POLLWRNORM); 644 645 if (events & (POLLIN | POLLRDNORM)) { 646 if (sc->sc_nframes > 0) { 647 DPRINTF(("%s: have data\n", __FUNCTION__)); 648 revents |= events & (POLLIN | POLLRDNORM); 649 } else { 650 DPRINTF(("%s: recording select\n", __FUNCTION__)); 651 selrecord(p, &sc->sc_rsel); 652 } 653 } 654 splx(s); 655 656 return (revents); 657 } 658 659 int 660 irframet_set_params(void *h, struct irda_params *p) 661 { 662 struct tty *tp = h; 663 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 664 int i; 665 666 DPRINTF(("%s: tp=%p speed=%d ebofs=%d maxsize=%d\n", 667 __FUNCTION__, tp, p->speed, p->ebofs, p->maxsize)); 668 669 if (p->speed != sc->sc_params.speed) { 670 /* Checked in irframe.c */ 671 lockmgr(&sc->sc_wr_lk, LK_EXCLUSIVE, NULL); 672 irt_dongles[sc->sc_dongle].setspeed(tp, p->speed); 673 lockmgr(&sc->sc_wr_lk, LK_RELEASE, NULL); 674 sc->sc_params.speed = p->speed; 675 } 676 677 /* Max size checked in irframe.c */ 678 sc->sc_params.ebofs = p->ebofs; 679 /* Max size checked in irframe.c */ 680 if (sc->sc_params.maxsize != p->maxsize) { 681 sc->sc_params.maxsize = p->maxsize; 682 if (sc->sc_inbuf != NULL) 683 free(sc->sc_inbuf, M_DEVBUF); 684 for (i = 0; i < MAXFRAMES; i++) 685 if (sc->sc_frames[i].buf != NULL) 686 free(sc->sc_frames[i].buf, M_DEVBUF); 687 if (sc->sc_params.maxsize != 0) { 688 sc->sc_inbuf = malloc(sc->sc_params.maxsize+2, 689 M_DEVBUF, M_WAITOK); 690 for (i = 0; i < MAXFRAMES; i++) 691 sc->sc_frames[i].buf = 692 malloc(sc->sc_params.maxsize, 693 M_DEVBUF, M_WAITOK); 694 } else { 695 sc->sc_inbuf = NULL; 696 for (i = 0; i < MAXFRAMES; i++) 697 sc->sc_frames[i].buf = NULL; 698 } 699 } 700 sc->sc_framestate = FRAME_OUTSIDE; 701 702 return (0); 703 } 704 705 int 706 irframet_get_speeds(void *h, int *speeds) 707 { 708 struct tty *tp = h; 709 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 710 711 DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp)); 712 713 if (sc == NULL) /* during attach */ 714 *speeds = IRDA_SPEEDS_SIR; 715 else 716 *speeds = irt_dongles[sc->sc_dongle].speedmask; 717 return (0); 718 } 719 720 int 721 irframet_get_turnarounds(void *h, int *turnarounds) 722 { 723 struct tty *tp = h; 724 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 725 726 DPRINTF(("%s: tp=%p\n", __FUNCTION__, tp)); 727 728 *turnarounds = irt_dongles[sc->sc_dongle].turnmask; 729 return (0); 730 } 731 732 void 733 irt_setspeed(struct tty *tp, u_int speed) 734 { 735 struct termios tt; 736 737 ttioctl(tp, TIOCGETA, (caddr_t)&tt, 0, curproc); 738 tt.c_ispeed = tt.c_ospeed = speed; 739 ttioctl(tp, TIOCSETAF, (caddr_t)&tt, 0, curproc); 740 } 741 742 void 743 irt_setline(struct tty *tp, u_int line) 744 { 745 int mline = line; 746 ttioctl(tp, TIOCMSET, (caddr_t)&mline, 0, curproc); 747 } 748 749 void 750 irt_delay(struct tty *tp, u_int ms) 751 { 752 if (cold) 753 delay(ms * 1000); 754 else 755 tsleep(&irt_delay, PZERO, "irtdly", ms * hz / 1000 + 1); 756 757 } 758 759 /********************************************************************** 760 * No dongle 761 **********************************************************************/ 762 void 763 irts_none(struct tty *tp, u_int speed) 764 { 765 irt_setspeed(tp, speed); 766 } 767 768 /********************************************************************** 769 * Tekram 770 **********************************************************************/ 771 #define TEKRAM_PW 0x10 772 773 #define TEKRAM_115200 (TEKRAM_PW|0x00) 774 #define TEKRAM_57600 (TEKRAM_PW|0x01) 775 #define TEKRAM_38400 (TEKRAM_PW|0x02) 776 #define TEKRAM_19200 (TEKRAM_PW|0x03) 777 #define TEKRAM_9600 (TEKRAM_PW|0x04) 778 #define TEKRAM_2400 (TEKRAM_PW|0x08) 779 780 #define TEKRAM_TV (TEKRAM_PW|0x05) 781 782 void 783 irts_tekram(struct tty *tp, u_int speed) 784 { 785 int s; 786 787 irt_setspeed(tp, 9600); 788 irt_setline(tp, 0); 789 irt_delay(tp, 50); 790 irt_setline(tp, TIOCM_RTS); 791 irt_delay(tp, 1); 792 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 793 irt_delay(tp, 1); /* 50 us */ 794 irt_setline(tp, TIOCM_DTR); 795 irt_delay(tp, 1); /* 7 us */ 796 switch(speed) { 797 case 115200: s = TEKRAM_115200; break; 798 case 57600: s = TEKRAM_57600; break; 799 case 38400: s = TEKRAM_38400; break; 800 case 19200: s = TEKRAM_19200; break; 801 case 2400: s = TEKRAM_2400; break; 802 default: s = TEKRAM_9600; break; 803 } 804 irt_putc(tp, s); 805 irt_delay(tp, 100); 806 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 807 if (speed != 9600) 808 irt_setspeed(tp, speed); 809 irt_delay(tp, 1); /* 50 us */ 810 } 811 812 /********************************************************************** 813 * Jeteye 814 **********************************************************************/ 815 void 816 irts_jeteye(struct tty *tp, u_int speed) 817 { 818 switch (speed) { 819 case 19200: 820 irt_setline(tp, TIOCM_DTR); 821 break; 822 case 115200: 823 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 824 break; 825 default: /*9600*/ 826 irt_setline(tp, TIOCM_RTS); 827 break; 828 } 829 irt_setspeed(tp, speed); 830 } 831 832 /********************************************************************** 833 * Actisys 834 **********************************************************************/ 835 void 836 irts_actisys(struct tty *tp, u_int speed) 837 { 838 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 839 int pulses; 840 841 irt_setspeed(tp, speed); 842 843 switch(speed) { 844 case 19200: pulses=1; break; 845 case 57600: pulses=2; break; 846 case 115200: pulses=3; break; 847 case 38400: pulses=4; break; 848 default: /* 9600 */ pulses=0; break; 849 } 850 851 if (sc->sc_dongle_private == 0) { 852 sc->sc_dongle_private = 1; 853 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 854 /* 855 * Must wait at least 50ms after initial 856 * power on to charge internal capacitor 857 */ 858 irt_delay(tp, 50); 859 } 860 irt_setline(tp, TIOCM_RTS); 861 delay(2); 862 for (;;) { 863 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 864 delay(2); 865 if (--pulses <= 0) 866 break; 867 irt_setline(tp, TIOCM_DTR); 868 delay(2); 869 } 870 } 871 872 /********************************************************************** 873 * Litelink 874 **********************************************************************/ 875 void 876 irts_litelink(struct tty *tp, u_int speed) 877 { 878 struct irframet_softc *sc = (struct irframet_softc *)tp->t_sc; 879 int pulses; 880 881 irt_setspeed(tp, speed); 882 883 switch(speed) { 884 case 57600: pulses=1; break; 885 case 38400: pulses=2; break; 886 case 19200: pulses=3; break; 887 case 9600: pulses=4; break; 888 default: /* 115200 */ pulses=0; break; 889 } 890 891 if (sc->sc_dongle_private == 0) { 892 sc->sc_dongle_private = 1; 893 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 894 } 895 irt_setline(tp, TIOCM_RTS); 896 irt_delay(tp, 1); /* 15 us */; 897 for (;;) { 898 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 899 irt_delay(tp, 1); /* 15 us */; 900 if (--pulses <= 0) 901 break; 902 irt_setline(tp, TIOCM_DTR); 903 irt_delay(tp, 1); /* 15 us */; 904 } 905 } 906 907 /********************************************************************** 908 * Girbil 909 **********************************************************************/ 910 /* Control register 1 */ 911 #define GIRBIL_TXEN 0x01 /* Enable transmitter */ 912 #define GIRBIL_RXEN 0x02 /* Enable receiver */ 913 #define GIRBIL_ECAN 0x04 /* Cancel self emmited data */ 914 #define GIRBIL_ECHO 0x08 /* Echo control characters */ 915 916 /* LED Current Register */ 917 #define GIRBIL_HIGH 0x20 918 #define GIRBIL_MEDIUM 0x21 919 #define GIRBIL_LOW 0x22 920 921 /* Baud register */ 922 #define GIRBIL_2400 0x30 923 #define GIRBIL_4800 0x31 924 #define GIRBIL_9600 0x32 925 #define GIRBIL_19200 0x33 926 #define GIRBIL_38400 0x34 927 #define GIRBIL_57600 0x35 928 #define GIRBIL_115200 0x36 929 930 /* Mode register */ 931 #define GIRBIL_IRDA 0x40 932 #define GIRBIL_ASK 0x41 933 934 /* Control register 2 */ 935 #define GIRBIL_LOAD 0x51 /* Load the new baud rate value */ 936 937 void 938 irts_girbil(struct tty *tp, u_int speed) 939 { 940 int s; 941 942 irt_setspeed(tp, 9600); 943 irt_setline(tp, TIOCM_DTR); 944 irt_delay(tp, 5); 945 irt_setline(tp, TIOCM_RTS); 946 irt_delay(tp, 20); 947 switch(speed) { 948 case 115200: s = GIRBIL_115200; break; 949 case 57600: s = GIRBIL_57600; break; 950 case 38400: s = GIRBIL_38400; break; 951 case 19200: s = GIRBIL_19200; break; 952 case 4800: s = GIRBIL_4800; break; 953 case 2400: s = GIRBIL_2400; break; 954 default: s = GIRBIL_9600; break; 955 } 956 irt_putc(tp, GIRBIL_TXEN|GIRBIL_RXEN); 957 irt_putc(tp, s); 958 irt_putc(tp, GIRBIL_LOAD); 959 irt_delay(tp, 100); 960 irt_setline(tp, TIOCM_DTR | TIOCM_RTS); 961 if (speed != 9600) 962 irt_setspeed(tp, speed); 963 } 964