digi.c revision 76358
1/*- 2 * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org> 3 * based on work by Slawa Olhovchenkov 4 * John Prince <johnp@knight-trosoft.com> 5 * Eric Hernes 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: head/sys/dev/digi/digi.c 76358 2001-05-08 07:55:33Z brian $ 30 */ 31 32/*- 33 * TODO: 34 * Allow altpin setups again 35 * Figure out what the con bios stuff is supposed to do 36 * Test with *LOTS* more cards - I only have a PCI8r and an ISA Xem. 37 */ 38 39#include <sys/param.h> 40#include <sys/systm.h> 41#include <sys/proc.h> 42#include <sys/conf.h> 43#include <sys/linker.h> 44#include <sys/kernel.h> 45#include <sys/mbuf.h> 46#include <sys/malloc.h> 47#include <sys/tty.h> 48#include <sys/syslog.h> 49#include <sys/fcntl.h> 50#include <sys/bus.h> 51#include <sys/bus.h> 52#include <machine/resource.h> 53 54#include <dev/digi/digireg.h> 55#include <dev/digi/digiio.h> 56#include <dev/digi/digi.h> 57#include <dev/digi/digi_mod.h> 58#include <dev/digi/digi_pci.h> 59 60#define CDEV_MAJOR 162 61 62#define CTRL_DEV 0x800000 63#define CALLOUT_MASK 0x400000 64#define CONTROL_INIT_STATE 0x100000 65#define CONTROL_LOCK_STATE 0x200000 66#define CONTROL_MASK (CTRL_DEV|CONTROL_INIT_STATE|CONTROL_LOCK_STATE) 67#define UNIT_MASK 0x030000 68#define PORT_MASK 0x0000FF 69#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) 70#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) 71#define MINOR_TO_UNIT(mynor) (((mynor) & UNIT_MASK)>>16) 72#define MINOR_TO_PORT(mynor) ((mynor) & PORT_MASK) 73 74static d_open_t digiopen; 75static d_close_t digiclose; 76static d_read_t digiread; 77static d_write_t digiwrite; 78static d_ioctl_t digiioctl; 79 80static void digistop(struct tty *tp, int rw); 81static int digimctl(struct digi_p *port, int bits, int how); 82static void digi_poll(void *ptr); 83static void digi_freemoduledata(struct digi_softc *); 84static void fepcmd(struct digi_p *port, int cmd, int op, int ncmds); 85static void digistart(struct tty *tp); 86static int digiparam(struct tty *tp, struct termios *t); 87static void digihardclose(struct digi_p *port); 88static void digi_intr(void *); 89static int digi_init(struct digi_softc *_sc); 90static int digi_loadmoduledata(struct digi_softc *); 91static int digi_inuse(struct digi_softc *); 92static void digi_free_state(struct digi_softc *); 93 94#define fepcmd_b(port, cmd, op1, op2, ncmds) \ 95 fepcmd(port, cmd, (op2 << 8) | op1, ncmds) 96#define fepcmd_w fepcmd 97 98 99static speed_t digidefaultrate = TTYDEF_SPEED; 100 101struct con_bios { 102 struct con_bios *next; 103 u_char *bios; 104 size_t size; 105}; 106 107struct con_bios *con_bios_list; 108devclass_t digi_devclass; 109static char driver_name[] = "digi"; 110unsigned digi_debug = 0; 111 112static struct speedtab digispeedtab[] = { 113 { 0, 0}, /* old (sysV-like) Bx codes */ 114 { 50, 1}, 115 { 75, 2}, 116 { 110, 3}, 117 { 134, 4}, 118 { 150, 5}, 119 { 200, 6}, 120 { 300, 7}, 121 { 600, 8}, 122 { 1200, 9}, 123 { 1800, 10}, 124 { 2400, 11}, 125 { 4800, 12}, 126 { 9600, 13}, 127 { 19200, 14}, 128 { 38400, 15}, 129 { 57600, (02000 | 1)}, 130 { 76800, (02000 | 2)}, 131 { 115200, (02000 | 3)}, 132 { 230400, (02000 | 6)}, 133 { -1, -1} 134}; 135 136const struct digi_control_signals digi_xixe_signals = { 137 0x02, 0x08, 0x10, 0x20, 0x40, 0x80 138}; 139 140const struct digi_control_signals digi_normal_signals = { 141 0x02, 0x80, 0x20, 0x10, 0x40, 0x01 142}; 143 144static struct cdevsw digi_sw = { 145 digiopen, /* open */ 146 digiclose, /* close */ 147 digiread, /* read */ 148 digiwrite, /* write */ 149 digiioctl, /* ioctl */ 150 ttypoll, /* poll */ 151 nommap, /* mmap */ 152 nostrategy, /* strategy */ 153 driver_name, /* name */ 154 CDEV_MAJOR, /* maj */ 155 nodump, /* dump */ 156 nopsize, /* psize */ 157 D_TTY | D_KQFILTER, /* flags */ 158 ttykqfilter /* bmaj */ 159}; 160 161int 162digi_modhandler(module_t mod, int event, void *arg) 163{ 164 static int ref = 0; 165 166 switch (event) { 167 case MOD_LOAD: 168 if (ref++ == 0) 169 cdevsw_add(&digi_sw); 170 break; 171 172 case MOD_UNLOAD: 173 if (--ref == 0) 174 cdevsw_remove(&digi_sw); 175 break; 176 } 177 178 return (0); 179} 180 181static void 182digi_poll(void *ptr) 183{ 184 struct digi_softc *sc; 185 186 sc = (struct digi_softc *)ptr; 187 callout_handle_init(&sc->callout); 188 digi_intr(sc); 189 sc->callout = timeout(digi_poll, sc, (hz >= 200) ? hz / 100 : 1); 190} 191 192static void 193digi_int_test(void *v) 194{ 195 struct digi_softc *sc = v; 196 197 callout_handle_init(&sc->inttest); 198#ifdef DIGI_INTERRUPT 199 if (sc->intr_timestamp.tv_sec || sc->intr_timestamp.tv_usec) { 200 /* interrupt OK! */ 201 return; 202 } 203 log(LOG_ERR, "digi%d: Interrupt didn't work, use polled mode\n", unit); 204#endif 205 sc->callout = timeout(digi_poll, sc, (hz >= 200) ? hz / 100 : 1); 206} 207 208static void 209digi_freemoduledata(struct digi_softc *sc) 210{ 211 if (sc->fep.data != NULL) { 212 free(sc->fep.data, M_TTYS); 213 sc->fep.data = NULL; 214 } 215 if (sc->link.data != NULL) { 216 free(sc->link.data, M_TTYS); 217 sc->link.data = NULL; 218 } 219 if (sc->bios.data != NULL) { 220 free(sc->bios.data, M_TTYS); 221 sc->bios.data = NULL; 222 } 223} 224 225static int 226digi_bcopy(const void *vfrom, void *vto, size_t sz) 227{ 228 volatile const char *from = (volatile const char *)vfrom; 229 volatile char *to = (volatile char *)vto; 230 size_t i; 231 232 for (i = 0; i < sz; i++) 233 *to++ = *from++; 234 235 from = (const volatile char *)vfrom; 236 to = (volatile char *)vto; 237 for (i = 0; i < sz; i++) 238 if (*to++ != *from++) 239 return (0); 240 return (1); 241} 242 243static int 244digi_init(struct digi_softc *sc) 245{ 246 int i, cnt, resp; 247 u_char *ptr; 248 int lowwater; 249 struct digi_p *port; 250 volatile struct board_chan *bc; 251 252 ptr = NULL; 253 254 if (sc->status == DIGI_STATUS_DISABLED) { 255 log(LOG_ERR, "digi%d: Cannot init a disabled card\n", 256 sc->res.unit); 257 return (EIO); 258 } 259 if (sc->bios.data == NULL) { 260 log(LOG_ERR, "digi%d: Cannot init without BIOS\n", 261 sc->res.unit); 262 return (EIO); 263 } 264#if 0 265 if (sc->link.data == NULL && sc->model >= PCCX) { 266 log(LOG_ERR, "digi%d: Cannot init without link info\n", 267 sc->res.unit); 268 return (EIO); 269 } 270#endif 271 if (sc->fep.data == NULL) { 272 log(LOG_ERR, "digi%d: Cannot init without fep code\n", 273 sc->res.unit); 274 return (EIO); 275 } 276 sc->status = DIGI_STATUS_NOTINIT; 277 278 if (sc->numports) { 279 /* 280 * We're re-initialising - maybe because someone's attached 281 * another port module. For now, we just re-initialise 282 * everything. 283 */ 284 if (digi_inuse(sc)) 285 return (EBUSY); 286 287 digi_free_state(sc); 288 } 289 290 ptr = sc->setwin(sc, MISCGLOBAL); 291 for (i = 0; i < 16; i += 2) 292 vW(ptr + i) = 0; 293 294 switch (sc->model) { 295 case PCXEVE: 296 outb(sc->wport, 0xff); /* window 7 */ 297 ptr = sc->vmem + (BIOSCODE & 0x1fff); 298 299 if (!digi_bcopy(sc->bios.data, ptr, sc->bios.size)) { 300 device_printf(sc->dev, "BIOS upload failed\n"); 301 return (EIO); 302 } 303 304 outb(sc->port, FEPCLR); 305 break; 306 307 case PCXE: 308 case PCXI: 309 case PCCX: 310 ptr = sc->setwin(sc, BIOSCODE + ((0xf000 - sc->mem_seg) << 4)); 311 if (!digi_bcopy(sc->bios.data, ptr, sc->bios.size)) { 312 device_printf(sc->dev, "BIOS upload failed\n"); 313 return (EIO); 314 } 315 break; 316 317 case PCXEM: 318 case PCIEPCX: 319 case PCIXR: 320 if (sc->model == PCIXR) 321 PCIPORT = FEPRST; 322 else 323 outb(sc->port, FEPRST | FEPMEM); 324 325 for (i = 0; ((sc->model == PCIXR ? PCIPORT : inb(sc->port)) & 326 FEPMASK) != FEPRST; i++) { 327 if (i > 1000) { 328 log(LOG_ERR, "digi%d: init reset failed\n", 329 sc->res.unit); 330 return (EIO); 331 } 332 tsleep(sc, PUSER | PCATCH, "digiinit0", 1); 333 } 334 DLOG(DIGIDB_INIT, (sc->dev, "Got init reset after %d us\n", i)); 335 336 /* Now upload the BIOS */ 337 cnt = (sc->bios.size < sc->win_size - BIOSOFFSET) ? 338 sc->bios.size : sc->win_size - BIOSOFFSET; 339 340 ptr = sc->setwin(sc, BIOSOFFSET); 341 if (!digi_bcopy(sc->bios.data, ptr, cnt)) { 342 device_printf(sc->dev, "BIOS upload (1) failed\n"); 343 return (EIO); 344 } 345 346 if (cnt != sc->bios.size) { 347 /* and the second part */ 348 ptr = sc->setwin(sc, sc->win_size); 349 if (!digi_bcopy(sc->bios.data + cnt, ptr, 350 sc->bios.size - cnt)) { 351 device_printf(sc->dev, "BIOS upload failed\n"); 352 return (EIO); 353 } 354 } 355 356 ptr = sc->setwin(sc, 0); 357 vW(ptr + 0) = 0x0401; 358 vW(ptr + 2) = 0x0bf0; 359 vW(ptr + 4) = 0x0000; 360 vW(ptr + 6) = 0x0000; 361 362 break; 363 } 364 365 DLOG(DIGIDB_INIT, (sc->dev, "BIOS uploaded\n")); 366 367 ptr = sc->setwin(sc, MISCGLOBAL); 368 W(ptr) = 0; 369 370 if (sc->model == PCIXR) { 371 PCIPORT = FEPCLR; 372 resp = FEPRST; 373 } else if (sc->model == PCXEVE) { 374 outb(sc->port, FEPCLR); 375 resp = FEPRST; 376 } else { 377 outb(sc->port, FEPCLR | FEPMEM); 378 resp = FEPRST | FEPMEM; 379 } 380 381 for (i = 0; ((sc->model == PCIXR ? PCIPORT : inb(sc->port)) & FEPMASK) 382 == resp; i++) { 383 if (i > 1000) { 384 log(LOG_ERR, "digi%d: BIOS start failed\n", 385 sc->res.unit); 386 return (EIO); 387 } 388 tsleep(sc, PUSER | PCATCH, "digibios0", 1); 389 } 390 391 DLOG(DIGIDB_INIT, (sc->dev, "BIOS started after %d us\n", i)); 392 393 for (i = 0; vW(ptr) != *(u_short *)"GD"; i++) { 394 if (i > 2000) { 395 log(LOG_ERR, "digi%d: BIOS boot failed " 396 "(0x%02x != 0x%02x)\n", 397 sc->res.unit, vW(ptr), *(u_short *)"GD"); 398 return (EIO); 399 } 400 tsleep(sc, PUSER | PCATCH, "digibios1", 1); 401 } 402 403 DLOG(DIGIDB_INIT, (sc->dev, "BIOS booted after %d iterations\n", i)); 404 405 if (sc->link.data != NULL) { 406 DLOG(DIGIDB_INIT, (sc->dev, "Loading link data\n")); 407 ptr = sc->setwin(sc, 0xcd0); 408 digi_bcopy(sc->link.data, ptr, 21); /* XXX 21 ? */ 409 } 410 411 /* load FEP/OS */ 412 413 switch (sc->model) { 414 case PCXE: 415 case PCXEVE: 416 case PCXI: 417 ptr = sc->setwin(sc, sc->model == PCXI ? 0x2000 : 0x0); 418 digi_bcopy(sc->fep.data, ptr, sc->fep.size); 419 420 /* A BIOS request to move our data to 0x2000 */ 421 ptr = sc->setwin(sc, MBOX); 422 vW(ptr + 0) = 2; 423 vW(ptr + 2) = sc->mem_seg + FEPCODESEG; 424 vW(ptr + 4) = 0; 425 vW(ptr + 6) = FEPCODESEG; 426 vW(ptr + 8) = 0; 427 vW(ptr + 10) = sc->fep.size; 428 429 /* Run the BIOS request */ 430 outb(sc->port, FEPREQ | FEPMEM); 431 outb(sc->port, FEPCLR | FEPMEM); 432 433 for (i = 0; W(ptr); i++) { 434 if (i > 10) { 435 log(LOG_ERR, "digi%d: FEP/OS move failed\n", 436 sc->res.unit); 437 sc->hidewin(sc); 438 return (EIO); 439 } 440 tsleep(sc, PUSER | PCATCH, "digifep0", 1); 441 } 442 DLOG(DIGIDB_INIT, 443 (sc->dev, "FEP/OS moved after %d iterations\n", i)); 444 445 /* Clear the confirm word */ 446 ptr = sc->setwin(sc, FEPSTAT); 447 vW(ptr + 0) = 0; 448 449 /* A BIOS request to execute the FEP/OS */ 450 ptr = sc->setwin(sc, MBOX); 451 vW(ptr + 0) = 0x01; 452 vW(ptr + 2) = FEPCODESEG; 453 vW(ptr + 4) = 0x04; 454 455 /* Run the BIOS request */ 456 outb(sc->port, FEPREQ); 457 outb(sc->port, FEPCLR); 458 459 ptr = sc->setwin(sc, FEPSTAT); 460 461 break; 462 463 case PCXEM: 464 case PCIEPCX: 465 case PCIXR: 466 DLOG(DIGIDB_INIT, (sc->dev, "Loading FEP/OS\n")); 467 468 cnt = (sc->fep.size < sc->win_size - BIOSOFFSET) ? 469 sc->fep.size : sc->win_size - BIOSOFFSET; 470 471 ptr = sc->setwin(sc, BIOSOFFSET); 472 digi_bcopy(sc->fep.data, ptr, cnt); 473 474 if (cnt != sc->fep.size) { 475 ptr = sc->setwin(sc, BIOSOFFSET + cnt); 476 digi_bcopy(sc->fep.data + cnt, ptr, 477 sc->fep.size - cnt); 478 } 479 480 DLOG(DIGIDB_INIT, (sc->dev, "FEP/OS loaded\n")); 481 482 ptr = sc->setwin(sc, 0xc30); 483 W(ptr + 4) = 0x1004; 484 W(ptr + 6) = 0xbfc0; 485 W(ptr + 0) = 0x03; 486 W(ptr + 2) = 0x00; 487 488 /* Clear the confirm word */ 489 ptr = sc->setwin(sc, FEPSTAT); 490 W(ptr + 0) = 0; 491 492 if (sc->port) 493 outb(sc->port, 0); /* XXX necessary ? */ 494 495 break; 496 497 case PCCX: 498 ptr = sc->setwin(sc, 0xd000); 499 digi_bcopy(sc->fep.data, ptr, sc->fep.size); 500 501 /* A BIOS request to execute the FEP/OS */ 502 ptr = sc->setwin(sc, 0xc40); 503 W(ptr + 0) = 1; 504 W(ptr + 2) = FEPCODE >> 4; 505 W(ptr + 4) = 4; 506 507 /* Clear the confirm word */ 508 ptr = sc->setwin(sc, FEPSTAT); 509 W(ptr + 0) = 0; 510 511 /* Run the BIOS request */ 512 outb(sc->port, FEPREQ | FEPMEM); /* send interrupt to BIOS */ 513 outb(sc->port, FEPCLR | FEPMEM); 514 break; 515 } 516 517 /* Now wait 'till the FEP/OS has booted */ 518 for (i = 0; vW(ptr) != *(u_short *)"OS"; i++) { 519 if (i > 2000) { 520 log(LOG_ERR, "digi%d: FEP/OS start failed " 521 "(0x%02x != 0x%02x)\n", 522 sc->res.unit, vW(ptr), *(u_short *)"OS"); 523 sc->hidewin(sc); 524 return (EIO); 525 } 526 tsleep(sc, PUSER | PCATCH, "digifep1", 1); 527 } 528 529 DLOG(DIGIDB_INIT, (sc->dev, "FEP/OS started after %d iterations\n", i)); 530 531 if (sc->model >= PCXEM) { 532 ptr = sc->setwin(sc, 0xe04); 533 vW(ptr) = 2; 534 ptr = sc->setwin(sc, 0xc02); 535 sc->numports = vW(ptr); 536 } else { 537 ptr = sc->setwin(sc, 0xc22); 538 sc->numports = vW(ptr); 539 } 540 541 if (sc->numports == 0) { 542 device_printf(sc->dev, "%s, 0 ports found\n", sc->name); 543 sc->hidewin(sc); 544 return (0); 545 } 546 547 if (sc->numports > 256) { 548 /* Our minor numbering scheme is broken for more than 256 */ 549 device_printf(sc->dev, "%s, 256 ports (%d ports found)\n", 550 sc->name, sc->numports); 551 sc->numports = 256; 552 } else 553 device_printf(sc->dev, "%s, %d ports found\n", sc->name, 554 sc->numports); 555 556 if (sc->ports) 557 free(sc->ports, M_TTYS); 558 MALLOC(sc->ports, struct digi_p *, 559 sizeof(struct digi_p) * sc->numports, M_TTYS, M_WAIT | M_ZERO); 560 561 if (sc->ttys) 562 free(sc->ttys, M_TTYS); 563 MALLOC(sc->ttys, struct tty *, sizeof(struct tty) * sc->numports, 564 M_TTYS, M_WAIT | M_ZERO); 565 566 /* 567 * XXX Should read port 0xc90 for an array of 2byte values, 1 per 568 * port. If the value is 0, the port is broken.... 569 */ 570 571 ptr = sc->setwin(sc, 0); 572 573 /* We should now init per-port structures */ 574 bc = (volatile struct board_chan *)(ptr + CHANSTRUCT); 575 sc->gdata = (volatile struct global_data *)(ptr + FEP_GLOBAL); 576 577 sc->memcmd = ptr + sc->gdata->cstart; 578 sc->memevent = ptr + sc->gdata->istart; 579 580 for (i = 0; i < sc->numports; i++, bc++) { 581 port = sc->ports + i; 582 port->pnum = i; 583 port->sc = sc; 584 port->status = ENABLED; 585 port->tp = sc->ttys + i; 586 port->bc = bc; 587 588 if (sc->model == PCXEVE) { 589 port->txbuf = ptr + 590 (((bc->tseg - sc->mem_seg) << 4) & 0x1fff); 591 port->rxbuf = ptr + 592 (((bc->rseg - sc->mem_seg) << 4) & 0x1fff); 593 port->txwin = FEPWIN | ((bc->tseg - sc->mem_seg) >> 9); 594 port->rxwin = FEPWIN | ((bc->rseg - sc->mem_seg) >> 9); 595 } else if (sc->model == PCXI || sc->model == PCXE) { 596 port->txbuf = ptr + ((bc->tseg - sc->mem_seg) << 4); 597 port->rxbuf = ptr + ((bc->rseg - sc->mem_seg) << 4); 598 port->txwin = port->rxwin = 0; 599 } else { 600 port->txbuf = ptr + 601 (((bc->tseg - sc->mem_seg) << 4) % sc->win_size); 602 port->rxbuf = ptr + 603 (((bc->rseg - sc->mem_seg) << 4) % sc->win_size); 604 port->txwin = FEPWIN | 605 (((bc->tseg - sc->mem_seg) << 4) / sc->win_size); 606 port->rxwin = FEPWIN | 607 (((bc->rseg - sc->mem_seg) << 4) / sc->win_size); 608 } 609 port->txbufsize = bc->tmax + 1; 610 port->rxbufsize = bc->rmax + 1; 611 612 lowwater = port->txbufsize >> 2; 613 if (lowwater > 1024) 614 lowwater = 1024; 615 sc->setwin(sc, 0); 616 fepcmd_w(port, STXLWATER, lowwater, 10); 617 fepcmd_w(port, SRXLWATER, port->rxbufsize >> 2, 10); 618 fepcmd_w(port, SRXHWATER, (3 * port->rxbufsize) >> 2, 10); 619 620 bc->edelay = 100; 621 port->dtr_wait = 3 * hz; 622 623 /* 624 * We don't use all the flags from <sys/ttydefaults.h> since 625 * they are only relevant for logins. It's important to have 626 * echo off initially so that the line doesn't start blathering 627 * before the echo flag can be turned off. 628 */ 629 port->it_in.c_iflag = 0; 630 port->it_in.c_oflag = 0; 631 port->it_in.c_cflag = TTYDEF_CFLAG; 632 port->it_in.c_lflag = 0; 633 termioschars(&port->it_in); 634 port->it_in.c_ispeed = port->it_in.c_ospeed = digidefaultrate; 635 port->it_out = port->it_in; 636 port->send_ring = 1; /* Default action on signal RI */ 637 638 port->dev[0] = make_dev(&digi_sw, (sc->res.unit << 16) + i, 639 UID_ROOT, GID_WHEEL, 0600, "ttyD%d.%d", sc->res.unit, i); 640 port->dev[1] = make_dev(&digi_sw, ((sc->res.unit << 16) + i) | 641 CONTROL_INIT_STATE, UID_ROOT, GID_WHEEL, 642 0600, "ttyiD%d.%d", sc->res.unit, i); 643 port->dev[2] = make_dev(&digi_sw, ((sc->res.unit << 16) + i) | 644 CONTROL_LOCK_STATE, UID_ROOT, GID_WHEEL, 645 0600, "ttylD%d.%d", sc->res.unit, i); 646 port->dev[3] = make_dev(&digi_sw, ((sc->res.unit << 16) + i) | 647 CALLOUT_MASK, UID_UUCP, GID_DIALER, 648 0660, "cuaD%d.%d", sc->res.unit, i); 649 port->dev[4] = make_dev(&digi_sw, ((sc->res.unit << 16) + i) | 650 CALLOUT_MASK | CONTROL_INIT_STATE, UID_UUCP, GID_DIALER, 651 0660, "cuaiD%d.%d", sc->res.unit, i); 652 port->dev[5] = make_dev(&digi_sw, ((sc->res.unit << 16) + i) | 653 CALLOUT_MASK | CONTROL_LOCK_STATE, UID_UUCP, GID_DIALER, 654 0660, "cualD%d.%d", sc->res.unit, i); 655 } 656 657 sc->hidewin(sc); 658 sc->inttest = timeout(digi_int_test, sc, hz); 659 /* fepcmd_w(&sc->ports[0], 0xff, 0, 0); */ 660 sc->status = DIGI_STATUS_ENABLED; 661 662 return (0); 663} 664 665static int 666digimctl(struct digi_p *port, int bits, int how) 667{ 668 int mstat; 669 670 if (how == DMGET) { 671 port->sc->setwin(port->sc, 0); 672 mstat = port->bc->mstat; 673 port->sc->hidewin(port->sc); 674 bits = TIOCM_LE; 675 if (mstat & port->sc->csigs->rts) 676 bits |= TIOCM_RTS; 677 if (mstat & port->sc->csigs->cd) 678 bits |= TIOCM_CD; 679 if (mstat & port->sc->csigs->dsr) 680 bits |= TIOCM_DSR; 681 if (mstat & port->sc->csigs->cts) 682 bits |= TIOCM_CTS; 683 if (mstat & port->sc->csigs->ri) 684 bits |= TIOCM_RI; 685 if (mstat & port->sc->csigs->dtr) 686 bits |= TIOCM_DTR; 687 return (bits); 688 } 689 690 /* Only DTR and RTS may be set */ 691 mstat = 0; 692 if (bits & TIOCM_DTR) 693 mstat |= port->sc->csigs->dtr; 694 if (bits & TIOCM_RTS) 695 mstat |= port->sc->csigs->rts; 696 697 switch (how) { 698 case DMSET: 699 fepcmd_b(port, SETMODEM, mstat, ~mstat, 0); 700 break; 701 case DMBIS: 702 fepcmd_b(port, SETMODEM, mstat, 0, 0); 703 break; 704 case DMBIC: 705 fepcmd_b(port, SETMODEM, 0, mstat, 0); 706 break; 707 } 708 709 return (0); 710} 711 712static void 713digi_disc_optim(struct tty *tp, struct termios *t, struct digi_p *port) 714{ 715 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP)) && 716 (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) && 717 (!(t->c_iflag & PARMRK) || 718 (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) && 719 !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) && 720 linesw[tp->t_line].l_rint == ttyinput) 721 tp->t_state |= TS_CAN_BYPASS_L_RINT; 722 else 723 tp->t_state &= ~TS_CAN_BYPASS_L_RINT; 724} 725 726int 727digiopen(dev_t dev, int flag, int mode, struct proc *p) 728{ 729 struct digi_softc *sc; 730 struct tty *tp; 731 int unit; 732 int pnum; 733 struct digi_p *port; 734 int s; 735 int error, mynor; 736 volatile struct board_chan *bc; 737 738 error = 0; 739 mynor = minor(dev); 740 unit = MINOR_TO_UNIT(minor(dev)); 741 pnum = MINOR_TO_PORT(minor(dev)); 742 743 sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit); 744 if (!sc) 745 return (ENXIO); 746 747 if (sc->status != DIGI_STATUS_ENABLED) { 748 DLOG(DIGIDB_OPEN, (sc->dev, "Cannot open a disabled card\n")); 749 return (ENXIO); 750 } 751 if (pnum >= sc->numports) { 752 DLOG(DIGIDB_OPEN, (sc->dev, "port%d: Doesn't exist\n", pnum)); 753 return (ENXIO); 754 } 755 if (mynor & (CTRL_DEV | CONTROL_MASK)) { 756 sc->opencnt++; 757 return (0); 758 } 759 port = &sc->ports[pnum]; 760 tp = dev->si_tty = port->tp; 761 bc = port->bc; 762 763 s = spltty(); 764 765open_top: 766 while (port->status & DIGI_DTR_OFF) { 767 port->wopeners++; 768 error = tsleep(&port->dtr_wait, TTIPRI | PCATCH, "digidtr", 0); 769 port->wopeners--; 770 if (error) 771 goto out; 772 } 773 774 if (tp->t_state & TS_ISOPEN) { 775 /* 776 * The device is open, so everything has been initialized. 777 * Handle conflicts. 778 */ 779 if (mynor & CALLOUT_MASK) { 780 if (!port->active_out) { 781 error = EBUSY; 782 DLOG(DIGIDB_OPEN, (sc->dev, "port %d:" 783 " BUSY error = %d\n", pnum, error)); 784 goto out; 785 } 786 } else if (port->active_out) { 787 if (flag & O_NONBLOCK) { 788 error = EBUSY; 789 DLOG(DIGIDB_OPEN, (sc->dev, 790 "port %d: BUSY error = %d\n", pnum, error)); 791 goto out; 792 } 793 port->wopeners++; 794 error = tsleep(&port->active_out, TTIPRI | PCATCH, 795 "digibi", 0); 796 port->wopeners--; 797 if (error != 0) { 798 DLOG(DIGIDB_OPEN, (sc->dev, 799 "port %d: tsleep(digibi) error = %d\n", 800 pnum, error)); 801 goto out; 802 } 803 goto open_top; 804 } 805 if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) { 806 error = EBUSY; 807 goto out; 808 } 809 } else { 810 /* 811 * The device isn't open, so there are no conflicts. 812 * Initialize it. Initialization is done twice in many 813 * cases: to preempt sleeping callin opens if we are callout, 814 * and to complete a callin open after DCD rises. 815 */ 816 tp->t_oproc = digistart; 817 tp->t_param = digiparam; 818 tp->t_stop = digistop; 819 tp->t_dev = dev; 820 tp->t_termios = (mynor & CALLOUT_MASK) ? 821 port->it_out : port->it_in; 822 sc->setwin(sc, 0); 823 824 bc->rout = bc->rin; /* clear input queue */ 825 bc->idata = 1; 826 bc->iempty = 1; 827 bc->ilow = 1; 828 bc->mint = port->sc->csigs->cd | port->sc->csigs->ri; 829 bc->tin = bc->tout; 830 port->wopeners++; /* XXX required ? */ 831 error = digiparam(tp, &tp->t_termios); 832 port->wopeners--; 833 834 if (error != 0) { 835 DLOG(DIGIDB_OPEN, (sc->dev, 836 "port %d: cxpparam error = %d\n", pnum, error)); 837 goto out; 838 } 839 ttsetwater(tp); 840 841 /* handle fake and initial DCD for callout devices */ 842 843 if (bc->mstat & port->sc->csigs->cd || mynor & CALLOUT_MASK) 844 linesw[tp->t_line].l_modem(tp, 1); 845 } 846 847 /* Wait for DCD if necessary */ 848 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) && 849 !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { 850 port->wopeners++; 851 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "digidcd", 0); 852 port->wopeners--; 853 if (error != 0) { 854 DLOG(DIGIDB_OPEN, (sc->dev, 855 "port %d: tsleep(digidcd) error = %d\n", 856 pnum, error)); 857 goto out; 858 } 859 goto open_top; 860 } 861 error = linesw[tp->t_line].l_open(dev, tp); 862 DLOG(DIGIDB_OPEN, (sc->dev, "port %d: l_open error = %d\n", 863 pnum, error)); 864 865 digi_disc_optim(tp, &tp->t_termios, port); 866 867 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) 868 port->active_out = TRUE; 869 870 if (tp->t_state & TS_ISOPEN) 871 sc->opencnt++; 872out: 873 splx(s); 874 875 if (!(tp->t_state & TS_ISOPEN)) 876 digihardclose(port); 877 878 DLOG(DIGIDB_OPEN, (sc->dev, "port %d: open() returns %d\n", 879 pnum, error)); 880 881 return (error); 882} 883 884int 885digiclose(dev_t dev, int flag, int mode, struct proc *p) 886{ 887 int mynor; 888 struct tty *tp; 889 int unit, pnum; 890 struct digi_softc *sc; 891 struct digi_p *port; 892 int s; 893 894 mynor = minor(dev); 895 unit = MINOR_TO_UNIT(mynor); 896 pnum = MINOR_TO_PORT(mynor); 897 898 sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit); 899 KASSERT(sc, ("digi%d: softc not allocated in digiclose\n", unit)); 900 901 if (mynor & (CTRL_DEV | CONTROL_MASK)) { 902 sc->opencnt--; 903 return (0); 904 } 905 906 port = sc->ports + pnum; 907 tp = port->tp; 908 909 DLOG(DIGIDB_CLOSE, (sc->dev, "port %d: closing\n", pnum)); 910 911 s = spltty(); 912 linesw[tp->t_line].l_close(tp, flag); 913 digi_disc_optim(tp, &tp->t_termios, port); 914 digistop(tp, FREAD | FWRITE); 915 digihardclose(port); 916 ttyclose(tp); 917 if (--sc->opencnt == 0) 918 splx(s); 919 return (0); 920} 921 922static void 923digidtrwakeup(void *chan) 924{ 925 struct digi_p *port = chan; 926 927 port->status &= ~DIGI_DTR_OFF; 928 wakeup(&port->dtr_wait); 929 port->wopeners--; 930} 931 932static void 933digihardclose(struct digi_p *port) 934{ 935 volatile struct board_chan *bc; 936 int s; 937 938 bc = port->bc; 939 940 s = spltty(); 941 port->sc->setwin(port->sc, 0); 942 bc->idata = 0; 943 bc->iempty = 0; 944 bc->ilow = 0; 945 bc->mint = 0; 946 if ((port->tp->t_cflag & HUPCL) || 947 (!port->active_out && !(bc->mstat & port->sc->csigs->cd) && 948 !(port->it_in.c_cflag & CLOCAL)) || 949 !(port->tp->t_state & TS_ISOPEN)) { 950 digimctl(port, TIOCM_DTR | TIOCM_RTS, DMBIC); 951 if (port->dtr_wait != 0) { 952 /* Schedule a wakeup of any callin devices */ 953 port->wopeners++; 954 timeout(&digidtrwakeup, port, port->dtr_wait); 955 port->status |= DIGI_DTR_OFF; 956 } 957 } 958 port->active_out = FALSE; 959 wakeup(&port->active_out); 960 wakeup(TSA_CARR_ON(port->tp)); 961 splx(s); 962} 963 964int 965digiread(dev_t dev, struct uio *uio, int flag) 966{ 967 int mynor; 968 struct tty *tp; 969 int error, unit, pnum; 970 struct digi_softc *sc; 971 972 mynor = minor(dev); 973 if (mynor & CONTROL_MASK) 974 return (ENODEV); 975 976 unit = MINOR_TO_UNIT(mynor); 977 pnum = MINOR_TO_PORT(mynor); 978 979 sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit); 980 KASSERT(sc, ("digi%d: softc not allocated in digiclose\n", unit)); 981 tp = &sc->ttys[pnum]; 982 983 error = linesw[tp->t_line].l_read(tp, uio, flag); 984 DLOG(DIGIDB_READ, (sc->dev, "port %d: read() returns %d\n", 985 pnum, error)); 986 987 return (error); 988} 989 990int 991digiwrite(dev_t dev, struct uio *uio, int flag) 992{ 993 int mynor; 994 struct tty *tp; 995 int error, unit, pnum; 996 struct digi_softc *sc; 997 998 mynor = minor(dev); 999 if (mynor & CONTROL_MASK) 1000 return (ENODEV); 1001 1002 unit = MINOR_TO_UNIT(mynor); 1003 pnum = MINOR_TO_PORT(mynor); 1004 1005 sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit); 1006 KASSERT(sc, ("digi%d: softc not allocated in digiclose\n", unit)); 1007 tp = &sc->ttys[pnum]; 1008 1009 error = linesw[tp->t_line].l_write(tp, uio, flag); 1010 DLOG(DIGIDB_WRITE, (sc->dev, "port %d: write() returns %d\n", 1011 pnum, error)); 1012 1013 return (error); 1014} 1015 1016/* 1017 * Load module "digi_<mod>.ko" and look for a symbol called digi_mod_<mod>. 1018 * 1019 * Populate sc->bios, sc->fep, and sc->link from this data. 1020 * 1021 * sc->fep.data, sc->bios.data and sc->link.data are malloc()d according 1022 * to their respective sizes. 1023 * 1024 * The module is unloaded when we're done. 1025 */ 1026static int 1027digi_loadmoduledata(struct digi_softc *sc) 1028{ 1029 struct digi_mod *digi_mod; 1030 linker_file_t lf; 1031 char *modfile, *sym; 1032 caddr_t symptr; 1033 int res, symlen; 1034 1035 KASSERT(sc->bios.data == NULL, ("Uninitialised BIOS variable")); 1036 KASSERT(sc->fep.data == NULL, ("Uninitialised FEP variable")); 1037 KASSERT(sc->link.data == NULL, ("Uninitialised LINK variable")); 1038 KASSERT(sc->module != NULL, ("Uninitialised module name")); 1039 1040 /*- 1041 * XXX: It'd be nice to have something like linker_search_path() 1042 * here. For the moment we hardcode things - the comments 1043 * in linker_load_module() before the call to 1044 * linker_search_path() suggests that ``there will be a 1045 * system...''. 1046 */ 1047 modfile = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 1048 snprintf(modfile, MAXPATHLEN, "/boot/kernel/digi_%s.ko", sc->module); 1049 if ((res = linker_load_file(modfile, &lf)) != 0) 1050 printf("%s: Failed %d to load module\n", modfile, res); 1051 free(modfile, M_TEMP); 1052 if (res != 0) 1053 return (res); 1054 1055 symlen = strlen(sc->module) + 10; 1056 sym = malloc(symlen, M_TEMP, M_WAITOK); 1057 snprintf(sym, symlen, "digi_mod_%s", sc->module); 1058 if ((symptr = linker_file_lookup_symbol(lf, sym, 0)) == NULL) 1059 printf("digi_%s.ko: Symbol `%s' not found\n", sc->module, sym); 1060 free(sym, M_TEMP); 1061 1062 digi_mod = (struct digi_mod *)symptr; 1063 if (digi_mod->dm_version != DIGI_MOD_VERSION) { 1064 printf("digi_%s.ko: Invalid version %d (need %d)\n", 1065 sc->module, digi_mod->dm_version, DIGI_MOD_VERSION); 1066 linker_file_unload(lf); 1067 return (EINVAL); 1068 } 1069 1070 sc->bios.size = digi_mod->dm_bios.size; 1071 if (sc->bios.size != 0 && digi_mod->dm_bios.data != NULL) { 1072 sc->bios.data = malloc(sc->bios.size, M_TTYS, M_WAIT); 1073 bcopy(digi_mod->dm_bios.data, sc->bios.data, sc->bios.size); 1074 } 1075 1076 sc->fep.size = digi_mod->dm_fep.size; 1077 if (sc->fep.size != 0 && digi_mod->dm_fep.data != NULL) { 1078 sc->fep.data = malloc(sc->fep.size, M_TTYS, M_WAIT); 1079 bcopy(digi_mod->dm_fep.data, sc->fep.data, sc->fep.size); 1080 } 1081 1082 sc->link.size = digi_mod->dm_link.size; 1083 if (sc->link.size != 0 && digi_mod->dm_link.data != NULL) { 1084 sc->link.data = malloc(sc->link.size, M_TTYS, M_WAIT); 1085 bcopy(digi_mod->dm_link.data, sc->link.data, sc->link.size); 1086 } 1087 1088 linker_file_unload(lf); 1089 1090 return (0); 1091} 1092 1093static int 1094digiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) 1095{ 1096 int unit, pnum, mynor, error, s; 1097 struct digi_softc *sc; 1098 struct digi_p *port; 1099 struct tty *tp; 1100#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1101 int oldcmd; 1102 struct termios term; 1103#endif 1104 1105 mynor = minor(dev); 1106 unit = MINOR_TO_UNIT(mynor); 1107 pnum = MINOR_TO_PORT(mynor); 1108 1109 sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit); 1110 KASSERT(sc, ("digi%d: softc not allocated in digiioctl\n", unit)); 1111 1112 if (sc->status == DIGI_STATUS_DISABLED) 1113 return (ENXIO); 1114 1115 if (mynor & CTRL_DEV) { 1116 switch (cmd) { 1117 case DIGIIO_DEBUG: 1118#ifdef DEBUG 1119 digi_debug = *(int *)data; 1120 return (0); 1121#else 1122 device_printf(sc->dev, "DEBUG not defined\n"); 1123 return (ENXIO); 1124#endif 1125 case DIGIIO_REINIT: 1126 digi_loadmoduledata(sc); 1127 error = digi_init(sc); 1128 digi_freemoduledata(sc); 1129 return (error); 1130 1131 case DIGIIO_MODEL: 1132 *(digiModel_t *)data = sc->model; 1133 return (0); 1134 1135 case DIGIIO_IDENT: 1136 return (copyout(sc->name, *(char **)data, 1137 strlen(sc->name) + 1)); 1138 } 1139 } 1140 1141 if (pnum >= sc->numports) 1142 return (ENXIO); 1143 1144 port = sc->ports + pnum; 1145 if (!(port->status & ENABLED)) 1146 return (ENXIO); 1147 1148 tp = port->tp; 1149 1150 if (mynor & CONTROL_MASK) { 1151 struct termios *ct; 1152 1153 switch (mynor & CONTROL_MASK) { 1154 case CONTROL_INIT_STATE: 1155 ct = (mynor & CALLOUT_MASK) ? 1156 &port->it_out : &port->it_in; 1157 break; 1158 case CONTROL_LOCK_STATE: 1159 ct = (mynor & CALLOUT_MASK) ? 1160 &port->lt_out : &port->lt_in; 1161 break; 1162 default: 1163 return (ENODEV); /* /dev/nodev */ 1164 } 1165 1166 switch (cmd) { 1167 case TIOCSETA: 1168 error = suser(p); 1169 if (error != 0) 1170 return (error); 1171 *ct = *(struct termios *)data; 1172 1173 return (0); 1174 case TIOCGETA: 1175 *(struct termios *)data = *ct; 1176 1177 return (0); 1178 case TIOCGETD: 1179 *(int *)data = TTYDISC; 1180 return (0); 1181 case TIOCGWINSZ: 1182 bzero(data, sizeof(struct winsize)); 1183 return (0); 1184 default: 1185 return (ENOTTY); 1186 } 1187 } 1188 tp = port->tp; 1189#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1190 term = tp->t_termios; 1191 oldcmd = cmd; 1192 error = ttsetcompat(tp, &cmd, data, &term); 1193 if (error != 0) 1194 return (error); 1195 if (cmd != oldcmd) 1196 data = (caddr_t) & term; 1197#endif 1198 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { 1199 int cc; 1200 struct termios *dt; 1201 struct termios *lt; 1202 1203 dt = (struct termios *)data; 1204 lt = (mynor & CALLOUT_MASK) ? &port->lt_out : &port->lt_in; 1205 1206 dt->c_iflag = 1207 (tp->t_iflag & lt->c_iflag) | (dt->c_iflag & ~lt->c_iflag); 1208 dt->c_oflag = 1209 (tp->t_oflag & lt->c_oflag) | (dt->c_oflag & ~lt->c_oflag); 1210 dt->c_cflag = 1211 (tp->t_cflag & lt->c_cflag) | (dt->c_cflag & ~lt->c_cflag); 1212 dt->c_lflag = 1213 (tp->t_lflag & lt->c_lflag) | (dt->c_lflag & ~lt->c_lflag); 1214 port->c_iflag = dt->c_iflag & (IXOFF | IXON | IXANY); 1215 dt->c_iflag &= ~(IXOFF | IXON | IXANY); 1216 for (cc = 0; cc < NCCS; ++cc) 1217 if (lt->c_cc[cc] != 0) 1218 dt->c_cc[cc] = tp->t_cc[cc]; 1219 if (lt->c_ispeed != 0) 1220 dt->c_ispeed = tp->t_ispeed; 1221 if (lt->c_ospeed != 0) 1222 dt->c_ospeed = tp->t_ospeed; 1223 } 1224 error = linesw[tp->t_line].l_ioctl(tp, cmd, data, flag, p); 1225 if (error == 0 && cmd == TIOCGETA) 1226 ((struct termios *)data)->c_iflag |= port->c_iflag; 1227 1228 if (error >= 0 && error != ENOIOCTL) 1229 return (error); 1230 s = spltty(); 1231 error = ttioctl(tp, cmd, data, flag); 1232 if (error == 0 && cmd == TIOCGETA) 1233 ((struct termios *)data)->c_iflag |= port->c_iflag; 1234 1235 digi_disc_optim(tp, &tp->t_termios, port); 1236 if (error >= 0 && error != ENOIOCTL) { 1237 splx(s); 1238 return (error); 1239 } 1240 sc->setwin(sc, 0); 1241 switch (cmd) { 1242 case DIGIIO_RING: 1243 port->send_ring = *(u_char *)data; 1244 break; 1245 case TIOCSBRK: 1246 /* 1247 * now it sends 250 millisecond break because I don't know 1248 * how to send an infinite break 1249 */ 1250 fepcmd_w(port, SENDBREAK, 250, 10); 1251 break; 1252 case TIOCCBRK: 1253 /* now it's empty */ 1254 break; 1255 case TIOCSDTR: 1256 digimctl(port, TIOCM_DTR, DMBIS); 1257 break; 1258 case TIOCCDTR: 1259 digimctl(port, TIOCM_DTR, DMBIC); 1260 break; 1261 case TIOCMSET: 1262 digimctl(port, *(int *)data, DMSET); 1263 break; 1264 case TIOCMBIS: 1265 digimctl(port, *(int *)data, DMBIS); 1266 break; 1267 case TIOCMBIC: 1268 digimctl(port, *(int *)data, DMBIC); 1269 break; 1270 case TIOCMGET: 1271 *(int *)data = digimctl(port, 0, DMGET); 1272 break; 1273 case TIOCMSDTRWAIT: 1274 error = suser(p); 1275 if (error != 0) { 1276 splx(s); 1277 return (error); 1278 } 1279 port->dtr_wait = *(int *)data *hz / 100; 1280 1281 break; 1282 case TIOCMGDTRWAIT: 1283 *(int *)data = port->dtr_wait * 100 / hz; 1284 break; 1285#ifdef DIGI_INTERRUPT 1286 case TIOCTIMESTAMP: 1287 *(struct timeval *)data = sc->intr_timestamp; 1288 1289 break; 1290#endif 1291 default: 1292 splx(s); 1293 return (ENOTTY); 1294 } 1295 splx(s); 1296 return (0); 1297} 1298 1299static int 1300digiparam(struct tty *tp, struct termios *t) 1301{ 1302 int mynor; 1303 int unit; 1304 int pnum; 1305 struct digi_softc *sc; 1306 struct digi_p *port; 1307 int cflag; 1308 int iflag; 1309 int hflow; 1310 int s; 1311 int window; 1312 1313 mynor = minor(tp->t_dev); 1314 unit = MINOR_TO_UNIT(mynor); 1315 pnum = MINOR_TO_PORT(mynor); 1316 1317 sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit); 1318 KASSERT(sc, ("digi%d: softc not allocated in digiparam\n", unit)); 1319 1320 port = &sc->ports[pnum]; 1321 1322 DLOG(DIGIDB_SET, (sc->dev, "port%d: setting parameters\n", pnum)); 1323 1324 if (t->c_ispeed == 0) 1325 t->c_ispeed = t->c_ospeed; 1326 1327 cflag = ttspeedtab(t->c_ospeed, digispeedtab); 1328 1329 if (cflag < 0 || (cflag > 0 && t->c_ispeed != t->c_ospeed)) 1330 return (EINVAL); 1331 1332 s = splclock(); 1333 1334 window = sc->window; 1335 sc->setwin(sc, 0); 1336 1337 if (cflag == 0) { /* hangup */ 1338 DLOG(DIGIDB_SET, (sc->dev, "port%d: hangup\n", pnum)); 1339 digimctl(port, TIOCM_DTR | TIOCM_RTS, DMBIC); 1340 } else { 1341 digimctl(port, TIOCM_DTR | TIOCM_RTS, DMBIS); 1342 1343 DLOG(DIGIDB_SET, (sc->dev, "port%d: CBAUD = %d\n", pnum, 1344 cflag)); 1345 1346#if 0 1347 /* convert flags to sysV-style values */ 1348 if (t->c_cflag & PARODD) 1349 cflag |= 0x0200; 1350 if (t->c_cflag & PARENB) 1351 cflag |= 0x0100; 1352 if (t->c_cflag & CSTOPB) 1353 cflag |= 0x0080; 1354#else 1355 /* convert flags to sysV-style values */ 1356 if (t->c_cflag & PARODD) 1357 cflag |= FEP_PARODD; 1358 if (t->c_cflag & PARENB) 1359 cflag |= FEP_PARENB; 1360 if (t->c_cflag & CSTOPB) 1361 cflag |= FEP_CSTOPB; 1362 if (t->c_cflag & CLOCAL) 1363 cflag |= FEP_CLOCAL; 1364#endif 1365 1366 cflag |= (t->c_cflag & CSIZE) >> 4; 1367 DLOG(DIGIDB_SET, (sc->dev, "port%d: CFLAG = 0x%x\n", pnum, 1368 cflag)); 1369 fepcmd_w(port, SETCFLAGS, (unsigned)cflag, 0); 1370 } 1371 1372 iflag = 1373 t->c_iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP); 1374 if (port->c_iflag & IXON) 1375 iflag |= 0x400; 1376 if (port->c_iflag & IXANY) 1377 iflag |= 0x800; 1378 if (port->c_iflag & IXOFF) 1379 iflag |= 0x1000; 1380 1381 DLOG(DIGIDB_SET, (sc->dev, "port%d: set iflag = 0x%x\n", pnum, iflag)); 1382 fepcmd_w(port, SETIFLAGS, (unsigned)iflag, 0); 1383 1384 hflow = 0; 1385 if (t->c_cflag & CDTR_IFLOW) 1386 hflow |= sc->csigs->dtr; 1387 if (t->c_cflag & CRTS_IFLOW) 1388 hflow |= sc->csigs->rts; 1389 if (t->c_cflag & CCTS_OFLOW) 1390 hflow |= sc->csigs->cts; 1391 if (t->c_cflag & CDSR_OFLOW) 1392 hflow |= sc->csigs->dsr; 1393 if (t->c_cflag & CCAR_OFLOW) 1394 hflow |= sc->csigs->cd; 1395 1396 DLOG(DIGIDB_SET, (sc->dev, "port%d: set hflow = 0x%x\n", pnum, hflow)); 1397 fepcmd_w(port, SETHFLOW, 0xff00 | (unsigned)hflow, 0); 1398 1399 DLOG(DIGIDB_SET, (sc->dev, "port%d: set startc(0x%x), stopc(0x%x)\n", 1400 pnum, t->c_cc[VSTART], t->c_cc[VSTOP])); 1401 fepcmd_b(port, SONOFFC, t->c_cc[VSTART], t->c_cc[VSTOP], 0); 1402 1403 if (sc->window != 0) 1404 sc->towin(sc, 0); 1405 if (window != 0) 1406 sc->towin(sc, window); 1407 splx(s); 1408 1409 return (0); 1410} 1411 1412static void 1413digi_intr(void *vp) 1414{ 1415 struct digi_p *port; 1416 char *cxcon; 1417 struct digi_softc *sc; 1418 int ehead, etail; 1419 volatile struct board_chan *bc; 1420 struct tty *tp; 1421 int head, tail; 1422 int wrapmask; 1423 int size, window; 1424 struct event { 1425 u_char pnum; 1426 u_char event; 1427 u_char mstat; 1428 u_char lstat; 1429 } event; 1430 1431 sc = vp; 1432 1433 if (sc->status != DIGI_STATUS_ENABLED) { 1434 DLOG(DIGIDB_IRQ, (sc->dev, "interrupt on disabled board !\n")); 1435 return; 1436 } 1437 1438#ifdef DIGI_INTERRUPT 1439 microtime(&sc->intr_timestamp); 1440#endif 1441 1442 window = sc->window; 1443 sc->setwin(sc, 0); 1444 1445 if (sc->model >= PCXEM && W(sc->vmem + 0xd00)) { 1446 struct con_bios *con = con_bios_list; 1447 register u_char *ptr; 1448 1449 ptr = sc->vmem + W(sc->vmem + 0xd00); 1450 while (con) { 1451 if (ptr[1] && W(ptr + 2) == W(con->bios + 2)) 1452 /* Not first block -- exact match */ 1453 break; 1454 1455 if (W(ptr + 4) >= W(con->bios + 4) && 1456 W(ptr + 4) <= W(con->bios + 6)) 1457 /* Initial search concetrator BIOS */ 1458 break; 1459 } 1460 1461 if (con == NULL) { 1462 log(LOG_ERR, "digi%d: wanted bios LREV = 0x%04x" 1463 " not found!\n", sc->res.unit, W(ptr + 4)); 1464 W(ptr + 10) = 0; 1465 W(sc->vmem + 0xd00) = 0; 1466 goto eoi; 1467 } 1468 cxcon = con->bios; 1469 W(ptr + 4) = W(cxcon + 4); 1470 W(ptr + 6) = W(cxcon + 6); 1471 if (ptr[1] == 0) 1472 W(ptr + 2) = W(cxcon + 2); 1473 W(ptr + 8) = (ptr[1] << 6) + W(cxcon + 8); 1474 size = W(cxcon + 10) - (ptr[1] << 10); 1475 if (size <= 0) { 1476 W(ptr + 8) = W(cxcon + 8); 1477 W(ptr + 10) = 0; 1478 } else { 1479 if (size > 1024) 1480 size = 1024; 1481 W(ptr + 10) = size; 1482 bcopy(cxcon + (ptr[1] << 10), ptr + 12, size); 1483 } 1484 W(sc->vmem + 0xd00) = 0; 1485 goto eoi; 1486 } 1487 1488 ehead = sc->gdata->ein; 1489 etail = sc->gdata->eout; 1490 if (ehead == etail) { 1491#ifdef DEBUG 1492 sc->intr_count++; 1493 if (sc->intr_count % 6000 == 0) { 1494 DLOG(DIGIDB_IRQ, (sc->dev, 1495 "6000 useless polls %x %x\n", ehead, etail)); 1496 sc->intr_count = 0; 1497 } 1498#endif 1499 goto eoi; 1500 } 1501 while (ehead != etail) { 1502 event = *(volatile struct event *)(sc->memevent + etail); 1503 1504 etail = (etail + 4) & sc->gdata->imax; 1505 1506 if (event.pnum >= sc->numports) { 1507 log(LOG_ERR, "digi%d: port %d: got event" 1508 " on nonexisting port\n", sc->res.unit, 1509 event.pnum); 1510 continue; 1511 } 1512 port = &sc->ports[event.pnum]; 1513 bc = port->bc; 1514 tp = port->tp; 1515 1516 if (!(tp->t_state & TS_ISOPEN) && !port->wopeners) { 1517 DLOG(DIGIDB_IRQ, (sc->dev, 1518 "port %d: event 0x%x on closed port\n", 1519 event.pnum, event.event)); 1520 bc->rout = bc->rin; 1521 bc->idata = 0; 1522 bc->iempty = 0; 1523 bc->ilow = 0; 1524 bc->mint = 0; 1525 continue; 1526 } 1527 if (event.event & ~ALL_IND) 1528 log(LOG_ERR, "digi%d: port%d: ? event 0x%x mstat 0x%x" 1529 " lstat 0x%x\n", sc->res.unit, event.pnum, 1530 event.event, event.mstat, event.lstat); 1531 1532 if (event.event & DATA_IND) { 1533 DLOG(DIGIDB_IRQ, (sc->dev, "port %d: DATA_IND\n", 1534 event.pnum)); 1535 wrapmask = port->rxbufsize - 1; 1536 head = bc->rin; 1537 tail = bc->rout; 1538 1539 size = 0; 1540 if (!(tp->t_state & TS_ISOPEN)) { 1541 bc->rout = head; 1542 goto end_of_data; 1543 } 1544 while (head != tail) { 1545 int top; 1546 1547 DLOG(DIGIDB_INT, (sc->dev, 1548 "port %d: p rx head = %d tail = %d\n", 1549 event.pnum, head, tail)); 1550 top = (head > tail) ? head : wrapmask + 1; 1551 sc->towin(sc, port->rxwin); 1552 size = top - tail; 1553 if (tp->t_state & TS_CAN_BYPASS_L_RINT) { 1554 size = b_to_q((char *)port->rxbuf + 1555 tail, size, &tp->t_rawq); 1556 tail = top - size; 1557 ttwakeup(tp); 1558 } else for (; tail < top;) { 1559 linesw[tp->t_line]. 1560 l_rint(port->rxbuf[tail], tp); 1561 sc->towin(sc, port->rxwin); 1562 size--; 1563 tail++; 1564 if (tp->t_state & TS_TBLOCK) 1565 break; 1566 } 1567 tail &= wrapmask; 1568 sc->setwin(sc, 0); 1569 bc->rout = tail; 1570 head = bc->rin; 1571 if (size) 1572 break; 1573 } 1574 1575 if (bc->orun) { 1576 CE_RECORD(port, CE_OVERRUN); 1577 log(LOG_ERR, "digi%d: port%d: %s\n", 1578 sc->res.unit, event.pnum, 1579 digi_errortxt(CE_OVERRUN)); 1580 bc->orun = 0; 1581 } 1582end_of_data: 1583 if (size) { 1584 tp->t_state |= TS_TBLOCK; 1585 port->status |= PAUSE_RX; 1586 DLOG(DIGIDB_RX, (sc->dev, "port %d: pause RX\n", 1587 event.pnum)); 1588 } else { 1589 bc->idata = 1; 1590 } 1591 } 1592 1593 if (event.event & MODEMCHG_IND) { 1594 DLOG(DIGIDB_MODEM, (sc->dev, "port %d: MODEMCHG_IND\n", 1595 event.pnum)); 1596 1597 if ((event.mstat ^ event.lstat) & port->sc->csigs->cd) { 1598 sc->hidewin(sc); 1599 linesw[tp->t_line].l_modem 1600 (tp, event.mstat & port->sc->csigs->cd); 1601 sc->setwin(sc, 0); 1602 wakeup(TSA_CARR_ON(tp)); 1603 } 1604 1605 if (event.mstat & sc->csigs->ri) { 1606 DLOG(DIGIDB_RI, (sc->dev, "port %d: RING\n", 1607 event.pnum)); 1608 if (port->send_ring) { 1609 linesw[tp->t_line].l_rint('R', tp); 1610 linesw[tp->t_line].l_rint('I', tp); 1611 linesw[tp->t_line].l_rint('N', tp); 1612 linesw[tp->t_line].l_rint('G', tp); 1613 linesw[tp->t_line].l_rint('\r', tp); 1614 linesw[tp->t_line].l_rint('\n', tp); 1615 } 1616 } 1617 } 1618 if (event.event & BREAK_IND) { 1619 DLOG(DIGIDB_MODEM, (sc->dev, "port %d: BREAK_IND\n", 1620 event.pnum)); 1621 linesw[tp->t_line].l_rint(TTY_BI, tp); 1622 } 1623 if (event.event & (LOWTX_IND | EMPTYTX_IND)) { 1624 DLOG(DIGIDB_IRQ, (sc->dev, "port %d:%s%s\n", 1625 event.pnum, 1626 event.event & LOWTX_IND ? " LOWTX" : "", 1627 event.event & EMPTYTX_IND ? " EMPTYTX" : "")); 1628 (*linesw[tp->t_line].l_start)(tp); 1629 } 1630 } 1631 sc->gdata->eout = etail; 1632eoi: 1633 if (sc->window != 0) 1634 sc->towin(sc, 0); 1635 if (window != 0) 1636 sc->towin(sc, window); 1637} 1638 1639static void 1640digistart(struct tty *tp) 1641{ 1642 int unit; 1643 int pnum; 1644 struct digi_p *port; 1645 struct digi_softc *sc; 1646 volatile struct board_chan *bc; 1647 int head, tail; 1648 int size, ocount, totcnt = 0; 1649 int s; 1650 int wmask; 1651 1652 unit = MINOR_TO_UNIT(minor(tp->t_dev)); 1653 pnum = MINOR_TO_PORT(minor(tp->t_dev)); 1654 1655 sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit); 1656 KASSERT(sc, ("digi%d: softc not allocated in digistart\n", unit)); 1657 1658 port = &sc->ports[pnum]; 1659 bc = port->bc; 1660 1661 wmask = port->txbufsize - 1; 1662 1663 s = spltty(); 1664 port->lcc = tp->t_outq.c_cc; 1665 sc->setwin(sc, 0); 1666 if (!(tp->t_state & TS_TBLOCK)) { 1667 if (port->status & PAUSE_RX) { 1668 DLOG(DIGIDB_RX, (sc->dev, "port %d: resume RX\n", 1669 pnum)); 1670 /* 1671 * CAREFUL - braces are needed here if the DLOG is 1672 * optimised out! 1673 */ 1674 } 1675 port->status &= ~PAUSE_RX; 1676 bc->idata = 1; 1677 } 1678 if (!(tp->t_state & TS_TTSTOP) && port->status & PAUSE_TX) { 1679 DLOG(DIGIDB_TX, (sc->dev, "port %d: resume TX\n", pnum)); 1680 port->status &= ~PAUSE_TX; 1681 fepcmd_w(port, RESUMETX, 0, 10); 1682 } 1683 if (tp->t_outq.c_cc == 0) 1684 tp->t_state &= ~TS_BUSY; 1685 else 1686 tp->t_state |= TS_BUSY; 1687 1688 head = bc->tin; 1689 while (tp->t_outq.c_cc != 0) { 1690 tail = bc->tout; 1691 DLOG(DIGIDB_INT, (sc->dev, "port%d: s tx head = %d tail = %d\n", 1692 pnum, head, tail)); 1693 1694 if (head < tail) 1695 size = tail - head - 1; 1696 else { 1697 size = port->txbufsize - head; 1698 if (tail == 0) 1699 size--; 1700 } 1701 1702 if (size == 0) 1703 break; 1704 sc->towin(sc, port->txwin); 1705 ocount = q_to_b(&tp->t_outq, port->txbuf + head, size); 1706 totcnt += ocount; 1707 head += ocount; 1708 head &= wmask; 1709 sc->setwin(sc, 0); 1710 bc->tin = head; 1711 bc->iempty = 1; 1712 bc->ilow = 1; 1713 } 1714 port->lostcc = tp->t_outq.c_cc; 1715 tail = bc->tout; 1716 if (head < tail) 1717 size = port->txbufsize - tail + head; 1718 else 1719 size = head - tail; 1720 1721 port->lbuf = size; 1722 DLOG(DIGIDB_INT, (sc->dev, "port%d: s total cnt = %d\n", pnum, totcnt)); 1723 ttwwakeup(tp); 1724 splx(s); 1725} 1726 1727static void 1728digistop(struct tty *tp, int rw) 1729{ 1730 struct digi_softc *sc; 1731 int unit; 1732 int pnum; 1733 struct digi_p *port; 1734 1735 unit = MINOR_TO_UNIT(minor(tp->t_dev)); 1736 pnum = MINOR_TO_PORT(minor(tp->t_dev)); 1737 1738 sc = (struct digi_softc *)devclass_get_softc(digi_devclass, unit); 1739 KASSERT(sc, ("digi%d: softc not allocated in digistop\n", unit)); 1740 port = sc->ports + pnum; 1741 1742 DLOG(DIGIDB_TX, (sc->dev, "port %d: pause TX\n", pnum)); 1743 port->status |= PAUSE_TX; 1744 fepcmd_w(port, PAUSETX, 0, 10); 1745} 1746 1747static void 1748fepcmd(struct digi_p *port, int cmd, int op1, int ncmds) 1749{ 1750 u_char *mem; 1751 unsigned tail, head; 1752 int count, n; 1753 1754 mem = port->sc->memcmd; 1755 1756 port->sc->setwin(port->sc, 0); 1757 1758 head = port->sc->gdata->cin; 1759 mem[head + 0] = cmd; 1760 mem[head + 1] = port->pnum; 1761 *(ushort *)(mem + head + 2) = op1; 1762 1763 head = (head + 4) & port->sc->gdata->cmax; 1764 port->sc->gdata->cin = head; 1765 1766 for (count = FEPTIMEOUT; count > 0; count--) { 1767 head = port->sc->gdata->cin; 1768 tail = port->sc->gdata->cout; 1769 n = (head - tail) & port->sc->gdata->cmax; 1770 1771 if (n <= ncmds * sizeof(short) * 4) 1772 break; 1773 } 1774 if (count == 0) 1775 log(LOG_ERR, "digi%d: port%d: timeout on FEP command\n", 1776 port->sc->res.unit, port->pnum); 1777} 1778 1779const char * 1780digi_errortxt(int id) 1781{ 1782 static const char *error_desc[] = { 1783 "silo overflow", 1784 "interrupt-level buffer overflow", 1785 "tty-level buffer overflow", 1786 }; 1787 1788 KASSERT(id >= 0 && id < sizeof(error_desc) / sizeof(error_desc[0]), 1789 ("Unexpected digi error id %d\n", id)); 1790 1791 return (error_desc[id]); 1792} 1793 1794int 1795digi_attach(struct digi_softc *sc) 1796{ 1797 sc->res.ctldev = make_dev(&digi_sw, 1798 (sc->res.unit << 16) | CTRL_DEV, UID_ROOT, GID_WHEEL, 1799 0600, "digi%r.ctl", sc->res.unit); 1800 1801 digi_loadmoduledata(sc); 1802 digi_init(sc); 1803 digi_freemoduledata(sc); 1804 1805 return (0); 1806} 1807 1808static int 1809digi_inuse(struct digi_softc *sc) 1810{ 1811 int i; 1812 1813 for (i = 0; i < sc->numports; i++) 1814 if (sc->ttys[i].t_state & TS_ISOPEN) { 1815 DLOG(DIGIDB_INIT, (sc->dev, "port%d: busy\n", i)); 1816 return (1); 1817 } else if (sc->ports[i].wopeners || sc->ports[i].opencnt) { 1818 DLOG(DIGIDB_INIT, (sc->dev, "port%d: blocked in open\n", 1819 i)); 1820 return (1); 1821 } 1822 return (0); 1823} 1824 1825static void 1826digi_free_state(struct digi_softc *sc) 1827{ 1828 int d, i; 1829 1830 /* Blow it all away */ 1831 1832 for (i = 0; i < sc->numports; i++) 1833 for (d = 0; d < 6; d++) 1834 destroy_dev(sc->ports[i].dev[d]); 1835 1836 untimeout(digi_poll, sc, sc->callout); 1837 callout_handle_init(&sc->callout); 1838 untimeout(digi_int_test, sc, sc->inttest); 1839 callout_handle_init(&sc->inttest); 1840 1841 bus_teardown_intr(sc->dev, sc->res.irq, sc->res.irqHandler); 1842#ifdef DIGI_INTERRUPT 1843 if (sc->res.irq != NULL) { 1844 bus_release_resource(dev, SYS_RES_IRQ, sc->res.irqrid, 1845 sc->res.irq); 1846 sc->res.irq = NULL; 1847 } 1848#endif 1849 if (sc->numports) { 1850 KASSERT(sc->ports, ("digi%d: Lost my ports ?", sc->res.unit)); 1851 KASSERT(sc->ttys, ("digi%d: Lost my ttys ?", sc->res.unit)); 1852 FREE(sc->ports, M_TTYS); 1853 sc->ports = NULL; 1854 FREE(sc->ttys, M_TTYS); 1855 sc->ttys = NULL; 1856 sc->numports = 0; 1857 } 1858 1859 sc->status = DIGI_STATUS_NOTINIT; 1860} 1861 1862int 1863digi_detach(device_t dev) 1864{ 1865 struct digi_softc *sc = device_get_softc(dev); 1866 1867 DLOG(DIGIDB_INIT, (sc->dev, "detaching\n")); 1868 1869 /* If we're INIT'd, numports must be 0 */ 1870 KASSERT(sc->numports == 0 || sc->status != DIGI_STATUS_NOTINIT, 1871 ("digi%d: numports(%d) & status(%d) are out of sync", 1872 sc->res.unit, sc->numports, (int)sc->status)); 1873 1874 if (digi_inuse(sc)) 1875 return (EBUSY); 1876 1877 digi_free_state(sc); 1878 1879 destroy_dev(makedev(CDEV_MAJOR, 1880 (sc->res.unit << 16) | CTRL_DEV)); 1881 1882 if (sc->res.mem != NULL) { 1883 bus_release_resource(dev, SYS_RES_MEMORY, sc->res.mrid, 1884 sc->res.mem); 1885 sc->res.mem = NULL; 1886 } 1887 if (sc->res.io != NULL) { 1888 bus_release_resource(dev, SYS_RES_IOPORT, sc->res.iorid, 1889 sc->res.io); 1890 sc->res.io = NULL; 1891 } 1892 1893 return (0); 1894} 1895 1896int 1897digi_shutdown(device_t dev) 1898{ 1899 return (0); 1900} 1901