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