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