1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * Copyright (c) 2011 Bayard G. Bell. All rights reserved. 25 */ 26 27 28 /* 29 * HDLC protocol handler for Z8530 SCC. 30 */ 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/types.h> 35 #include <sys/sysmacros.h> 36 #include <sys/kmem.h> 37 #include <sys/stropts.h> 38 #include <sys/stream.h> 39 #include <sys/strsun.h> 40 #include <sys/stat.h> 41 #include <sys/cred.h> 42 #include <sys/user.h> 43 #include <sys/proc.h> 44 #include <sys/file.h> 45 #include <sys/uio.h> 46 #include <sys/buf.h> 47 #include <sys/mkdev.h> 48 #include <sys/cmn_err.h> 49 #include <sys/errno.h> 50 #include <sys/fcntl.h> 51 52 #include <sys/zsdev.h> 53 #include <sys/ser_sync.h> 54 #include <sys/conf.h> 55 #include <sys/ddi.h> 56 #include <sys/sunddi.h> 57 #include <sys/dlpi.h> 58 59 #define ZSH_TRACING 60 #ifdef ZSH_TRACING 61 #include <sys/vtrace.h> 62 63 /* 64 * Temp tracepoint definitions 65 */ 66 #define TR_ZSH 50 67 68 #define TR_ZSH_TXINT 1 69 #define TR_ZSH_XSINT 2 70 #define TR_ZSH_RXINT 3 71 #define TR_ZSH_SRINT 4 72 73 #define TR_ZSH_WPUT_START 5 74 #define TR_ZSH_WPUT_END 6 75 #define TR_ZSH_START_START 7 76 #define TR_ZSH_START_END 8 77 #define TR_ZSH_SOFT_START 9 78 #define TR_ZSH_SOFT_END 10 79 80 #define TR_ZSH_OPEN 11 81 #define TR_ZSH_CLOSE 12 82 83 #endif /* ZSH_TRACING */ 84 85 /* 86 * Logging definitions 87 */ 88 89 /* 90 * #define ZSH_DEBUG 91 */ 92 #ifdef ZSH_DEBUG 93 94 #ifdef ZS_DEBUG_ALL 95 extern char zs_h_log[]; 96 extern int zs_h_log_n; 97 #define zsh_h_log_add(c) \ 98 { \ 99 if (zs_h_log_n >= ZS_H_LOG_MAX) \ 100 zs_h_log_n = 0; \ 101 zs_h_log[zs_h_log_n++] = 'A' + zs->zs_unit; \ 102 zs_h_log[zs_h_log_n++] = c; \ 103 zs_h_log[zs_h_log_n] = '\0'; \ 104 } 105 #define zsh_h_log_clear 106 #else 107 #define ZSH_H_LOG_MAX 0x8000 108 char zsh_h_log[2][ZSH_H_LOG_MAX +10]; 109 int zsh_h_log_n[2]; 110 #define zsh_h_log_add(c) \ 111 { \ 112 if (zsh_h_log_n[zs->zs_unit] >= ZSH_H_LOG_MAX) \ 113 zsh_h_log_n[zs->zs_unit] = 0; \ 114 zsh_h_log[zs->zs_unit][zsh_h_log_n[zs->zs_unit]++] = c; \ 115 zsh_h_log[zs->zs_unit][zsh_h_log_n[zs->zs_unit]] = '\0'; \ 116 } 117 118 #define zsh_h_log_clear \ 119 { register char *p; \ 120 for (p = &zsh_h_log[zs->zs_unit][ZSH_H_LOG_MAX]; \ 121 p >= &zsh_h_log[zs->zs_unit][0]; p--) \ 122 *p = '\0'; \ 123 zsh_h_log_n[zs->zs_unit] = 0; \ 124 } 125 #endif 126 127 #define ZSH_R0_LOG(r0) { \ 128 if (r0 & ZSRR0_RX_READY) zsh_h_log_add('R'); \ 129 if (r0 & ZSRR0_TIMER) zsh_h_log_add('Z'); \ 130 if (r0 & ZSRR0_TX_READY) zsh_h_log_add('T'); \ 131 if (r0 & ZSRR0_CD) zsh_h_log_add('D'); \ 132 if (r0 & ZSRR0_SYNC) zsh_h_log_add('S'); \ 133 if (r0 & ZSRR0_CTS) zsh_h_log_add('C'); \ 134 if (r0 & ZSRR0_TXUNDER) zsh_h_log_add('U'); \ 135 if (r0 & ZSRR0_BREAK) zsh_h_log_add('B'); \ 136 } 137 #endif 138 139 #ifndef MAXZSH 140 #define MAXZSH 2 141 #define MAXZSHCLONES (80) /* three clone opens per instance */ 142 #endif /* MAXZSH */ 143 144 int maxzsh = MAXZSH; 145 146 int zsh_timer_count = 10; 147 int zsh_default_mru = 1024; 148 149 struct ser_str *zsh_str = NULL; 150 unsigned char zsh_usedminor[MAXZSHCLONES]; 151 152 153 /* 154 * The HDLC protocol 155 */ 156 int zsh_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result); 157 static int zsh_probe(dev_info_t *dev); 158 static int zsh_attach(dev_info_t *dev, ddi_attach_cmd_t cmd); 159 static int zsh_detach(dev_info_t *dev, ddi_detach_cmd_t cmd); 160 static int zsh_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr); 161 static int zsh_close(queue_t *rq, int flag); 162 static void zsh_wput(queue_t *wq, mblk_t *mp); 163 static int zsh_start(struct zscom *zs, struct syncline *zss); 164 static void zsh_ioctl(queue_t *wq, mblk_t *mp); 165 166 static struct module_info hdlc_minfo = { 167 0x5a48, /* module ID number: "ZH" */ 168 "zsh", /* module name */ 169 0, /* minimum packet size accepted */ 170 INFPSZ, /* maximum packet size accepted */ 171 12*1024, /* queue high water mark (bytes) */ 172 4*1024 /* queue low water mark (bytes) */ 173 }; 174 175 static struct qinit hdlc_rinit = { 176 putq, /* input put procedure */ 177 NULL, /* input service procedure */ 178 zsh_open, /* open procedure */ 179 zsh_close, /* close procedure */ 180 NULL, /* reserved */ 181 &hdlc_minfo, /* module info */ 182 NULL /* reserved */ 183 }; 184 185 static struct qinit hdlc_winit = { 186 (int (*)())zsh_wput, /* output put procedure */ 187 NULL, /* output service procedure */ 188 NULL, /* open procedure */ 189 NULL, /* close procedure */ 190 NULL, /* reserved */ 191 &hdlc_minfo, /* module info */ 192 NULL /* reserved */ 193 }; 194 195 struct streamtab hdlctab = { 196 &hdlc_rinit, /* initialize read queue */ 197 &hdlc_winit, /* initialize write queue */ 198 NULL, /* mux read qinit */ 199 NULL /* mux write qinit */ 200 }; 201 202 DDI_DEFINE_STREAM_OPS(zsh_ops, nulldev, zsh_probe, zsh_attach, 203 zsh_detach, nodev, zsh_info, D_MP, &hdlctab, ddi_quiesce_not_supported); 204 205 /* 206 * This is the loadable module wrapper. 207 */ 208 209 #include <sys/errno.h> 210 #include <sys/modctl.h> 211 212 /* 213 * Module linkage information for the kernel. 214 */ 215 216 static struct modldrv modldrv = { 217 &mod_driverops, /* Type of module. This one is a driver */ 218 "Z8530 serial HDLC drv", 219 &zsh_ops, /* our own ops for this module */ 220 }; 221 222 static struct modlinkage modlinkage = { 223 MODREV_1, 224 (void *)&modldrv, 225 NULL 226 }; 227 228 int 229 _init(void) 230 { 231 return (mod_install(&modlinkage)); 232 } 233 234 int 235 _fini(void) 236 { 237 return (mod_remove(&modlinkage)); 238 } 239 240 int 241 _info(struct modinfo *modinfop) 242 { 243 return (mod_info(&modlinkage, modinfop)); 244 } 245 246 247 /* 248 * The HDLC interrupt entry points. 249 */ 250 static void zsh_txint(struct zscom *zs); 251 static void zsh_xsint(struct zscom *zs); 252 static void zsh_rxint(struct zscom *zs); 253 static void zsh_srint(struct zscom *zs); 254 static int zsh_softint(struct zscom *zs); 255 256 struct zsops zsops_hdlc = { 257 zsh_txint, 258 zsh_xsint, 259 zsh_rxint, 260 zsh_srint, 261 zsh_softint, 262 NULL, 263 NULL 264 }; 265 266 static int zsh_program(struct zscom *zs, struct scc_mode *sm); 267 static void zsh_setmstat(struct zscom *zs, int event); 268 static void zsh_rxbad(struct zscom *zs, struct syncline *zss); 269 static void zsh_txbad(struct zscom *zs, struct syncline *zss); 270 static void zsh_watchdog(void *); 271 static void zsh_callback(void *); 272 static int zsh_hdp_ok_or_rts_state(struct zscom *zs, struct syncline *zss); 273 static void zsh_init_port(struct zscom *zs, struct syncline *zss); 274 static int zsh_setmode(struct zscom *zs, struct syncline *zss, 275 struct scc_mode *sm); 276 277 278 /* 279 * The HDLC Driver. 280 */ 281 282 283 /* 284 * Special macros to handle STREAMS operations. 285 * These are required to address memory leakage problems. 286 * WARNING : the macro do NOT call ZSSETSOFT 287 */ 288 289 /* 290 * Should be called holding only the adaptive (zs_excl) mutex. 291 */ 292 #define ZSH_GETBLOCK(zs, allocbcount) \ 293 { \ 294 register int n = ZSH_MAX_RSTANDBY; \ 295 while (--n >= 0) { \ 296 if (!zss->sl_rstandby[n]) { \ 297 if ((zss->sl_rstandby[n] = \ 298 allocb(zss->sl_mru, BPRI_MED)) == NULL) { \ 299 if (zss->sl_bufcid == 0) { \ 300 mutex_enter(zs->zs_excl_hi); \ 301 if (zss->sl_txstate != TX_OFF) { \ 302 mutex_exit(zs->zs_excl_hi); \ 303 zss->sl_bufcid = bufcall(zss->sl_mru, \ 304 BPRI_MED, zsh_callback, zs); \ 305 break; \ 306 } else \ 307 mutex_exit(zs->zs_excl_hi); \ 308 } \ 309 } \ 310 allocbcount--; \ 311 } \ 312 } \ 313 } 314 315 /* 316 * Should be called holding the spin (zs_excl_hi) mutex. 317 */ 318 #define ZSH_ALLOCB(mp) \ 319 { \ 320 register int n = ZSH_MAX_RSTANDBY; \ 321 mp = NULL; \ 322 while (--n >= 0) { \ 323 if ((mp = zss->sl_rstandby[n]) != NULL) { \ 324 zss->sl_rstandby[n] = NULL; \ 325 break; \ 326 } \ 327 } \ 328 } 329 330 #define ZSH_PUTQ(mp) \ 331 { \ 332 register int wptr, rptr; \ 333 wptr = zss->sl_rdone_wptr; \ 334 rptr = zss->sl_rdone_rptr; \ 335 zss->sl_rdone[wptr] = mp; \ 336 if ((wptr) + 1 == ZSH_RDONE_MAX) \ 337 zss->sl_rdone_wptr = wptr = 0; \ 338 else \ 339 zss->sl_rdone_wptr = ++wptr; \ 340 if (wptr == rptr) { /* Should never occur */ \ 341 SCC_BIC(1, ZSWR1_INIT); \ 342 zss->sl_m_error = ENOSR; \ 343 ZSSETSOFT(zs); \ 344 } \ 345 } 346 347 #define ZSH_FREEMSG(mp) \ 348 { \ 349 ZSH_PUTQ(mp); \ 350 } 351 352 353 /* 354 * Should be called holding only the adaptive (zs_excl) mutex. 355 */ 356 #define ZSH_GETQ(mp) \ 357 { \ 358 if (zss->sl_rdone_rptr != zss->sl_rdone_wptr) { \ 359 mp = zss->sl_rdone[zss->sl_rdone_rptr++]; \ 360 if (zss->sl_rdone_rptr == ZSH_RDONE_MAX) \ 361 zss->sl_rdone_rptr = 0; \ 362 } else \ 363 mp = NULL; \ 364 } 365 366 #define ZSH_FLUSHQ \ 367 { \ 368 register mblk_t *tmp; \ 369 for (;;) { \ 370 ZSH_GETQ(tmp); \ 371 if (!(tmp)) \ 372 break; \ 373 freemsg(tmp); \ 374 } \ 375 } 376 377 /*ARGSUSED*/ 378 static int 379 zsh_probe(dev_info_t *dev) 380 { 381 return (DDI_PROBE_DONTCARE); 382 } 383 384 /*ARGSUSED*/ 385 static int 386 zsh_attach(dev_info_t *dev, ddi_attach_cmd_t cmd) 387 { 388 register int unit; 389 char name[3] = { 390 '\0', '\0', '\0' }; 391 392 /* 393 * Since zsh is a child of the "pseudo" nexus, we can expect the 394 * attach routine to be called only once. We need to create all 395 * necessary devices in one shot. There is never more than one 396 * SCC chip that supports zsh devices. 397 */ 398 399 if (cmd != DDI_ATTACH) 400 return (DDI_FAILURE); 401 if (zscom == NULL) 402 return (DDI_FAILURE); /* zsattach not done */ 403 unit = 2 * ddi_get_instance(dev); 404 if (unit > 1) 405 return (DDI_FAILURE); /* only use cpu ports */ 406 407 if (ddi_create_minor_node(dev, "zsh", S_IFCHR, 408 NULL, DDI_PSEUDO, CLONE_DEV) == DDI_FAILURE) { 409 ddi_remove_minor_node(dev, NULL); 410 cmn_err(CE_WARN, "zsh clone device creation failed."); 411 return (DDI_FAILURE); 412 } 413 414 for (; unit < maxzsh/2; unit++) { 415 zscom[unit].zs_hdlc_dip = dev; 416 417 (void) sprintf(name, "%d", unit); 418 if (ddi_create_minor_node(dev, name, S_IFCHR, 419 2*unit, DDI_PSEUDO, NULL) == DDI_FAILURE) { 420 ddi_remove_minor_node(dev, NULL); 421 return (DDI_FAILURE); 422 } 423 unit++; 424 (void) sprintf(name, "%d", unit); 425 if (ddi_create_minor_node(dev, name, S_IFCHR, 426 2*(unit-1)+1, DDI_PSEUDO, NULL) == DDI_FAILURE) { 427 ddi_remove_minor_node(dev, NULL); 428 return (DDI_FAILURE); 429 } 430 } 431 432 return (DDI_SUCCESS); 433 } 434 435 /* ARGSUSED */ 436 int 437 zsh_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 438 void **result) 439 { 440 register dev_t dev = (dev_t)arg; 441 register int unit, error; 442 register struct zscom *zs; 443 444 if ((unit = UNIT(dev)) >= nzs) 445 return (DDI_FAILURE); 446 447 switch (infocmd) { 448 case DDI_INFO_DEVT2DEVINFO: 449 if (zscom == NULL) { 450 error = DDI_FAILURE; 451 } else { 452 zs = &zscom[unit]; 453 *result = zs->zs_hdlc_dip; 454 error = DDI_SUCCESS; 455 } 456 break; 457 case DDI_INFO_DEVT2INSTANCE: 458 *result = (void *)(uintptr_t)(unit / 2); 459 error = DDI_SUCCESS; 460 break; 461 default: 462 error = DDI_FAILURE; 463 } 464 return (error); 465 } 466 467 static int 468 zsh_detach(dev_info_t *dev, ddi_detach_cmd_t cmd) 469 { 470 if (cmd != DDI_DETACH) 471 return (DDI_FAILURE); 472 473 ddi_remove_minor_node(dev, NULL); 474 475 return (DDI_SUCCESS); 476 } 477 478 static void 479 zsh_init_port(struct zscom *zs, struct syncline *zss) 480 { 481 register uchar_t s0; 482 483 SCC_WRITE(3, (ZSWR3_RX_ENABLE | ZSWR3_RXCRC_ENABLE | ZSWR3_RX_8)); 484 SCC_WRITE(5, (ZSWR5_TX_8 | ZSWR5_DTR | ZSWR5_TXCRC_ENABLE)); 485 zss->sl_rr0 = SCC_READ0(); 486 if (zss->sl_flags & SF_FDXPTP) { 487 SCC_BIS(5, ZSWR5_TX_ENABLE); 488 SCC_BIS(5, ZSWR5_RTS); 489 s0 = SCC_READ0(); 490 if ((s0 & ZSRR0_CTS) || 491 !(zss->sl_mode.sm_config & (CONN_SIGNAL | CONN_IBM))) { 492 /* 493 * send msg that CTS is up 494 */ 495 zss->sl_rr0 |= ZSRR0_CTS; 496 zss->sl_txstate = TX_IDLE; 497 } else { 498 zss->sl_flags |= SF_XMT_INPROG; 499 zss->sl_txstate = TX_RTS; 500 zss->sl_rr0 &= ~ZSRR0_CTS; 501 zss->sl_wd_count = zsh_timer_count; 502 if (!zss->sl_wd_id) 503 zss->sl_wd_id = timeout(zsh_watchdog, 504 zs, SIO_WATCHDOG_TICK); 505 } 506 } else { 507 SCC_BIC(15, ZSR15_CTS); 508 SCC_BIC(5, ZSWR5_TX_ENABLE); 509 SCC_BIC(5, ZSWR5_RTS); 510 zss->sl_flags &= ~SF_FLUSH_WQ; 511 } 512 } 513 514 /* 515 * Open routine. 516 */ 517 518 /*ARGSUSED*/ 519 static int 520 zsh_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr) 521 { 522 register struct zscom *zs; 523 register struct syncline *zss; 524 register struct ser_str *stp; 525 register int unit; 526 register int tmp; 527 528 if (sflag != CLONEOPEN) { 529 if (rq->q_ptr) 530 return (EBUSY); /* We got a stream that is in use */ 531 532 unit = UNIT(*dev); 533 if (unit >= maxzsh) 534 return (ENXIO); /* unit not configured */ 535 536 if (zscom == NULL) 537 return (ENXIO); /* device not found by autoconfig */ 538 zs = &zscom[unit]; 539 540 if (zs->zs_ops == NULL) { 541 return (ENXIO); /* device not found by autoconfig */ 542 } 543 544 TRACE_1(TR_ZSH, TR_ZSH_OPEN, "zsh_open:unit = %d", unit); 545 546 mutex_enter(zs->zs_excl); 547 if ((zs->zs_ops != &zsops_null) && 548 (zs->zs_ops != &zsops_hdlc)) { 549 mutex_exit(zs->zs_excl); 550 return (EBUSY); /* another protocol got here first */ 551 } 552 553 /* Mark device as busy (for power management) */ 554 (void) pm_busy_component(zs->zs_dip, unit%2+1); 555 (void) ddi_dev_is_needed(zs->zs_dip, unit%2+1, 1); 556 557 zsopinit(zs, &zsops_hdlc); 558 559 zss = (struct syncline *)&zscom[unit].zs_priv_str; 560 stp = &zss->sl_stream; 561 stp->str_state = NULL; 562 stp->str_com = (caddr_t)zs; 563 564 zss->sl_xhead = NULL; 565 zss->sl_xactb = NULL; 566 zs->zs_wr_cur = NULL; 567 zs->zs_wr_lim = NULL; 568 zs->zs_wr_cur = NULL; 569 zs->zs_wr_lim = NULL; 570 zss->sl_rhead = NULL; 571 zss->sl_ractb = NULL; 572 zs->zs_rd_cur = NULL; 573 zs->zs_rd_lim = NULL; 574 zss->sl_mstat = NULL; 575 zss->sl_xstandby = NULL; 576 zss->sl_wd_id = 0; 577 zss->sl_soft_active = 0; 578 zss->sl_stream.str_rq = NULL; 579 580 zs->zs_priv = (caddr_t)zss; 581 582 zss->sl_mru = zsh_default_mru; 583 tmp = ZSH_MAX_RSTANDBY; 584 ZSH_GETBLOCK(zs, tmp); 585 if (zss->sl_rstandby[0] == NULL) { 586 cmn_err(CE_WARN, "zsh_open: can't alloc message block"); 587 mutex_exit(zs->zs_excl); 588 return (ENOSR); 589 } 590 mutex_enter(zs->zs_excl_hi); 591 ZSH_ALLOCB(zss->sl_ractb); 592 zss->sl_txstate = TX_OFF; 593 zss->sl_rr0 = SCC_READ0(); 594 zss->sl_flags &= (SF_INITIALIZED | SF_FDXPTP); 595 if (zss->sl_flags & SF_INITIALIZED) 596 zsh_init_port(zs, zss); 597 mutex_exit(zs->zs_excl_hi); 598 mutex_exit(zs->zs_excl); 599 } else { /* CLONEOPEN */ 600 mutex_enter(&zs_curr_lock); 601 for (unit = maxzsh; unit < MAXZSHCLONES; unit++) 602 if (!zsh_usedminor[unit]) { 603 zsh_usedminor[unit] = (unsigned char)unit; 604 break; 605 } 606 mutex_exit(&zs_curr_lock); 607 if (unit >= MAXZSHCLONES) /* no slots available */ 608 return (ENODEV); 609 *dev = makedevice(getmajor(*dev), unit); 610 611 stp = kmem_zalloc(sizeof (struct ser_str), KM_NOSLEEP); 612 if (stp == NULL) { 613 cmn_err(CE_WARN, 614 "zsh clone open failed, no memory, rq=%p\n", 615 (void *)rq); 616 return (ENOMEM); 617 } 618 stp->str_state = STR_CLONE; 619 stp->str_com = NULL; /* can't determine without ppa */ 620 } 621 stp->str_rq = rq; 622 stp->str_inst = unit; 623 624 rq->q_ptr = WR(rq)->q_ptr = (caddr_t)stp; 625 qprocson(rq); 626 return (0); 627 } 628 629 /* 630 * Close routine. 631 */ 632 int zsh_tx_enable_in_close = 0; 633 634 /*ARGSUSED*/ 635 static int 636 zsh_close(queue_t *rq, int flag) 637 { 638 struct ser_str *stp; 639 struct zscom *zs; 640 struct syncline *zss; 641 mblk_t *mp; 642 int i; 643 timeout_id_t sl_wd_id; 644 bufcall_id_t sl_bufcid; 645 646 /* 647 * Note that a close is only called on the last close of a 648 * particular stream. Assume that we need to do it all. 649 */ 650 qprocsoff(rq); /* no new business after this */ 651 652 stp = (struct ser_str *)rq->q_ptr; 653 if (stp == NULL) 654 return (0); /* already been closed once */ 655 656 if (stp->str_state == STR_CLONE) { 657 zsh_usedminor[stp->str_inst] = 0; 658 } else { 659 zs = (struct zscom *)stp->str_com; 660 if (zs == NULL) 661 goto out; 662 663 TRACE_1(TR_ZSH, TR_ZSH_CLOSE, "zs = %p", zs); 664 665 zss = (struct syncline *)zs->zs_priv; 666 mutex_enter(zs->zs_excl); 667 flushq(WR(rq), FLUSHALL); 668 mutex_enter(zs->zs_excl_hi); 669 if (zss->sl_xstandby) { 670 zss->sl_xstandby->b_wptr = zss->sl_xstandby->b_rptr; 671 ZSH_FREEMSG(zss->sl_xstandby); 672 zss->sl_xstandby = NULL; 673 } 674 mutex_exit(zs->zs_excl_hi); 675 676 ZSH_FLUSHQ; 677 678 /* 679 * Stop the Watchdog Timer. 680 */ 681 if ((sl_wd_id = zss->sl_wd_id) != 0) 682 zss->sl_wd_id = 0; 683 684 /* 685 * Cancel outstanding "bufcall" request. 686 */ 687 if ((sl_bufcid = zss->sl_bufcid) != 0) 688 zss->sl_bufcid = 0; 689 690 mutex_enter(zs->zs_excl_hi); 691 if (zs->zs_wr_cur) { 692 zs->zs_wr_cur = NULL; 693 zs->zs_wr_lim = NULL; 694 SCC_WRITE0(ZSWR0_SEND_ABORT); 695 ZSDELAY(); 696 ZSDELAY(); 697 } 698 zss->sl_txstate = TX_OFF; /* so it can't rearm in close */ 699 700 zs->zs_wr_cur = NULL; 701 zs->zs_wr_lim = NULL; 702 SCC_BIC(15, 703 (ZSR15_TX_UNDER | ZSR15_BREAK | ZSR15_SYNC | ZSR15_CTS)); 704 SCC_WRITE(3, 0); /* Quiesce receiver */ 705 if (zsh_tx_enable_in_close && !(zss->sl_flags & SF_FDXPTP)) { 706 SCC_BIS(5, ZSWR5_TX_ENABLE); 707 } else 708 SCC_BIC(5, ZSWR5_TX_ENABLE); 709 710 SCC_BIC(5, (ZSWR5_DTR | ZSWR5_RTS | ZSWR5_TXCRC_ENABLE)); 711 SCC_WRITE0(ZSWR0_RESET_TXINT); /* reset TX */ 712 SCC_WRITE0(ZSWR0_RESET_STATUS); /* reset XS */ 713 SCC_WRITE0(ZSWR0_RESET_ERRORS); 714 (void) SCC_READDATA(); /* reset RX */ 715 ZSDELAY(); 716 (void) SCC_READDATA(); 717 ZSDELAY(); 718 (void) SCC_READDATA(); 719 ZSDELAY(); 720 721 722 /* 723 * Free up everything we ever allocated. 724 */ 725 if ((mp = zss->sl_rhead) != NULL) { 726 zss->sl_ractb = NULL; /* already freed */ 727 zs->zs_rd_cur = NULL; 728 zs->zs_rd_lim = NULL; 729 zss->sl_rhead = NULL; 730 } 731 mutex_exit(zs->zs_excl_hi); 732 if (mp) 733 freemsg(mp); 734 735 mutex_enter(zs->zs_excl_hi); 736 if ((mp = zss->sl_ractb) != NULL) { 737 zs->zs_rd_cur = NULL; 738 zs->zs_rd_lim = NULL; 739 zss->sl_ractb = NULL; 740 } 741 mutex_exit(zs->zs_excl_hi); 742 if (mp) 743 freemsg(mp); 744 745 for (i = 0; i < ZSH_MAX_RSTANDBY; i++) { 746 mutex_enter(zs->zs_excl_hi); 747 mp = zss->sl_rstandby[i]; 748 zss->sl_rstandby[i] = NULL; 749 mutex_exit(zs->zs_excl_hi); 750 if (mp) 751 freemsg(mp); 752 } 753 754 mutex_enter(zs->zs_excl_hi); 755 if ((mp = zss->sl_xhead) != NULL) { 756 zss->sl_xhead = NULL; 757 zss->sl_xactb = NULL; 758 } 759 mutex_exit(zs->zs_excl_hi); 760 if (mp) 761 freemsg(mp); 762 763 ZSH_FLUSHQ; 764 765 mutex_enter(zs->zs_excl_hi); 766 if ((mp = zss->sl_xstandby) != NULL) 767 zss->sl_xstandby = NULL; 768 mutex_exit(zs->zs_excl_hi); 769 if (mp) 770 freemsg(mp); 771 772 mutex_enter(zs->zs_excl_hi); 773 if ((mp = zss->sl_mstat) != NULL) 774 zss->sl_mstat = NULL; 775 zss->sl_txstate = TX_OFF; /* so it can't rearm in close */ 776 mutex_exit(zs->zs_excl_hi); 777 if (mp) 778 freemsg(mp); 779 780 zss->sl_stream.str_rq = NULL; 781 zsopinit(zs, &zsops_null); 782 mutex_exit(zs->zs_excl); 783 if (sl_wd_id) 784 (void) untimeout(sl_wd_id); 785 if (sl_bufcid) 786 unbufcall(sl_bufcid); 787 while (zss->sl_soft_active) 788 drv_usecwait(1); 789 790 /* Mark device as available for power management */ 791 (void) pm_idle_component(zs->zs_dip, zs->zs_unit%2+1); 792 } 793 794 if (stp->str_state == STR_CLONE) 795 kmem_free(stp, sizeof (struct ser_str)); 796 797 out: 798 rq->q_ptr = WR(rq)->q_ptr = NULL; 799 800 return (0); 801 } 802 803 static int 804 zsh_hdp_ok_or_rts_state(struct zscom *zs, struct syncline *zss) 805 { 806 register uchar_t s0; 807 808 SCC_BIS(15, ZSR15_CTS); 809 SCC_BIS(5, ZSWR5_RTS); 810 s0 = SCC_READ0(); 811 if (s0 & ZSRR0_CTS) { 812 SCC_BIS(5, ZSWR5_TX_ENABLE); 813 zss->sl_rr0 |= ZSRR0_CTS; 814 return (1); 815 } 816 zss->sl_flags |= SF_XMT_INPROG; 817 zss->sl_txstate = TX_RTS; 818 zss->sl_rr0 &= ~ZSRR0_CTS; 819 zss->sl_wd_count = zsh_timer_count; 820 return (0); 821 } 822 823 /* 824 * Put procedure for write queue. 825 */ 826 static void 827 zsh_wput(queue_t *wq, mblk_t *mp) 828 { 829 register struct ser_str *stp = (struct ser_str *)wq->q_ptr; 830 register struct zscom *zs; 831 register struct syncline *zss = NULL; 832 register ulong_t prim, error = 0; 833 register union DL_primitives *dlp; 834 register int ppa; 835 register mblk_t *tmp; 836 register struct copyresp *resp; 837 838 /* 839 * stp->str_com supplied by open or DLPI attach. 840 */ 841 if (stp == NULL) { 842 freemsg(mp); 843 return; 844 } 845 zs = (struct zscom *)stp->str_com; 846 847 TRACE_0(TR_ZSH, TR_ZSH_WPUT_START, "zsh_wput start"); 848 849 if ((mp->b_datap->db_type == M_FLUSH) && 850 (stp->str_state == STR_CLONE)) { 851 if (*mp->b_rptr & FLUSHW) { 852 flushq(wq, FLUSHDATA); 853 *mp->b_rptr &= ~FLUSHW; 854 } 855 if (*mp->b_rptr & FLUSHR) 856 qreply(wq, mp); /* let the read queues have at it */ 857 else 858 freemsg(mp); 859 return; 860 } 861 862 if ((zs == NULL) && (mp->b_datap->db_type != M_PROTO)) { 863 freemsg(mp); 864 cmn_err(CE_WARN, 865 "zsh: clone device %d must be attached before use!", 866 stp->str_inst); 867 (void) putnextctl1(RD(wq), M_ERROR, EPROTO); 868 return; 869 } 870 871 if (stp->str_state == STR_CLONE) { /* Clone opened, limited. */ 872 if ((mp->b_datap->db_type != M_PROTO) && 873 (mp->b_datap->db_type != M_IOCTL) && 874 (mp->b_datap->db_type != M_IOCDATA)) { 875 freemsg(mp); 876 cmn_err(CE_WARN, 877 "zsh%x: invalid operation for clone dev.\n", 878 stp->str_inst); 879 (void) putnextctl1(RD(wq), M_ERROR, EPROTO); 880 return; 881 } 882 } else { 883 zss = (struct syncline *)zs->zs_priv; 884 } 885 886 switch (mp->b_datap->db_type) { 887 888 case M_DATA: 889 /* 890 * Queue the message up to be transmitted. 891 * Set "in progress" flag and call the start routine. 892 */ 893 mutex_enter(zs->zs_excl_hi); 894 if (!(zss->sl_flags & SF_INITIALIZED)) { 895 mutex_exit(zs->zs_excl_hi); 896 cmn_err(CE_WARN, 897 "zsh%x not initialized, can't send message", 898 zs->zs_unit); 899 freemsg(mp); 900 (void) putnextctl1(RD(wq), M_ERROR, ECOMM); 901 return; 902 } 903 mutex_exit(zs->zs_excl_hi); 904 if (zs->zs_flags & ZS_NEEDSOFT) { 905 zs->zs_flags &= ~ZS_NEEDSOFT; 906 (void) zsh_softint(zs); 907 } 908 while (mp->b_wptr == mp->b_rptr) { 909 register mblk_t *mp1; 910 mp1 = unlinkb(mp); 911 freemsg(mp); 912 mp = mp1; 913 if (mp == NULL) 914 return; 915 } 916 mutex_enter(zs->zs_excl); 917 (void) putq(wq, mp); 918 mutex_enter(zs->zs_excl_hi); 919 if (zss->sl_flags & SF_FLUSH_WQ) { 920 mutex_exit(zs->zs_excl_hi); 921 flushq(wq, FLUSHDATA); 922 mutex_exit(zs->zs_excl); 923 924 TRACE_1(TR_ZSH, TR_ZSH_WPUT_END, 925 "zsh_wput end: zs = %p", zs); 926 927 return; 928 } 929 tmp = NULL; 930 again: 931 if (!zss->sl_xstandby) { 932 if (tmp) 933 zss->sl_xstandby = tmp; 934 else { 935 mutex_exit(zs->zs_excl_hi); 936 tmp = getq(wq); 937 mutex_enter(zs->zs_excl_hi); 938 if (tmp) 939 goto again; 940 } 941 } else if (tmp) { 942 mutex_exit(zs->zs_excl_hi); 943 (void) putbq(wq, tmp); 944 mutex_enter(zs->zs_excl_hi); 945 } 946 947 if (zss->sl_flags & SF_XMT_INPROG) { 948 mutex_exit(zs->zs_excl_hi); 949 mutex_exit(zs->zs_excl); 950 951 TRACE_1(TR_ZSH, TR_ZSH_WPUT_END, 952 "zsh_wput end: zs = %p", zs); 953 954 return; 955 } 956 957 if (!zss->sl_wd_id) { 958 zss->sl_wd_count = zsh_timer_count; 959 zss->sl_txstate = TX_IDLE; 960 mutex_exit(zs->zs_excl_hi); 961 zss->sl_wd_id = timeout(zsh_watchdog, zs, 962 SIO_WATCHDOG_TICK); 963 mutex_enter(zs->zs_excl_hi); 964 } 965 966 zss->sl_flags |= SF_XMT_INPROG; 967 if ((zss->sl_flags & SF_FDXPTP) || 968 zsh_hdp_ok_or_rts_state(zs, zss)) 969 (void) zsh_start(zs, zss); 970 mutex_exit(zs->zs_excl_hi); 971 mutex_exit(zs->zs_excl); 972 break; 973 974 case M_PROTO: 975 /* 976 * Here is where a clone device finds out about the 977 * hardware it is going to attach to. The request is 978 * validated and a ppa is extracted from it and validated. 979 * This number is used to index the hardware data structure 980 * and the protocol data structure, in case the latter 981 * was not provided by a data-path open before this. 982 */ 983 if (stp->str_state != STR_CLONE) { 984 freemsg(mp); 985 return; 986 } 987 988 if (MBLKL(mp) < DL_ATTACH_REQ_SIZE) { 989 prim = DL_ATTACH_REQ; 990 error = DL_BADPRIM; 991 goto end_proto; 992 } 993 dlp = (union DL_primitives *)mp->b_rptr; 994 prim = dlp->dl_primitive; 995 if (prim != DL_ATTACH_REQ) { 996 error = DL_BADPRIM; 997 goto end_proto; 998 } 999 ppa = dlp->attach_req.dl_ppa; 1000 ppa = (ppa%2) ? ((ppa-1)*2 +1) : (ppa*2); 1001 if (ppa >= maxzsh) { 1002 error = DL_BADPPA; 1003 goto end_proto; 1004 } 1005 zs = &zscom[ppa]; 1006 if (zs->zs_ops == NULL) { 1007 error = ENXIO; 1008 goto end_proto; 1009 } 1010 mutex_enter(zs->zs_excl); 1011 if ((zs->zs_ops != &zsops_null) && 1012 (zs->zs_ops != &zsops_hdlc)) { 1013 /* 1014 * another protocol got here first 1015 */ 1016 error = (EBUSY); 1017 mutex_exit(zs->zs_excl); 1018 goto end_proto; 1019 1020 } 1021 1022 stp->str_com = (caddr_t)zs; 1023 mutex_exit(zs->zs_excl); 1024 end_proto: 1025 if (error) 1026 dlerrorack(wq, mp, prim, error, 0); 1027 else 1028 dlokack(wq, mp, DL_ATTACH_REQ); 1029 break; 1030 1031 case M_IOCTL: 1032 zsh_ioctl(wq, mp); 1033 break; 1034 1035 case M_IOCDATA: 1036 resp = (struct copyresp *)mp->b_rptr; 1037 if (resp->cp_rval) { 1038 /* 1039 * Just free message on failure. 1040 */ 1041 freemsg(mp); 1042 break; 1043 } 1044 1045 switch (resp->cp_cmd) { 1046 1047 case S_IOCGETMODE: 1048 case S_IOCGETSTATS: 1049 case S_IOCGETSPEED: 1050 case S_IOCGETMCTL: 1051 case S_IOCGETMRU: 1052 mioc2ack(mp, NULL, 0, 0); 1053 qreply(wq, mp); 1054 break; 1055 1056 case S_IOCSETMODE: 1057 zss = (struct syncline *)&zs->zs_priv_str; 1058 mutex_enter(zs->zs_excl); 1059 error = zsh_setmode(zs, zss, 1060 (struct scc_mode *)mp->b_cont->b_rptr); 1061 if (error) { 1062 register struct iocblk *iocp = 1063 (struct iocblk *)mp->b_rptr; 1064 mp->b_datap->db_type = M_IOCNAK; 1065 iocp->ioc_error = error; 1066 } else 1067 mioc2ack(mp, NULL, 0, 0); 1068 mutex_exit(zs->zs_excl); 1069 qreply(wq, mp); 1070 break; 1071 1072 case S_IOCSETMRU: 1073 zss = (struct syncline *)&zs->zs_priv_str; 1074 mutex_enter(zs->zs_excl); 1075 zss->sl_mru = *(int *)mp->b_cont->b_rptr; 1076 mutex_exit(zs->zs_excl); 1077 mioc2ack(mp, NULL, 0, 0); 1078 qreply(wq, mp); 1079 break; 1080 default: 1081 freemsg(mp); 1082 } 1083 break; 1084 1085 /* 1086 * We're at the bottom of the food chain, so we flush our 1087 * write queue, clear the FLUSHW bit so it doesn't go round 1088 * and round forever, then flush our read queue (since there's 1089 * no read put procedure down here) and pass it up for any 1090 * higher modules to deal with in their own way. 1091 */ 1092 case M_FLUSH: 1093 if (*mp->b_rptr & FLUSHW) { 1094 mutex_enter(zs->zs_excl); 1095 flushq(wq, FLUSHDATA); 1096 mutex_enter(zs->zs_excl_hi); 1097 tmp = zss->sl_xstandby; 1098 zss->sl_xstandby = NULL; 1099 mutex_exit(zs->zs_excl_hi); 1100 if (tmp) 1101 freemsg(tmp); 1102 mutex_exit(zs->zs_excl); 1103 *mp->b_rptr &= ~FLUSHW; 1104 } 1105 1106 if (*mp->b_rptr & FLUSHR) { 1107 mutex_enter(zs->zs_excl); 1108 ZSH_FLUSHQ; 1109 mutex_exit(zs->zs_excl); 1110 qreply(wq, mp); /* let the read queues have at it */ 1111 } else 1112 freemsg(mp); 1113 break; 1114 1115 default: 1116 /* 1117 * "No, I don't want a subscription to Chain Store Age, 1118 * thank you anyway." 1119 */ 1120 freemsg(mp); 1121 break; 1122 } 1123 1124 TRACE_1(TR_ZSH, TR_ZSH_WPUT_END, "zsh_wput end: zs = %p", zs); 1125 } 1126 1127 /* 1128 * Get the next message from the write queue, set up the necessary pointers, 1129 * state info, etc., and start the transmit "engine" by sending the first 1130 * character. We'll then rotate through txint until done, then get an xsint. 1131 */ 1132 static int 1133 zsh_start(struct zscom *zs, struct syncline *zss) 1134 { 1135 register mblk_t *mp; 1136 register uchar_t *wptr; 1137 register uchar_t *rptr; 1138 register uchar_t sl_flags = zss->sl_flags; 1139 1140 /* 1141 * Attempt to grab the next M_DATA message off the queue (that's 1142 * all that will be left after wput) and begin transmission. 1143 * This routine is normally called after completion of a previous 1144 * frame, or when zsh_wput gets a new message. If we are in a 1145 * mode that put us in the TX_RTS state, waiting for CTS, and CTS 1146 * is not up yet, we have no business here. Ditto if we're in 1147 * either the TX_ACTIVE or TX_CRC states. In these cases we 1148 * don't clear SF_CALLSTART, so we don't forget there's work to do. 1149 */ 1150 1151 TRACE_1(TR_ZSH, TR_ZSH_START_START, 1152 "zsh_start start: zs = %p", zs); 1153 1154 if (sl_flags & SF_PHONY) { 1155 sl_flags &= ~SF_PHONY; 1156 SCC_BIC(15, ZSR15_CTS); 1157 SCC_BIC(5, ZSWR5_RTS); 1158 SCC_WRITE0(ZSWR0_RESET_TXINT); 1159 SCC_BIC(5, ZSWR5_TX_ENABLE); 1160 zss->sl_rr0 &= ~ZSRR0_CTS; 1161 zss->sl_txstate = TX_IDLE; 1162 /* 1163 * if we get another msg by chance zsh_watchog will start 1164 */ 1165 sl_flags &= ~SF_XMT_INPROG; 1166 zss->sl_flags = sl_flags; 1167 1168 TRACE_1(TR_ZSH, TR_ZSH_START_END, 1169 "zsh_start end: zs = %d", zs); 1170 1171 return (0); 1172 } 1173 mp = zss->sl_xstandby; 1174 if (mp == NULL) { 1175 if (!(sl_flags & SF_FDXPTP)) { 1176 sl_flags |= SF_PHONY; 1177 ZSH_ALLOCB(mp); 1178 if (!mp) 1179 return (0); 1180 mp->b_datap->db_type = M_RSE; 1181 mp->b_wptr = mp->b_rptr + 1; 1182 goto transmit; 1183 } 1184 sl_flags &= ~SF_XMT_INPROG; 1185 zss->sl_flags = sl_flags; 1186 1187 TRACE_1(TR_ZSH, TR_ZSH_START_END, 1188 "zsh_start end: zs = %p", zs); 1189 1190 return (0); 1191 } 1192 1193 transmit: 1194 zss->sl_xstandby = NULL; 1195 rptr = mp->b_rptr; 1196 wptr = mp->b_wptr; 1197 ZSSETSOFT(zs); 1198 1199 #ifdef ZSH_DEBUG 1200 if (zss->sl_xhead || zss->sl_xactb) { 1201 debug_enter("xhead1"); 1202 } 1203 #endif 1204 1205 zss->sl_xhead = mp; 1206 zss->sl_xactb = mp; 1207 zss->sl_wd_count = zsh_timer_count; 1208 zss->sl_txstate = TX_ACTIVE; 1209 zss->sl_ocnt = 0; 1210 SCC_BIS(10, ZSWR10_UNDERRUN_ABORT); /* abort on underrun */ 1211 SCC_WRITE0(ZSWR0_RESET_TXCRC); /* reset transmit CRC */ 1212 zss->sl_ocnt = wptr - rptr; 1213 mp->b_wptr = rptr; /* to tell soft to free this msg */ 1214 SCC_WRITEDATA(*rptr++); /* resets TXINT */ 1215 zs->zs_wr_cur = rptr; 1216 zs->zs_wr_lim = wptr; 1217 1218 SCC_WRITE0(ZSWR0_RESET_EOM); 1219 1220 TRACE_1(TR_ZSH, TR_ZSH_START_END, 1221 "zsh_start end: zs = %p", zs); 1222 1223 zss->sl_flags = sl_flags; 1224 return (1); 1225 } 1226 1227 1228 /* 1229 * Process an "ioctl" message sent down to us. 1230 */ 1231 static void 1232 zsh_ioctl(queue_t *wq, mblk_t *mp) 1233 { 1234 register struct ser_str *stp = (struct ser_str *)wq->q_ptr; 1235 register struct zscom *zs = (struct zscom *)stp->str_com; 1236 register struct syncline *zss = (struct syncline *)&zs->zs_priv_str; 1237 register struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 1238 register struct scc_mode *sm; 1239 register struct sl_stats *st; 1240 register uchar_t *msignals; 1241 register mblk_t *tmp; 1242 register int error = 0; 1243 1244 mutex_enter(zs->zs_excl); 1245 if ((zs->zs_ops != &zsops_null) && 1246 (zs->zs_ops != &zsops_hdlc)) { 1247 /* 1248 * another protocol got here first 1249 */ 1250 error = (EBUSY); 1251 goto end_zsh_ioctl; 1252 } 1253 1254 1255 switch (iocp->ioc_cmd) { 1256 1257 case S_IOCGETMODE: 1258 tmp = allocb(sizeof (struct scc_mode), BPRI_MED); 1259 if (tmp == NULL) { 1260 error = EAGAIN; 1261 break; 1262 } 1263 if (iocp->ioc_count != TRANSPARENT) 1264 mioc2ack(mp, tmp, sizeof (struct scc_mode), 0); 1265 else 1266 mcopyout(mp, NULL, sizeof (struct scc_mode), NULL, tmp); 1267 sm = (struct scc_mode *)mp->b_cont->b_rptr; 1268 bcopy(&zss->sl_mode, sm, sizeof (struct scc_mode)); 1269 break; 1270 1271 case S_IOCGETSTATS: 1272 tmp = allocb(sizeof (struct sl_stats), BPRI_MED); 1273 if (tmp == NULL) { 1274 error = EAGAIN; 1275 break; 1276 } 1277 if (iocp->ioc_count != TRANSPARENT) 1278 mioc2ack(mp, tmp, sizeof (struct sl_stats), 0); 1279 else 1280 mcopyout(mp, NULL, sizeof (struct sl_stats), NULL, tmp); 1281 st = (struct sl_stats *)mp->b_cont->b_rptr; 1282 bcopy(&zss->sl_st, st, sizeof (struct sl_stats)); 1283 break; 1284 1285 case S_IOCGETSPEED: 1286 tmp = allocb(sizeof (int), BPRI_MED); 1287 if (tmp == NULL) { 1288 error = EAGAIN; 1289 break; 1290 } 1291 if (iocp->ioc_count != TRANSPARENT) 1292 mioc2ack(mp, tmp, sizeof (int), 0); 1293 else 1294 mcopyout(mp, NULL, sizeof (int), NULL, tmp); 1295 *(int *)mp->b_cont->b_rptr = zss->sl_mode.sm_baudrate; 1296 break; 1297 1298 case S_IOCGETMCTL: 1299 tmp = allocb(sizeof (char), BPRI_MED); 1300 if (tmp == NULL) { 1301 error = EAGAIN; 1302 break; 1303 } 1304 if (iocp->ioc_count != TRANSPARENT) 1305 mioc2ack(mp, tmp, sizeof (char), 0); 1306 else 1307 mcopyout(mp, NULL, sizeof (char), NULL, tmp); 1308 msignals = (uchar_t *)mp->b_cont->b_rptr; 1309 *msignals = zss->sl_rr0 & (ZSRR0_CD | ZSRR0_CTS); 1310 break; 1311 1312 case S_IOCGETMRU: 1313 tmp = allocb(sizeof (int), BPRI_MED); 1314 if (tmp == NULL) { 1315 error = EAGAIN; 1316 break; 1317 } 1318 if (iocp->ioc_count != TRANSPARENT) 1319 mioc2ack(mp, tmp, sizeof (int), 0); 1320 else 1321 mcopyout(mp, NULL, sizeof (int), NULL, tmp); 1322 *(int *)mp->b_cont->b_rptr = zss->sl_mru; 1323 break; 1324 1325 case S_IOCSETMODE: 1326 if (iocp->ioc_count != TRANSPARENT) { 1327 error = miocpullup(mp, sizeof (struct scc_mode)); 1328 if (error != 0) 1329 break; 1330 error = zsh_setmode(zs, zss, 1331 (struct scc_mode *)mp->b_cont->b_rptr); 1332 if (error == 0) 1333 mioc2ack(mp, NULL, 0, 0); 1334 } else 1335 mcopyin(mp, NULL, sizeof (struct scc_mode), NULL); 1336 break; 1337 1338 case S_IOCCLRSTATS: 1339 mutex_enter(zs->zs_excl_hi); 1340 bzero(&zss->sl_st, sizeof (struct sl_stats)); 1341 mutex_exit(zs->zs_excl_hi); 1342 mioc2ack(mp, NULL, 0, 0); 1343 break; 1344 1345 case S_IOCSETMRU: 1346 if (iocp->ioc_count != TRANSPARENT) { 1347 error = miocpullup(mp, sizeof (int)); 1348 if (error != 0) 1349 break; 1350 zss->sl_mru = *(int *)mp->b_cont->b_rptr; 1351 mioc2ack(mp, NULL, 0, 0); 1352 } else 1353 mcopyin(mp, NULL, sizeof (int), NULL); 1354 break; 1355 1356 case S_IOCSETDTR: 1357 /* 1358 * The first integer of the M_DATA block that should 1359 * follow indicate if DTR must be set or reset 1360 */ 1361 error = miocpullup(mp, sizeof (int)); 1362 if (error != 0) 1363 break; 1364 1365 mutex_enter(zs->zs_excl_hi); 1366 if (*(int *)mp->b_cont->b_rptr != 0) 1367 (void) zsmctl(zs, ZSWR5_DTR, DMBIS); 1368 else 1369 (void) zsmctl(zs, ZSWR5_DTR, DMBIC); 1370 mutex_exit(zs->zs_excl_hi); 1371 break; 1372 1373 default: 1374 error = EINVAL; 1375 1376 } 1377 end_zsh_ioctl: 1378 iocp->ioc_error = error; 1379 mp->b_datap->db_type = (error) ? M_IOCNAK : M_IOCACK; 1380 mutex_exit(zs->zs_excl); 1381 qreply(wq, mp); 1382 } 1383 1384 /* 1385 * Set the mode of the zsh port 1386 */ 1387 1388 int 1389 zsh_setmode(struct zscom *zs, struct syncline *zss, struct scc_mode *sm) 1390 { 1391 register int error = 0; 1392 register mblk_t *mp; 1393 1394 mutex_enter(zs->zs_excl_hi); 1395 if (sm->sm_rxclock == RXC_IS_PLL) { 1396 zss->sl_mode.sm_retval = SMERR_RXC; 1397 mutex_exit(zs->zs_excl_hi); 1398 return (EINVAL); /* not supported */ 1399 } else { 1400 if (((zss->sl_mode.sm_config ^ sm->sm_config) & 1401 CONN_SIGNAL) != 0) { /* Changing, going... */ 1402 if (sm->sm_config & CONN_SIGNAL) { /* ...up. */ 1403 if (zss->sl_mstat == NULL) { 1404 mutex_exit(zs->zs_excl_hi); 1405 mp = allocb( 1406 sizeof (struct sl_status), 1407 BPRI_MED); 1408 mutex_enter(zs->zs_excl_hi); 1409 zss->sl_mstat = mp; 1410 } 1411 } else { /* ...down. */ 1412 if ((mp = zss->sl_mstat) != NULL) 1413 zss->sl_mstat = NULL; 1414 mutex_exit(zs->zs_excl_hi); 1415 if (mp) 1416 freemsg(mp); 1417 mutex_enter(zs->zs_excl_hi); 1418 } 1419 } 1420 if (!(sm->sm_config & CONN_IBM)) { 1421 if (sm->sm_config & CONN_HDX) { 1422 zss->sl_mode.sm_retval = SMERR_HDX; 1423 mutex_exit(zs->zs_excl_hi); 1424 return (EINVAL); 1425 } 1426 if (sm->sm_config & CONN_MPT) { 1427 zss->sl_mode.sm_retval = SMERR_MPT; 1428 mutex_exit(zs->zs_excl_hi); 1429 return (EINVAL); 1430 } 1431 } 1432 zss->sl_flags &= ~SF_FDXPTP; /* "conmode" */ 1433 if ((sm->sm_config & (CONN_HDX | CONN_MPT)) == 0) 1434 zss->sl_flags |= SF_FDXPTP; 1435 1436 error = zsh_program(zs, sm); 1437 if (!error && (zs->zs_ops != &zsops_null)) 1438 zsh_init_port(zs, zss); 1439 } 1440 mutex_exit(zs->zs_excl_hi); 1441 1442 return (error); 1443 } 1444 1445 /* 1446 * Transmit interrupt service procedure 1447 */ 1448 1449 static void 1450 zsh_txint(struct zscom *zs) 1451 { 1452 register struct syncline *zss; 1453 register mblk_t *mp; 1454 register int tmp; 1455 register uchar_t *wr_cur; 1456 1457 TRACE_1(TR_ZSH, TR_ZSH_TXINT, "zsh_txint: zs = %p", zs); 1458 1459 if ((wr_cur = zs->zs_wr_cur) != NULL && (wr_cur < zs->zs_wr_lim)) { 1460 SCC_WRITEDATA(*wr_cur++); 1461 zs->zs_wr_cur = wr_cur; 1462 return; 1463 } 1464 1465 1466 zss = (struct syncline *)&zs->zs_priv_str; 1467 1468 switch (zss->sl_txstate) { 1469 1470 /* 1471 * we here because end of message block lim = cur 1472 */ 1473 case TX_ACTIVE: 1474 1475 mp = zss->sl_xactb; 1476 1477 again_txint: 1478 mp = mp->b_cont; 1479 if (mp) { 1480 zss->sl_xactb = mp; 1481 zss->sl_ocnt += tmp = mp->b_wptr - mp->b_rptr; 1482 if (!tmp) 1483 goto again_txint; 1484 zs->zs_wr_cur = mp->b_rptr; 1485 zs->zs_wr_lim = mp->b_wptr; 1486 SCC_WRITEDATA(*zs->zs_wr_cur++); 1487 return; 1488 } 1489 1490 /* 1491 * This is where the fun starts. At this point the 1492 * last character in the frame has been sent. We 1493 * issue a RESET_TXINT so we won't get another txint 1494 * until the CRC has been completely sent. Also we 1495 * reset the Abort-On-Underrun bit so that CRC is 1496 * sent at EOM, rather than an Abort. 1497 */ 1498 zs->zs_wr_cur = zs->zs_wr_lim = NULL; 1499 zss->sl_txstate = TX_CRC; 1500 SCC_WRITE0(ZSWR0_RESET_TXINT); 1501 if (!(zss->sl_flags & SF_PHONY)) { 1502 SCC_BIC(10, ZSWR10_UNDERRUN_ABORT); 1503 zss->sl_st.opack++; 1504 zss->sl_st.ochar += zss->sl_ocnt; 1505 } 1506 zss->sl_ocnt = 0; 1507 ZSH_FREEMSG(zss->sl_xhead); 1508 zss->sl_xhead = zss->sl_xactb = NULL; 1509 ZSSETSOFT(zs); 1510 break; 1511 /* 1512 * This txint means we have sent the CRC bytes at EOF. 1513 * The next txint will mean we are sending or have sent the 1514 * flag character at EOF, but we handle that differently, and 1515 * enter different states,depending on whether we're IBM or not. 1516 */ 1517 case TX_CRC: 1518 if (!(zss->sl_flags & SF_FDXPTP)) { 1519 zss->sl_txstate = TX_FLAG; /* HDX path */ 1520 } else { /* FDX path */ 1521 if (!zsh_start(zs, zss)) { 1522 zss->sl_txstate = TX_IDLE; 1523 SCC_WRITE0(ZSWR0_RESET_TXINT); 1524 } 1525 } 1526 break; 1527 1528 /* 1529 * This txint means the closing flag byte is going out the door. 1530 * We use this state to allow this to complete before dropping RTS. 1531 */ 1532 case TX_FLAG: 1533 zss->sl_txstate = TX_LAST; 1534 (void) zsh_start(zs, zss); 1535 break; 1536 1537 /* 1538 * Arriving here means the flag should be out and it's finally 1539 * time to close the barn door. 1540 */ 1541 case TX_LAST: 1542 zss->sl_txstate = TX_IDLE; 1543 SCC_WRITE0(ZSWR0_RESET_TXINT); 1544 break; 1545 1546 /* 1547 * If transmit was aborted, do nothing - watchdog will recover. 1548 */ 1549 case TX_ABORTED: 1550 SCC_WRITE0(ZSWR0_RESET_TXINT); 1551 break; 1552 1553 default: 1554 SCC_WRITE0(ZSWR0_RESET_TXINT); 1555 break; 1556 } 1557 } 1558 1559 /* 1560 * External Status Change interrupt service procedure 1561 */ 1562 static void 1563 zsh_xsint(struct zscom *zs) 1564 { 1565 register struct syncline *zss = (struct syncline *)&zs->zs_priv_str; 1566 register uchar_t s0, x0; 1567 1568 TRACE_1(TR_ZSH, TR_ZSH_XSINT, "zsh_xsint: zs = %p", zs); 1569 1570 s0 = SCC_READ0(); 1571 x0 = s0 ^ zss->sl_rr0; 1572 zss->sl_rr0 = s0; 1573 SCC_WRITE0(ZSWR0_RESET_STATUS); 1574 1575 if (s0 & ZSRR0_TXUNDER) { 1576 switch (zss->sl_txstate) { 1577 /* 1578 * A transmitter underrun has occurred. If we are not 1579 * here as the result of an abort sent by the watchdog 1580 * timeout routine, we need to send an abort to flush 1581 * the transmitter. Otherwise there is a danger of 1582 * trashing the next frame but still sending a good crc. 1583 * The TX_ABORTED flag is set so that the watchdog 1584 * routine can initiate recovery. 1585 */ 1586 case TX_ACTIVE: 1587 SCC_WRITE0(ZSWR0_SEND_ABORT); 1588 SCC_WRITE0(ZSWR0_RESET_TXINT); 1589 zss->sl_st.underrun++; 1590 zsh_txbad(zs, zss); 1591 1592 zss->sl_txstate = TX_ABORTED; 1593 zss->sl_wd_count = 0; 1594 break; 1595 1596 case TX_CRC: 1597 break; 1598 1599 case TX_FLAG: 1600 break; 1601 1602 case TX_ABORTED: 1603 break; 1604 1605 case TX_OFF: 1606 break; 1607 1608 case TX_LAST: 1609 break; 1610 1611 default: 1612 break; 1613 } 1614 } 1615 1616 if ((x0 & ZSRR0_BREAK) && (s0 & ZSRR0_BREAK) && zs->zs_rd_cur) { 1617 zss->sl_st.abort++; 1618 zsh_rxbad(zs, zss); 1619 } else if ((s0 & ZSRR0_SYNC) && (zs->zs_rd_cur)) { 1620 /* 1621 * Tricky code to avoid disaster in the case where 1622 * an abort was detected while receiving a packet, 1623 * but the abort did not last long enough to be 1624 * detected by zsh_xsint - this can happen since 1625 * the ZSRR0_BREAK is not latched. Since an abort 1626 * will automatically cause the SCC to enter 1627 * hunt mode, hopefully, the sync/hunt bit will be 1628 * set in this case (although if the interrupt is 1629 * sufficiently delayed, the SCC may have sync'ed 1630 * in again if it has detected a flag). 1631 */ 1632 zss->sl_st.abort++; 1633 zsh_rxbad(zs, zss); 1634 } 1635 1636 if (x0 & s0 & ZSRR0_CTS) { 1637 if (zss->sl_txstate == TX_RTS) { 1638 if (!(zss->sl_flags & SF_FDXPTP)) { 1639 SCC_BIS(5, ZSWR5_TX_ENABLE); 1640 } 1641 (void) zsh_start(zs, zss); 1642 } else if ((zss->sl_mode.sm_config & 1643 (CONN_IBM | CONN_SIGNAL))) { 1644 zss->sl_flags &= ~SF_FLUSH_WQ; 1645 zsh_setmstat(zs, CS_CTS_UP); 1646 } 1647 } 1648 1649 /* 1650 * We don't care about CTS transitions unless we are in either 1651 * IBM or SIGNAL mode, or both. So, if we see CTS drop, and we 1652 * care, and we are not idle, send up a report message. 1653 */ 1654 if ((x0 & ZSRR0_CTS) && ((s0 & ZSRR0_CTS) == 0) && 1655 (zss->sl_txstate != TX_OFF) && 1656 (zss->sl_mode.sm_config & (CONN_IBM | CONN_SIGNAL))) { 1657 SCC_BIC(15, ZSR15_CTS); 1658 zsh_setmstat(zs, CS_CTS_DOWN); 1659 zss->sl_flags &= ~SF_XMT_INPROG; 1660 zss->sl_flags |= SF_FLUSH_WQ; 1661 zss->sl_st.cts++; 1662 if (zss->sl_txstate != TX_IDLE) 1663 SCC_WRITE0(ZSWR0_SEND_ABORT); 1664 SCC_WRITE0(ZSWR0_RESET_ERRORS); 1665 SCC_WRITE0(ZSWR0_RESET_TXINT); 1666 zss->sl_wd_count = 0; 1667 zsh_txbad(zs, zss); 1668 } 1669 } 1670 1671 1672 /* 1673 * Receive interrupt service procedure 1674 */ 1675 static void 1676 zsh_rxint(struct zscom *zs) 1677 { 1678 register struct syncline *zss = (struct syncline *)&zs->zs_priv_str; 1679 register mblk_t *bp = zss->sl_ractb; 1680 unsigned char *rd_cur; 1681 1682 TRACE_1(TR_ZSH, TR_ZSH_RXINT, "zsh_rxint: zs = %p", zs); 1683 1684 if (((rd_cur = zs->zs_rd_cur) != NULL) && rd_cur < zs->zs_rd_lim) { 1685 *rd_cur++ = SCC_READDATA(); 1686 zs->zs_rd_cur = rd_cur; 1687 return; 1688 } 1689 1690 if (!rd_cur) { /* Beginning of frame */ 1691 if (!bp) { 1692 ZSH_ALLOCB(bp); 1693 zss->sl_ractb = bp; 1694 } 1695 zss->sl_rhead = bp; 1696 } else { /* end of data block should be cur==lim */ 1697 bp->b_wptr = zs->zs_rd_cur; 1698 ZSH_ALLOCB(bp->b_cont); 1699 bp = zss->sl_ractb = bp->b_cont; 1700 } 1701 if (!bp) { 1702 zss->sl_st.nobuffers++; 1703 zsh_rxbad(zs, zss); 1704 return; 1705 } 1706 zs->zs_rd_cur = bp->b_wptr; 1707 zs->zs_rd_lim = bp->b_datap->db_lim; 1708 *zs->zs_rd_cur++ = SCC_READDATA(); /* Also resets interrupt */ 1709 } 1710 1711 1712 /* 1713 * Special Receive Condition Interrupt routine 1714 */ 1715 static void 1716 zsh_srint(struct zscom *zs) 1717 { 1718 register struct syncline *zss = (struct syncline *)&zs->zs_priv_str; 1719 register uchar_t s1; 1720 register uchar_t *rd_cur; 1721 1722 TRACE_1(TR_ZSH, TR_ZSH_SRINT, "zsh_srint: zs = %p", zs); 1723 1724 SCC_READ(1, s1); 1725 1726 if (s1 & ZSRR1_RXEOF) { /* end of frame */ 1727 (void) SCC_READDATA(); 1728 SCC_WRITE0(ZSWR0_RESET_ERRORS); 1729 if (s1 & ZSRR1_FE) { /* bad CRC */ 1730 zss->sl_st.crc++; 1731 zsh_rxbad(zs, zss); 1732 return; 1733 } 1734 1735 if ((rd_cur = zs->zs_rd_cur) == NULL) 1736 return; 1737 1738 /* 1739 * Drop one CRC byte from length because it came in 1740 * before the special interrupt got here. 1741 */ 1742 zss->sl_ractb->b_wptr = rd_cur - 1; 1743 1744 /* 1745 * put on done queue 1746 */ 1747 ZSH_PUTQ(zss->sl_rhead); 1748 zss->sl_rhead = NULL; 1749 zss->sl_ractb = NULL; 1750 zs->zs_rd_cur = NULL; 1751 zs->zs_rd_lim = NULL; 1752 ZSSETSOFT(zs); 1753 1754 } else if (s1 & ZSRR1_DO) { 1755 (void) SCC_READDATA(); 1756 SCC_WRITE0(ZSWR0_RESET_ERRORS); 1757 zss->sl_st.overrun++; 1758 zsh_rxbad(zs, zss); 1759 } else 1760 SCC_WRITE0(ZSWR0_RESET_ERRORS); 1761 } 1762 1763 /* 1764 * Handle a second stage interrupt. 1765 * Does mostly lower priority buffer management stuff. 1766 */ 1767 static int 1768 zsh_softint(struct zscom *zs) 1769 { 1770 register struct syncline *zss; 1771 register queue_t *q; 1772 register mblk_t *mp, *tmp; 1773 register mblk_t *head = NULL, *tail = NULL; 1774 register int allocbcount = 0; 1775 int m_error; 1776 1777 TRACE_1(TR_ZSH, TR_ZSH_SOFT_START, "zsh_soft start: zs = %p", zs); 1778 1779 mutex_enter(zs->zs_excl); 1780 zss = (struct syncline *)zs->zs_priv; 1781 if (!zss || (q = zss->sl_stream.str_rq) == NULL) { 1782 mutex_exit(zs->zs_excl); 1783 return (0); 1784 } 1785 m_error = zss->sl_m_error; 1786 1787 zss->sl_m_error = 0; 1788 1789 1790 if (!zss->sl_mstat) 1791 zss->sl_mstat = allocb(sizeof (struct sl_status), BPRI_MED); 1792 1793 mutex_enter(zs->zs_excl_hi); 1794 if (zss->sl_flags & SF_FLUSH_WQ) { 1795 if (!(zss->sl_flags & SF_FDXPTP)) { 1796 zss->sl_flags &= ~SF_FLUSH_WQ; 1797 } else { 1798 register uchar_t s0; 1799 1800 s0 = SCC_READ0(); 1801 if (s0 & ZSRR0_CTS) { 1802 zss->sl_rr0 |= ZSRR0_CTS; 1803 SCC_BIS(15, ZSR15_CTS); 1804 zss->sl_flags &= ~SF_FLUSH_WQ; 1805 zsh_setmstat(zs, CS_CTS_UP); 1806 } 1807 if (zss->sl_flags & SF_FLUSH_WQ) { 1808 mutex_exit(zs->zs_excl_hi); 1809 flushq(WR(q), FLUSHDATA); 1810 goto next; 1811 } 1812 } 1813 } 1814 mutex_exit(zs->zs_excl_hi); 1815 1816 next: 1817 for (;;) { 1818 ZSH_GETQ(mp); 1819 if (!mp) 1820 break; 1821 1822 if (mp->b_rptr == mp->b_wptr) { 1823 if (mp->b_datap->db_type == M_RSE) { 1824 allocbcount++; 1825 } 1826 freemsg(mp); 1827 continue; 1828 } 1829 if (mp->b_datap->db_type == M_DATA) { 1830 zss->sl_st.ichar += msgdsize(mp); 1831 zss->sl_st.ipack++; 1832 if (!(canputnext(q))) { 1833 zss->sl_st.ierror++; 1834 allocbcount++; 1835 freemsg(mp); 1836 continue; 1837 } 1838 } else if (mp->b_datap->db_type == M_PROTO) { 1839 if (!(canputnext(q))) { 1840 freemsg(mp); 1841 continue; 1842 } 1843 } 1844 if (!head) { 1845 allocbcount++; 1846 zss->sl_soft_active = 1; 1847 head = mp; 1848 } else { 1849 if (!tail) 1850 tail = head; 1851 tail->b_next = mp; 1852 tail = mp; 1853 } 1854 } 1855 if (allocbcount) 1856 ZSH_GETBLOCK(zs, allocbcount); 1857 1858 tmp = NULL; 1859 again: 1860 mutex_enter(zs->zs_excl_hi); 1861 if (!zss->sl_xstandby) { 1862 if (tmp) { 1863 zss->sl_xstandby = tmp; 1864 mutex_exit(zs->zs_excl_hi); 1865 } else { 1866 mutex_exit(zs->zs_excl_hi); 1867 if (tmp = getq(WR(q))) 1868 goto again; 1869 } 1870 } else { 1871 mutex_exit(zs->zs_excl_hi); 1872 if (tmp) 1873 (void) putbq(WR(q), tmp); 1874 } 1875 1876 mutex_exit(zs->zs_excl); 1877 1878 while (head) { 1879 if (!tail) { 1880 putnext(q, head); 1881 break; 1882 } 1883 mp = head; 1884 head = head->b_next; 1885 mp->b_next = NULL; 1886 putnext(q, mp); 1887 1888 } 1889 1890 if (m_error) 1891 (void) putnextctl1(q, M_ERROR, m_error); 1892 1893 zss->sl_soft_active = 0; 1894 1895 TRACE_1(TR_ZSH, TR_ZSH_SOFT_END, "zsh_soft end: zs = %p", zs); 1896 1897 return (0); 1898 } 1899 1900 /* 1901 * Initialization routine. 1902 * Sets Clock sources, baud rate, modes and miscellaneous parameters. 1903 */ 1904 static int 1905 zsh_program(struct zscom *zs, struct scc_mode *sm) 1906 { 1907 register struct syncline *zss = (struct syncline *)&zs->zs_priv_str; 1908 register struct zs_prog *zspp; 1909 register ushort_t tconst = 0; 1910 register int wr11 = 0; 1911 register int baud = 0; 1912 register int pll = 0; 1913 register int speed = 0; 1914 register int flags = ZSP_SYNC; 1915 int err = 0; 1916 1917 ZSSETSOFT(zs); /* get our house in order */ 1918 1919 switch (sm->sm_txclock) { 1920 case TXC_IS_TXC: 1921 wr11 |= ZSWR11_TXCLK_TRXC; 1922 break; 1923 case TXC_IS_RXC: 1924 wr11 |= ZSWR11_TXCLK_RTXC; 1925 break; 1926 case TXC_IS_BAUD: 1927 wr11 |= ZSWR11_TXCLK_BAUD; 1928 wr11 |= ZSWR11_TRXC_OUT_ENA + ZSWR11_TRXC_XMIT; 1929 baud++; 1930 break; 1931 case TXC_IS_PLL: 1932 wr11 |= ZSWR11_TXCLK_DPLL; 1933 pll++; 1934 break; 1935 default: 1936 zss->sl_mode.sm_retval = SMERR_TXC; 1937 err = EINVAL; 1938 goto out; 1939 } 1940 switch (sm->sm_rxclock) { 1941 case RXC_IS_RXC: 1942 wr11 |= ZSWR11_RXCLK_RTXC; 1943 break; 1944 case RXC_IS_TXC: 1945 wr11 |= ZSWR11_RXCLK_TRXC; 1946 break; 1947 case RXC_IS_BAUD: 1948 wr11 |= ZSWR11_RXCLK_BAUD; 1949 baud++; 1950 break; 1951 case RXC_IS_PLL: 1952 wr11 |= ZSWR11_RXCLK_DPLL; 1953 pll++; 1954 break; 1955 default: 1956 zss->sl_mode.sm_retval = SMERR_RXC; 1957 err = EINVAL; 1958 goto out; 1959 } 1960 if (baud && pll) { 1961 zss->sl_mode.sm_retval = SMERR_PLL; 1962 err = EINVAL; 1963 goto out; 1964 } 1965 if (pll && !(sm->sm_config & CONN_NRZI)) { 1966 zss->sl_mode.sm_retval = SMERR_PLL; 1967 err = EINVAL; 1968 goto out; 1969 } 1970 1971 /* 1972 * If we're going to use the BRG and the speed we want is != 0... 1973 */ 1974 if (baud && (speed = sm->sm_baudrate)) { 1975 tconst = (PCLK + speed) / (2 * speed) - 2; 1976 if (tconst == 0) { 1977 zss->sl_mode.sm_retval = SMERR_BAUDRATE; 1978 err = EINVAL; 1979 goto out; 1980 } 1981 sm->sm_baudrate = PCLK / (2 * ((int)tconst + 2)); 1982 } else { 1983 tconst = 0; /* Stop BRG. Also quiesces pin 24. */ 1984 } 1985 1986 if (pll) { 1987 if ((speed = sm->sm_baudrate * 32) != 0) 1988 tconst = (PCLK + speed) / (2 * speed) - 2; 1989 else 1990 tconst = 0; 1991 if (tconst == 0) { 1992 zss->sl_mode.sm_retval = SMERR_BAUDRATE; 1993 err = EINVAL; 1994 goto out; 1995 } 1996 speed = PCLK / (2 * ((int)tconst + 2)); 1997 sm->sm_baudrate = speed / 32; 1998 flags |= ZSP_PLL; 1999 } 2000 2001 if ((sm->sm_config & (CONN_LPBK|CONN_ECHO)) == (CONN_LPBK|CONN_ECHO)) { 2002 zss->sl_mode.sm_retval = SMERR_LPBKS; 2003 err = EINVAL; 2004 goto out; 2005 } 2006 if (sm->sm_config & CONN_LPBK) 2007 flags |= ZSP_LOOP; 2008 if (sm->sm_config & CONN_NRZI) 2009 flags |= ZSP_NRZI; 2010 if (sm->sm_config & CONN_ECHO) 2011 flags |= ZSP_ECHO; 2012 2013 zspp = &zs_prog[zs->zs_unit]; 2014 2015 zspp->zs = zs; 2016 zspp->flags = (uchar_t)flags; 2017 zspp->wr4 = ZSWR4_SDLC; 2018 zspp->wr11 = (uchar_t)wr11; 2019 zspp->wr12 = (uchar_t)(tconst & 0xff); 2020 zspp->wr13 = (uchar_t)((tconst >> 8) & 0xff); 2021 zspp->wr3 = (uchar_t)(ZSWR3_RX_ENABLE | ZSWR3_RXCRC_ENABLE | 2022 ZSWR3_RX_8); 2023 zspp->wr5 = (uchar_t)(ZSWR5_TX_8 | ZSWR5_DTR | ZSWR5_TXCRC_ENABLE); 2024 2025 if (zss->sl_flags & SF_FDXPTP) { 2026 zspp->wr5 |= ZSWR5_RTS; 2027 zss->sl_rr0 |= ZSRR0_CTS; /* Assume CTS is high */ 2028 } 2029 if (sm->sm_config & CONN_IBM) { 2030 zspp->wr15 = (uchar_t) 2031 (ZSR15_TX_UNDER | ZSR15_BREAK | ZSR15_SYNC | ZSR15_CTS); 2032 if (!(zss->sl_flags & SF_FDXPTP)) 2033 zspp->wr15 &= ~ZSR15_CTS; 2034 } else { 2035 zspp->wr5 |= ZSWR5_TX_ENABLE; 2036 zspp->wr15 = (uchar_t) 2037 (ZSR15_TX_UNDER | ZSR15_BREAK | ZSR15_SYNC); 2038 if (sm->sm_config & CONN_SIGNAL) 2039 zspp->wr15 |= ZSR15_CTS; 2040 } 2041 2042 zs_program(zspp); 2043 SCC_WRITE0(ZSWR0_RESET_STATUS); /* reset XS */ 2044 SCC_WRITE0(ZSWR0_RESET_STATUS); /* reset XS */ 2045 zss->sl_flags |= SF_INITIALIZED; 2046 bzero(&zss->sl_st, sizeof (struct sl_stats)); 2047 bcopy(sm, &zss->sl_mode, sizeof (struct scc_mode)); 2048 zss->sl_mode.sm_retval = 0; /* successful */ 2049 out: 2050 return (err); 2051 } 2052 2053 /* 2054 * Function to store modem signal changes in sl_mstat field. 2055 * Note that these events are supposed to be so far apart in time that 2056 * we should always be able to send up the event and allocate a message 2057 * block before another one happens. If not, we'll overwrite this one. 2058 */ 2059 static void 2060 zsh_setmstat(struct zscom *zs, int event) 2061 { 2062 register struct syncline *zss = (struct syncline *)&zs->zs_priv_str; 2063 register struct sl_status *mstat; 2064 register mblk_t *mp; 2065 2066 if (((mp = zss->sl_mstat) != NULL) && 2067 (zss->sl_mode.sm_config & (CONN_SIGNAL))) { 2068 mstat = (struct sl_status *)mp->b_wptr; 2069 mstat->type = (zss->sl_mode.sm_config & CONN_IBM) ? 2070 SLS_LINKERR : SLS_MDMSTAT; 2071 mstat->status = event; 2072 gethrestime(&mstat->tstamp); 2073 mp->b_wptr += sizeof (struct sl_status); 2074 mp->b_datap->db_type = M_PROTO; 2075 ZSH_PUTQ(mp); 2076 zss->sl_mstat = NULL; 2077 ZSSETSOFT(zs); 2078 } 2079 } 2080 2081 /* 2082 * Received Bad Frame procedure 2083 */ 2084 static void 2085 zsh_rxbad(struct zscom *zs, struct syncline *zss) 2086 { 2087 /* 2088 * swallow bad characters 2089 */ 2090 (void) SCC_READDATA(); 2091 (void) SCC_READDATA(); 2092 (void) SCC_READDATA(); 2093 2094 SCC_BIS(3, ZSWR3_HUNT); /* enter hunt mode - ignores rest of frame */ 2095 2096 zss->sl_st.ierror++; 2097 2098 /* 2099 * Free active receive message. 2100 */ 2101 if (zss->sl_rhead) { 2102 zss->sl_rhead->b_wptr = zss->sl_rhead->b_rptr; 2103 zss->sl_rhead->b_datap->db_type = M_RSE; 2104 ZSH_FREEMSG(zss->sl_rhead); 2105 zss->sl_ractb = NULL; 2106 zs->zs_rd_cur = NULL; 2107 zs->zs_rd_lim = NULL; 2108 } 2109 if (zss->sl_rhead) { 2110 zss->sl_rhead = NULL; 2111 ZSH_ALLOCB(zss->sl_ractb); 2112 zs->zs_rd_cur = NULL; 2113 zs->zs_rd_lim = NULL; 2114 } 2115 2116 ZSSETSOFT(zs); 2117 } 2118 2119 /* 2120 * Transmit error procedure 2121 */ 2122 static void 2123 zsh_txbad(struct zscom *zs, struct syncline *zss) 2124 { 2125 if (zss->sl_xhead) { /* free the message we were sending */ 2126 zss->sl_xhead->b_wptr = zss->sl_xhead->b_rptr; 2127 ZSH_FREEMSG(zss->sl_xhead); 2128 zss->sl_xactb = NULL; 2129 zs->zs_wr_cur = NULL; 2130 zs->zs_wr_lim = NULL; 2131 } 2132 zss->sl_xhead = NULL; 2133 2134 if (!(zss->sl_flags & SF_FDXPTP)) { 2135 /* 2136 * drop RTS and our notion of CTS 2137 */ 2138 SCC_BIC(5, ZSWR5_RTS); 2139 SCC_BIC(5, ZSWR5_TX_ENABLE); 2140 zss->sl_rr0 &= ~ZSRR0_CTS; 2141 } 2142 zss->sl_txstate = TX_IDLE; 2143 if (!(zss->sl_flags & SF_PHONY)) 2144 zss->sl_st.oerror++; 2145 } 2146 2147 /* 2148 * Transmitter watchdog timeout routine 2149 */ 2150 static void 2151 zsh_watchdog(void *arg) 2152 { 2153 struct zscom *zs = arg; 2154 struct syncline *zss = (struct syncline *)&zs->zs_priv_str; 2155 queue_t *wq; 2156 mblk_t *mp; 2157 int warning = 0; 2158 uchar_t s0; 2159 int do_flushwq = 0; 2160 2161 /* 2162 * The main reason for this routine is because, under some 2163 * circumstances, a transmit interrupt may get lost (ie., if 2164 * underrun occurs after the last character has been sent, and 2165 * the tx interrupt following the abort gets scheduled before 2166 * the current tx interrupt has been serviced). Transmit can 2167 * also get hung if the cable is pulled out and the clock was 2168 * coming in from the modem. 2169 */ 2170 2171 mutex_enter(zs->zs_excl); 2172 if (zss->sl_stream.str_rq) 2173 wq = WR(zss->sl_stream.str_rq); 2174 else { 2175 mutex_exit(zs->zs_excl); 2176 return; /* guard against close/callback race */ 2177 } 2178 2179 mutex_enter(zs->zs_excl_hi); 2180 if (!(zss->sl_flags & SF_XMT_INPROG) && wq->q_first) { 2181 zss->sl_flags |= SF_XMT_INPROG; 2182 if ((zss->sl_flags & SF_FDXPTP) || 2183 zsh_hdp_ok_or_rts_state(zs, zss)) 2184 (void) zsh_start(zs, zss); 2185 goto end_watchdog; 2186 } 2187 2188 if (zss->sl_wd_count-- > 0) 2189 goto end_watchdog; 2190 2191 if (zss->sl_flags & SF_FLUSH_WQ) { 2192 if (!(zss->sl_flags & SF_FDXPTP)) 2193 zss->sl_flags &= ~SF_FLUSH_WQ; 2194 else { 2195 s0 = SCC_READ0(); 2196 if (s0 & ZSRR0_CTS) { 2197 zss->sl_rr0 |= ZSRR0_CTS; 2198 SCC_BIS(15, ZSR15_CTS); 2199 zss->sl_flags &= ~SF_FLUSH_WQ; 2200 zsh_setmstat(zs, CS_CTS_UP); 2201 } 2202 } 2203 } 2204 2205 switch (zss->sl_txstate) { 2206 2207 case TX_ABORTED: 2208 /* 2209 * Transmitter was hung ... try restarting it. 2210 */ 2211 if (zss->sl_flags & SF_FDXPTP) { 2212 zss->sl_flags |= SF_XMT_INPROG; 2213 (void) zsh_start(zs, zss); 2214 } else 2215 do_flushwq = 1; 2216 break; 2217 2218 case TX_ACTIVE: 2219 case TX_CRC: 2220 /* 2221 * Transmit is hung for some reason. Reset tx interrupt. 2222 * Flush transmit fifo by sending an abort command 2223 * which also sets the Underrun/EOM latch in WR0 and in 2224 * turn generates an External Status interrupt that 2225 * will reset the necessary message buffer pointers. 2226 * The watchdog timer will cycle again to allow the SCC 2227 * to settle down after the abort command. The next 2228 * time through we'll see that the state is now TX_ABORTED 2229 * and call zsh_start to grab a new message. 2230 */ 2231 if (--zss->sl_wd_count <= 0) { 2232 SCC_WRITE0(ZSWR0_SEND_ABORT); 2233 SCC_WRITE0(ZSWR0_RESET_ERRORS); 2234 SCC_WRITE0(ZSWR0_RESET_TXINT); 2235 zsh_txbad(zs, zss); 2236 zss->sl_txstate = TX_ABORTED; /* must be after txbad */ 2237 warning = 1; 2238 } 2239 break; 2240 2241 case TX_RTS: 2242 /* 2243 * Timer expired after we raised RTS. CTS never came up. 2244 */ 2245 zss->sl_st.cts++; 2246 2247 zsh_setmstat(zs, CS_CTS_TO); 2248 zss->sl_flags &= ~SF_XMT_INPROG; 2249 zss->sl_flags |= SF_FLUSH_WQ; 2250 ZSSETSOFT(zs); 2251 break; 2252 2253 default: 2254 /* 2255 * If we time out in an inactive state we set a soft 2256 * interrupt. This will call zsh_start which will 2257 * clear SF_XMT_INPROG if the queue is empty. 2258 */ 2259 break; 2260 } 2261 end_watchdog: 2262 if (zss->sl_txstate != TX_OFF) { 2263 mutex_exit(zs->zs_excl_hi); 2264 zss->sl_wd_id = timeout(zsh_watchdog, zs, SIO_WATCHDOG_TICK); 2265 } else { 2266 zss->sl_wd_id = 0; /* safety */ 2267 mutex_exit(zs->zs_excl_hi); 2268 } 2269 if (warning || do_flushwq) { 2270 flushq(wq, FLUSHDATA); 2271 mutex_enter(zs->zs_excl_hi); 2272 if ((mp = zss->sl_xstandby) != NULL) 2273 zss->sl_xstandby = NULL; 2274 mutex_exit(zs->zs_excl_hi); 2275 if (mp) 2276 freemsg(mp); 2277 } 2278 mutex_exit(zs->zs_excl); 2279 if (warning) 2280 cmn_err(CE_WARN, "zsh%x: transmit hung", zs->zs_unit); 2281 } 2282 2283 static void 2284 zsh_callback(void *arg) 2285 { 2286 struct zscom *zs = arg; 2287 struct syncline *zss = (struct syncline *)&zs->zs_priv_str; 2288 int tmp = ZSH_MAX_RSTANDBY; 2289 2290 mutex_enter(zs->zs_excl); 2291 if (zss->sl_bufcid) { 2292 zss->sl_bufcid = 0; 2293 ZSH_GETBLOCK(zs, tmp); 2294 } 2295 mutex_exit(zs->zs_excl); 2296 } 2297