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