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