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