1*53905Smckusick /* 2*53905Smckusick * Copyright (c) 1992 The Regents of the University of California. 3*53905Smckusick * All rights reserved. 4*53905Smckusick * 5*53905Smckusick * This code is derived from software contributed to Berkeley by 6*53905Smckusick * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. 7*53905Smckusick * 8*53905Smckusick * %sccs.include.redist.c% 9*53905Smckusick * 10*53905Smckusick * from: $Hdr: scc.c,v 4.300 91/06/09 06:44:53 root Rel41 $ SONY 11*53905Smckusick * 12*53905Smckusick * @(#)scc.c 7.1 (Berkeley) 06/04/92 13*53905Smckusick */ 14*53905Smckusick 15*53905Smckusick /* 16*53905Smckusick * LH8530 SCC (serial communication controller) driver 17*53905Smckusick * 18*53905Smckusick * NOTE: This driver is available only for news700/1200/1700/3400. 19*53905Smckusick * 20*53905Smckusick * Any code and mechanism in this module may not be used 21*53905Smckusick * in any form without permissions. COPYRIGHT (C) 1989- 22*53905Smckusick * SONY Corporation, Super Microsystems Group (SMSG), 23*53905Smckusick * Work Station Division, all rights RESERVED. 24*53905Smckusick */ 25*53905Smckusick 26*53905Smckusick #include "../include/fix_machine_type.h" 27*53905Smckusick #include "../include/adrsmap.h" 28*53905Smckusick 29*53905Smckusick #ifdef news700 30*53905Smckusick #include "ms.h" 31*53905Smckusick #include "bm.h" 32*53905Smckusick #else 33*53905Smckusick #include "rs.h" 34*53905Smckusick #endif 35*53905Smckusick 36*53905Smckusick #include "param.h" 37*53905Smckusick #include "ioctl.h" 38*53905Smckusick #include "tty.h" 39*53905Smckusick #include "malloc.h" 40*53905Smckusick 41*53905Smckusick #include "sccparam.h" 42*53905Smckusick #include "sccreg.h" 43*53905Smckusick #include "scc.h" 44*53905Smckusick #include "scc.conf" 45*53905Smckusick 46*53905Smckusick #define PROBE_DATA 0x55 47*53905Smckusick 48*53905Smckusick #ifdef mips 49*53905Smckusick #define VOLATILE volatile 50*53905Smckusick #else 51*53905Smckusick #define VOLATILE 52*53905Smckusick #endif 53*53905Smckusick 54*53905Smckusick int tty00_is_console = 0; 55*53905Smckusick 56*53905Smckusick #define SCC_BUFSIZE 256 57*53905Smckusick 58*53905Smckusick char scc_buf[2][SCC_BUFSIZE]; 59*53905Smckusick 60*53905Smckusick scc_open(chan) 61*53905Smckusick int chan; 62*53905Smckusick { 63*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 64*53905Smckusick register int s; 65*53905Smckusick 66*53905Smckusick s = splscc(); 67*53905Smckusick if ((scc->scc_status & CHAN_ACTIVE) == 0) { 68*53905Smckusick scc_init(chan); 69*53905Smckusick if (chan <= SCC_REMOTE1) 70*53905Smckusick scc->r_dma.dma_addr = scc_buf[chan]; 71*53905Smckusick else 72*53905Smckusick scc->r_dma.dma_addr = 73*53905Smckusick malloc(SCC_BUFSIZE, M_DEVBUF, M_WAITOK); 74*53905Smckusick scc->r_dma.dma_count = 0; 75*53905Smckusick scc->scc_status |= CHAN_ACTIVE; 76*53905Smckusick } 77*53905Smckusick (void) splx(s); 78*53905Smckusick return (0); 79*53905Smckusick } 80*53905Smckusick 81*53905Smckusick scc_probe(chan) 82*53905Smckusick register int chan; 83*53905Smckusick { 84*53905Smckusick VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 85*53905Smckusick int s, temp, probe; 86*53905Smckusick 87*53905Smckusick if (badaddr(port, 1)) 88*53905Smckusick return (0); 89*53905Smckusick s = splscc(); 90*53905Smckusick temp = scc_read_reg(chan, RR12); 91*53905Smckusick scc_write_reg(chan, WR12, PROBE_DATA); 92*53905Smckusick probe = scc_read_reg(chan, RR12); 93*53905Smckusick scc_write_reg(chan, WR12, temp); 94*53905Smckusick (void) splx(s); 95*53905Smckusick return (probe == PROBE_DATA); 96*53905Smckusick } 97*53905Smckusick 98*53905Smckusick scc_getc(chan) 99*53905Smckusick int chan; 100*53905Smckusick { 101*53905Smckusick VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 102*53905Smckusick int c; 103*53905Smckusick 104*53905Smckusick if (port->ctrl & R0_RxCA) { 105*53905Smckusick SCCWAIT; 106*53905Smckusick c = port->data; 107*53905Smckusick SCCWAIT; 108*53905Smckusick return (c); 109*53905Smckusick } 110*53905Smckusick SCCWAIT; 111*53905Smckusick return (-1); 112*53905Smckusick } 113*53905Smckusick 114*53905Smckusick #ifndef notdef 115*53905Smckusick scc_putc(chan, c) 116*53905Smckusick int chan, c; 117*53905Smckusick { 118*53905Smckusick register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 119*53905Smckusick 120*53905Smckusick while ((port->ctrl & R0_TxBE) == 0) 121*53905Smckusick SCCWAIT; 122*53905Smckusick SCCWAIT; 123*53905Smckusick port->data = c; 124*53905Smckusick SCCWAIT; 125*53905Smckusick } 126*53905Smckusick #else 127*53905Smckusick scc_putc(chan, c) 128*53905Smckusick int chan, c; 129*53905Smckusick { 130*53905Smckusick register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 131*53905Smckusick register VOLATILE u_char *ctrl = &sccsw[chan].scc_port->ctrl; 132*53905Smckusick register VOLATILE u_char *data = &sccsw[chan].scc_port->data; 133*53905Smckusick 134*53905Smckusick SCCWAIT; 135*53905Smckusick while ((*ctrl & R0_TxBE) == 0) { 136*53905Smckusick SCCWAIT; 137*53905Smckusick } 138*53905Smckusick SCCWAIT; 139*53905Smckusick 140*53905Smckusick *ctrl = W0_RES_TxINT; 141*53905Smckusick SCCWAIT; 142*53905Smckusick *data = (char)(c & 0xff); 143*53905Smckusick SCCWAIT; 144*53905Smckusick scc_write_reg(chan, WR1, W1_RxINT_ALL|W1_TxINTE|W1_EXTINTE|W1_PARITY); 145*53905Smckusick SCCWAIT; 146*53905Smckusick } 147*53905Smckusick #endif 148*53905Smckusick 149*53905Smckusick scc_init(chan) 150*53905Smckusick int chan; 151*53905Smckusick { 152*53905Smckusick register VOLATILE struct scc_reg *port; 153*53905Smckusick register char *data; 154*53905Smckusick register int i; 155*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 156*53905Smckusick int s; 157*53905Smckusick 158*53905Smckusick s = splscc(); 159*53905Smckusick data = scc->scc_init; 160*53905Smckusick port = scc->scc_port; 161*53905Smckusick for (i = 0; i < N_INITDATA; i++) { 162*53905Smckusick port->ctrl = *data++; 163*53905Smckusick SCCWAIT; 164*53905Smckusick } 165*53905Smckusick scc_write_reg(chan, WR2, scc->scc_vec & ~0x0f); 166*53905Smckusick /* KU:XXX 167*53905Smckusick This must be bug because scc->scc_param is not initialized yet. 168*53905Smckusick scc_set_param(chan, scc->scc_param); 169*53905Smckusick */ 170*53905Smckusick (void) splx(s); 171*53905Smckusick } 172*53905Smckusick 173*53905Smckusick #define vec_to_scc(vec) ((((vec) - SCCVEC0) >> 3) & 0x000f) 174*53905Smckusick #define vec_to_chan(vec) scc2chan[vec_to_scc(vec)] 175*53905Smckusick 176*53905Smckusick int scc2chan[] = { 177*53905Smckusick #ifdef news700 178*53905Smckusick 0, 1, 179*53905Smckusick #else /* news700 */ 180*53905Smckusick 1, 0, 181*53905Smckusick #endif /* news700 */ 182*53905Smckusick 3, 2, 183*53905Smckusick 5, 4, 184*53905Smckusick 7, 6, 185*53905Smckusick 9, 8 186*53905Smckusick }; 187*53905Smckusick 188*53905Smckusick #ifdef news700 189*53905Smckusick #define OFF 0x80 190*53905Smckusick 191*53905Smckusick scc_rint(vec) 192*53905Smckusick int vec; 193*53905Smckusick { 194*53905Smckusick int chan = vec_to_chan(vec); 195*53905Smckusick Scc_channel *scc = &sccsw[chan]; 196*53905Smckusick register struct scc_reg *port = scc->scc_port; 197*53905Smckusick register int c; 198*53905Smckusick #if NMS > 0 199*53905Smckusick extern int _ms_helper(); 200*53905Smckusick #endif /* NMS > 0 */ 201*53905Smckusick #if NBM > 0 202*53905Smckusick extern int kb_softint(); 203*53905Smckusick #endif /* NBM > 0 */ 204*53905Smckusick 205*53905Smckusick if ((scc->scc_status & CHAN_ACTIVE) == 0) { 206*53905Smckusick scc_reset(chan); 207*53905Smckusick goto out; 208*53905Smckusick } 209*53905Smckusick while (port->ctrl & R0_RxCA) { 210*53905Smckusick SCCWAIT; 211*53905Smckusick c = port->data; 212*53905Smckusick SCCWAIT; 213*53905Smckusick switch (chan) { 214*53905Smckusick 215*53905Smckusick case SCC_MOUSE: 216*53905Smckusick #if NMS > 0 217*53905Smckusick if (xputc(c, SCC_MOUSE) < 0) 218*53905Smckusick printf("mouse queue overflow\n"); 219*53905Smckusick softcall(_ms_helper, (caddr_t)0); 220*53905Smckusick #endif 221*53905Smckusick break; 222*53905Smckusick 223*53905Smckusick case SCC_KEYBOARD: 224*53905Smckusick #if NBM > 0 225*53905Smckusick if (xputc(c, SCC_KEYBOARD) < 0) 226*53905Smckusick printf("keyboard queue overflow\n"); 227*53905Smckusick softcall(kb_softint, (caddr_t)0); 228*53905Smckusick #endif 229*53905Smckusick break; 230*53905Smckusick 231*53905Smckusick default: 232*53905Smckusick printf("kb or ms stray intr\n"); 233*53905Smckusick break; 234*53905Smckusick } 235*53905Smckusick SCCWAIT; 236*53905Smckusick } 237*53905Smckusick out: 238*53905Smckusick port->ctrl = W0_RES_IUS; 239*53905Smckusick SCCWAIT; 240*53905Smckusick } 241*53905Smckusick #else /* news700 */ 242*53905Smckusick scc_rint(vec) 243*53905Smckusick int vec; 244*53905Smckusick { 245*53905Smckusick int chan = vec_to_chan(vec); 246*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 247*53905Smckusick register VOLATILE struct scc_reg *port = scc->scc_port; 248*53905Smckusick register int c; 249*53905Smckusick 250*53905Smckusick if ((scc->scc_status & CHAN_ACTIVE) == 0) { 251*53905Smckusick scc_reset(chan); 252*53905Smckusick goto out; 253*53905Smckusick } 254*53905Smckusick if (scc->scc_status & LINE_BREAK){ 255*53905Smckusick scc->scc_status &= ~LINE_BREAK; 256*53905Smckusick c = port->data; 257*53905Smckusick SCCWAIT; 258*53905Smckusick } 259*53905Smckusick while (port->ctrl & R0_RxCA) { 260*53905Smckusick SCCWAIT; 261*53905Smckusick c = port->data; 262*53905Smckusick SCCWAIT; 263*53905Smckusick #if NRS > 0 264*53905Smckusick scc_pdma(chan, c); 265*53905Smckusick #endif 266*53905Smckusick } 267*53905Smckusick SCCWAIT; 268*53905Smckusick out: 269*53905Smckusick port->ctrl = W0_RES_IUS; 270*53905Smckusick SCCWAIT; 271*53905Smckusick } 272*53905Smckusick #endif /* news700 */ 273*53905Smckusick 274*53905Smckusick #if NRS > 0 275*53905Smckusick scc_enable(chan) 276*53905Smckusick int chan; 277*53905Smckusick { 278*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 279*53905Smckusick int n; 280*53905Smckusick int s; 281*53905Smckusick 282*53905Smckusick s = splscc(); 283*53905Smckusick if ((n = scc->r_dma.dma_count) > 0) { 284*53905Smckusick scc->r_dma.dma_count = 0; 285*53905Smckusick rsrint(chan, scc->r_dma.dma_addr, n); 286*53905Smckusick } else 287*53905Smckusick scc->scc_status |= ENABLE; 288*53905Smckusick (void) splx(s); 289*53905Smckusick } 290*53905Smckusick 291*53905Smckusick scc_pdma(chan, c) 292*53905Smckusick int chan; 293*53905Smckusick int c; 294*53905Smckusick { 295*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 296*53905Smckusick int n; 297*53905Smckusick 298*53905Smckusick if (scc->r_dma.dma_count >= SCC_BUFSIZE) 299*53905Smckusick printf("rs%d soft fifo overflow\n", chan); 300*53905Smckusick else 301*53905Smckusick scc->r_dma.dma_addr[scc->r_dma.dma_count++] = c; 302*53905Smckusick if (scc->scc_status & ENABLE || scc->r_dma.dma_count >= SCC_BUFSIZE) { 303*53905Smckusick scc->scc_status &= ~ENABLE; 304*53905Smckusick n = scc->r_dma.dma_count; 305*53905Smckusick scc->r_dma.dma_count = 0; 306*53905Smckusick rsrint(chan, scc->r_dma.dma_addr, n); 307*53905Smckusick } 308*53905Smckusick } 309*53905Smckusick #endif /* NRS > 0 */ 310*53905Smckusick 311*53905Smckusick scc_xint(vec) 312*53905Smckusick int vec; 313*53905Smckusick { 314*53905Smckusick int chan = vec_to_chan(vec); 315*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 316*53905Smckusick register VOLATILE struct scc_reg *port = scc->scc_port; 317*53905Smckusick 318*53905Smckusick if (scc->scc_status & OSTOP) 319*53905Smckusick scc->scc_status &= ~(OACTIVE|OSTOP); 320*53905Smckusick if (scc->scc_status & OFLUSH) { 321*53905Smckusick scc->x_dma.dma_count = 0; 322*53905Smckusick scc->scc_status &= ~(OACTIVE|OFLUSH); 323*53905Smckusick } 324*53905Smckusick if ((scc->scc_status & OACTIVE) && (scc->x_dma.dma_count > 0)) { 325*53905Smckusick port->data = *(scc->x_dma.dma_addr)++; 326*53905Smckusick SCCWAIT; 327*53905Smckusick scc->x_dma.dma_count--; 328*53905Smckusick } else { 329*53905Smckusick port->ctrl = W0_RES_TxINT; 330*53905Smckusick SCCWAIT; 331*53905Smckusick scc->scc_status &= ~OACTIVE; 332*53905Smckusick #if NRS > 0 333*53905Smckusick if (scc->x_dma.dma_count == 0) 334*53905Smckusick rsxint(chan); 335*53905Smckusick #endif 336*53905Smckusick } 337*53905Smckusick port->ctrl = W0_RES_IUS; 338*53905Smckusick SCCWAIT; 339*53905Smckusick } 340*53905Smckusick 341*53905Smckusick scc_sint(vec) 342*53905Smckusick int vec; 343*53905Smckusick { 344*53905Smckusick int chan = vec_to_chan(vec); 345*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 346*53905Smckusick register VOLATILE struct scc_reg *port = scc->scc_port; 347*53905Smckusick register int status; 348*53905Smckusick register int param = 0; 349*53905Smckusick 350*53905Smckusick port->ctrl = W0_RES_EXT; 351*53905Smckusick SCCWAIT; 352*53905Smckusick if ((scc->scc_status & CHAN_ACTIVE) == 0) { 353*53905Smckusick scc_reset(chan); 354*53905Smckusick goto out; 355*53905Smckusick } 356*53905Smckusick status = port->ctrl; 357*53905Smckusick SCCWAIT; 358*53905Smckusick if (status & R0_DCD) 359*53905Smckusick param |= DCD; 360*53905Smckusick if (status & R0_CTS) 361*53905Smckusick param |= CTS; 362*53905Smckusick if (status & R0_BREAK){ 363*53905Smckusick param |= RBREAK; 364*53905Smckusick scc->scc_status |= LINE_BREAK; 365*53905Smckusick } 366*53905Smckusick if ((scc->scc_param & (DCD|CTS|RBREAK)) != param) { 367*53905Smckusick scc->scc_param = (scc->scc_param & ~(DCD|CTS|RBREAK)) | param; 368*53905Smckusick #if NRS > 0 369*53905Smckusick rssint(chan, scc->scc_param); 370*53905Smckusick #endif 371*53905Smckusick } 372*53905Smckusick out: 373*53905Smckusick port->ctrl = W0_RES_IUS; 374*53905Smckusick SCCWAIT; 375*53905Smckusick } 376*53905Smckusick 377*53905Smckusick scc_cint(vec) 378*53905Smckusick int vec; 379*53905Smckusick { 380*53905Smckusick int chan = vec_to_chan(vec); 381*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 382*53905Smckusick register VOLATILE struct scc_reg *port = scc->scc_port; 383*53905Smckusick register int status; 384*53905Smckusick int c; 385*53905Smckusick 386*53905Smckusick if ((scc->scc_status & CHAN_ACTIVE) == 0) { 387*53905Smckusick scc_reset(chan); 388*53905Smckusick goto out; 389*53905Smckusick } 390*53905Smckusick status = scc_read_reg(chan, RR1); 391*53905Smckusick if (status & R1_CRC) 392*53905Smckusick scc->scc_param |= FRAMING_ERROR; 393*53905Smckusick if (status & R1_OVRUN) { 394*53905Smckusick if ((scc->scc_param & OVERRUN_ERROR) == 0) { 395*53905Smckusick scc->scc_param |= OVERRUN_ERROR; 396*53905Smckusick #if NRS > 0 397*53905Smckusick rssint(chan, scc->scc_param); 398*53905Smckusick #endif /* NRS > 0 */ 399*53905Smckusick } 400*53905Smckusick } 401*53905Smckusick if (status & R1_PARITY) { 402*53905Smckusick scc->scc_param |= SCC_PARITY_ERROR; 403*53905Smckusick while (port->ctrl & R0_RxCA) { 404*53905Smckusick SCCWAIT; 405*53905Smckusick c = port->data; 406*53905Smckusick SCCWAIT; 407*53905Smckusick #if NRS > 0 408*53905Smckusick if (scc->scc_param & NOCHECK) 409*53905Smckusick scc_pdma(chan, c); 410*53905Smckusick #endif 411*53905Smckusick } 412*53905Smckusick SCCWAIT; 413*53905Smckusick } 414*53905Smckusick out: 415*53905Smckusick port->ctrl = W0_RES_ERROR; 416*53905Smckusick SCCWAIT; 417*53905Smckusick port->ctrl = W0_RES_IUS; 418*53905Smckusick SCCWAIT; 419*53905Smckusick } 420*53905Smckusick 421*53905Smckusick scc_write_reg(chan, reg, data) 422*53905Smckusick int chan, reg, data; 423*53905Smckusick { 424*53905Smckusick register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 425*53905Smckusick 426*53905Smckusick port->ctrl = reg; 427*53905Smckusick SCCWAIT; 428*53905Smckusick port->ctrl = data; 429*53905Smckusick SCCWAIT; 430*53905Smckusick } 431*53905Smckusick 432*53905Smckusick scc_read_reg(chan, reg) 433*53905Smckusick int chan, reg; 434*53905Smckusick { 435*53905Smckusick register VOLATILE struct scc_reg *port = sccsw[chan].scc_port; 436*53905Smckusick int result; 437*53905Smckusick 438*53905Smckusick port->ctrl = reg; 439*53905Smckusick SCCWAIT; 440*53905Smckusick result = port->ctrl; 441*53905Smckusick SCCWAIT; 442*53905Smckusick return (result); 443*53905Smckusick } 444*53905Smckusick 445*53905Smckusick #ifdef news1700 446*53905Smckusick #define DSRA 0x20 447*53905Smckusick #define RIA 0x04 448*53905Smckusick #define DSRB 0x02 449*53905Smckusick #define RIB 0x01 450*53905Smckusick 451*53905Smckusick #define DSRC 0x01 452*53905Smckusick #define RIC 0x02 453*53905Smckusick #define DSRD 0x04 454*53905Smckusick #define RID 0x08 455*53905Smckusick #define DSRE 0x10 456*53905Smckusick #define RIE 0x20 457*53905Smckusick #define DSRF 0x40 458*53905Smckusick #define RIF 0x80 459*53905Smckusick #endif /* news1700 */ 460*53905Smckusick 461*53905Smckusick #ifdef news1200 462*53905Smckusick #define DSRA 0x08 463*53905Smckusick #define RIA 0x04 464*53905Smckusick #define DSRB 0x02 465*53905Smckusick #define RIB 0x01 466*53905Smckusick #endif /* news1200 */ 467*53905Smckusick 468*53905Smckusick #ifdef news3400 469*53905Smckusick #define DSRA 0x01 470*53905Smckusick #define RIA 0x02 471*53905Smckusick #define DSRB 0x04 472*53905Smckusick #define RIB 0x08 473*53905Smckusick 474*53905Smckusick #define DSRC 0x01 475*53905Smckusick #define RIC 0x02 476*53905Smckusick #define DSRD 0x04 477*53905Smckusick #define RID 0x08 478*53905Smckusick #define DSRE 0x10 479*53905Smckusick #define RIE 0x20 480*53905Smckusick #define DSRF 0x40 481*53905Smckusick #define RIF 0x80 482*53905Smckusick #endif /* news3400 */ 483*53905Smckusick 484*53905Smckusick struct ri_dsr { 485*53905Smckusick char *status; 486*53905Smckusick int ri; 487*53905Smckusick int dsr; 488*53905Smckusick } ri_dsr[] = { 489*53905Smckusick #ifdef news700 490*53905Smckusick { (char *)0, 0, 0 } 491*53905Smckusick #else /* news700 */ 492*53905Smckusick { (char *)SCC_STATUS0, RIA, DSRA }, 493*53905Smckusick { (char *)SCC_STATUS0, RIB, DSRB }, 494*53905Smckusick #if !defined(news1200) && !defined(news3200) 495*53905Smckusick { (char *)SCC_STATUS1, RIC, DSRC }, 496*53905Smckusick { (char *)SCC_STATUS1, RID, DSRD }, 497*53905Smckusick { (char *)SCC_STATUS1, RIE, DSRE }, 498*53905Smckusick { (char *)SCC_STATUS1, RIF, DSRF }, 499*53905Smckusick { (char *)SCC_STATUS2, RIC, DSRC }, 500*53905Smckusick { (char *)SCC_STATUS2, RID, DSRD }, 501*53905Smckusick { (char *)SCC_STATUS2, RIE, DSRE }, 502*53905Smckusick { (char *)SCC_STATUS2, RIF, DSRF } 503*53905Smckusick #endif /* !news1200 && !news3200 */ 504*53905Smckusick #endif /* news700 */ 505*53905Smckusick }; 506*53905Smckusick 507*53905Smckusick get_ri_dsr(chan) 508*53905Smckusick int chan; 509*53905Smckusick { 510*53905Smckusick register struct ri_dsr *p; 511*53905Smckusick register int status, param; 512*53905Smckusick 513*53905Smckusick param = 0; 514*53905Smckusick #ifndef news700 515*53905Smckusick p = &ri_dsr[chan]; 516*53905Smckusick status = *p->status; 517*53905Smckusick if ((status & p->ri) == 0) 518*53905Smckusick param |= RI; 519*53905Smckusick if ((status & p->dsr) == 0) 520*53905Smckusick param |= DSR; 521*53905Smckusick #endif /* !news700 */ 522*53905Smckusick return (param); 523*53905Smckusick } 524*53905Smckusick 525*53905Smckusick #ifdef news700 526*53905Smckusick /* 527*53905Smckusick * tc = floor(5000000 / 32 / baudrate - 2 + 0.5); 528*53905Smckusick */ 529*53905Smckusick static int tc0[] = { 530*53905Smckusick 0, /* B0 */ 531*53905Smckusick 3123, /* B50 */ 532*53905Smckusick 2081, /* B75 */ 533*53905Smckusick 1418, /* B110 */ 534*53905Smckusick 1164, /* B134 */ 535*53905Smckusick 1039, /* B150 */ 536*53905Smckusick 779, /* B200 */ 537*53905Smckusick 518, /* B300 */ 538*53905Smckusick 258, /* B600 */ 539*53905Smckusick 128, /* B1200 */ 540*53905Smckusick 84, /* B1800 */ 541*53905Smckusick 63, /* B2400 */ 542*53905Smckusick 30, /* B4800 */ 543*53905Smckusick 14, /* B9600 */ 544*53905Smckusick 14, /* EXTA */ 545*53905Smckusick 14 /* EXTB */ 546*53905Smckusick }; 547*53905Smckusick #endif /* news700 */ 548*53905Smckusick 549*53905Smckusick #ifdef news1700 550*53905Smckusick /* 551*53905Smckusick * tc0 = floor(4000000 / 32 / baudrate - 2 + 0.5); 552*53905Smckusick */ 553*53905Smckusick static int tc0[] = { 554*53905Smckusick 0, /* B0 */ 555*53905Smckusick 2498, /* B50 */ 556*53905Smckusick 1664, /* B75 */ 557*53905Smckusick 1134, /* B110 */ 558*53905Smckusick 930, /* B134 */ 559*53905Smckusick 831, /* B150 */ 560*53905Smckusick 623, /* B200 */ 561*53905Smckusick 414, /* B300 */ 562*53905Smckusick 206, /* B600 */ 563*53905Smckusick 102, /* B1200 */ 564*53905Smckusick 67, /* B1800 */ 565*53905Smckusick 50, /* B2400 */ 566*53905Smckusick 24, /* B4800 */ 567*53905Smckusick 11, /* B9600 */ 568*53905Smckusick 11, /* EXTA (B9600)*/ 569*53905Smckusick 11 /* EXTB (B9600)*/ 570*53905Smckusick }; 571*53905Smckusick #endif /* news1700 */ 572*53905Smckusick 573*53905Smckusick #if defined(news1200) || defined(news3400) 574*53905Smckusick /* 575*53905Smckusick * tc0 = floor(4915200 / 32 / baudrate - 2 + 0.5); 576*53905Smckusick */ 577*53905Smckusick static int tc0[] = { 578*53905Smckusick 0, /* B0 */ 579*53905Smckusick 3070, /* B50 */ 580*53905Smckusick 2046, /* B75 */ 581*53905Smckusick 1394, /* B110 */ 582*53905Smckusick 1144, /* B134 */ 583*53905Smckusick 1022, /* B150 */ 584*53905Smckusick 766, /* B200 */ 585*53905Smckusick 510, /* B300 */ 586*53905Smckusick 254, /* B600 */ 587*53905Smckusick 126, /* B1200 */ 588*53905Smckusick 83, /* B1800 */ 589*53905Smckusick 62, /* B2400 */ 590*53905Smckusick 30, /* B4800 */ 591*53905Smckusick 14, /* B9600 */ 592*53905Smckusick 6, /* EXTA (B19200) */ 593*53905Smckusick 2 /* EXTB (B38400) */ 594*53905Smckusick }; 595*53905Smckusick #endif /* news1200 || news3400 */ 596*53905Smckusick 597*53905Smckusick #ifndef news700 598*53905Smckusick static int tc1[] = { 599*53905Smckusick /* 600*53905Smckusick * tc1 = floor(3686400 / 32 / baudrate - 2 + 0.5); 601*53905Smckusick */ 602*53905Smckusick 0, /* B0 */ 603*53905Smckusick 2302, /* B50 */ 604*53905Smckusick 1534, /* B75 */ 605*53905Smckusick 1045, /* B110 */ 606*53905Smckusick 858, /* B134 */ 607*53905Smckusick 766, /* B150 */ 608*53905Smckusick 574, /* B200 */ 609*53905Smckusick 382, /* B300 */ 610*53905Smckusick 190, /* B600 */ 611*53905Smckusick 94, /* B1200 */ 612*53905Smckusick 62, /* B1800 */ 613*53905Smckusick 46, /* B2400 */ 614*53905Smckusick 22, /* B4800 */ 615*53905Smckusick 10, /* B9600 */ 616*53905Smckusick 4, /* B19200 */ 617*53905Smckusick 1, /* B38400 */ 618*53905Smckusick }; 619*53905Smckusick #endif /* !news700 */ 620*53905Smckusick 621*53905Smckusick scc_set_param(chan, param) 622*53905Smckusick int chan; 623*53905Smckusick register int param; 624*53905Smckusick { 625*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 626*53905Smckusick register int bit, baud, *tc; 627*53905Smckusick int s; 628*53905Smckusick 629*53905Smckusick s = splscc(); 630*53905Smckusick 631*53905Smckusick /* 632*53905Smckusick * Baud rate / external clock 633*53905Smckusick */ 634*53905Smckusick if ((baud = param & BAUD_RATE) == EXTB && chan <= SCC_REMOTE1 && 635*53905Smckusick param & EXTCLK_ENABLE) { 636*53905Smckusick scc_write_reg(chan, WR11, W11_RxC_RTxC|W11_TxC_TRxC); 637*53905Smckusick bit = W4_X1; 638*53905Smckusick } else { 639*53905Smckusick #ifdef news700 640*53905Smckusick tc = tc0; 641*53905Smckusick #else /* news700 */ 642*53905Smckusick tc = (chan <= SCC_REMOTE1) ? tc0 : tc1; 643*53905Smckusick #endif /* news700 */ 644*53905Smckusick scc_write_reg(chan, WR11, W11_RxC_BRG|W11_TxC_BRG); 645*53905Smckusick scc_write_reg(chan, WR12, tc[baud] & 0xff); 646*53905Smckusick scc_write_reg(chan, WR13, tc[baud] >> 8); 647*53905Smckusick bit = W4_X16; 648*53905Smckusick } 649*53905Smckusick 650*53905Smckusick /* 651*53905Smckusick * Clock mode / parity / stop bit 652*53905Smckusick */ 653*53905Smckusick if (param & PARITY) { 654*53905Smckusick bit |= W4_PARITY; 655*53905Smckusick if (param & EVEN) 656*53905Smckusick bit |= W4_EVEN; 657*53905Smckusick } 658*53905Smckusick switch (param & STOPBIT) { 659*53905Smckusick 660*53905Smckusick case STOP1: 661*53905Smckusick bit |= W4_STOP1; 662*53905Smckusick break; 663*53905Smckusick 664*53905Smckusick case STOP1_5: 665*53905Smckusick bit |= W4_STOP1_5; 666*53905Smckusick break; 667*53905Smckusick 668*53905Smckusick case STOP2: 669*53905Smckusick bit |= W4_STOP2; 670*53905Smckusick break; 671*53905Smckusick 672*53905Smckusick } 673*53905Smckusick scc_write_reg(chan, WR4, bit); 674*53905Smckusick 675*53905Smckusick /* 676*53905Smckusick * Receiver enable / receive character size / auto enable 677*53905Smckusick */ 678*53905Smckusick bit = (param & RXE ? W3_RxE : 0); 679*53905Smckusick switch (param & CHAR_SIZE) { 680*53905Smckusick 681*53905Smckusick case C5BIT: 682*53905Smckusick break; 683*53905Smckusick 684*53905Smckusick case C6BIT: 685*53905Smckusick bit |= W3_Rx6BIT; 686*53905Smckusick break; 687*53905Smckusick 688*53905Smckusick case C7BIT: 689*53905Smckusick bit |= W3_Rx7BIT; 690*53905Smckusick break; 691*53905Smckusick 692*53905Smckusick case C8BIT: 693*53905Smckusick bit |= W3_Rx8BIT; 694*53905Smckusick break; 695*53905Smckusick } 696*53905Smckusick #ifdef AUTO_ENABLE 697*53905Smckusick if (param & AUTO_ENABLE) 698*53905Smckusick bit |= W3_AUTO; 699*53905Smckusick #endif /* AUTO_ENABLE */ 700*53905Smckusick scc_write_reg(chan, WR3, bit); 701*53905Smckusick 702*53905Smckusick /* 703*53905Smckusick * Transmitter enable / transmit character size / RTS / DTR / BREAK 704*53905Smckusick */ 705*53905Smckusick bit = (param & TXE ? W5_TxE : 0); 706*53905Smckusick switch (param & CHAR_SIZE) { 707*53905Smckusick 708*53905Smckusick case C5BIT: 709*53905Smckusick break; 710*53905Smckusick 711*53905Smckusick case C6BIT: 712*53905Smckusick bit |= W5_Tx6BIT; 713*53905Smckusick break; 714*53905Smckusick 715*53905Smckusick case C7BIT: 716*53905Smckusick bit |= W5_Tx7BIT; 717*53905Smckusick break; 718*53905Smckusick 719*53905Smckusick case C8BIT: 720*53905Smckusick bit |= W5_Tx8BIT; 721*53905Smckusick break; 722*53905Smckusick } 723*53905Smckusick if (param & RTS) 724*53905Smckusick bit |= W5_RTS; 725*53905Smckusick if (param & DTR) 726*53905Smckusick bit |= W5_DTR; 727*53905Smckusick if (param & XBREAK) 728*53905Smckusick bit |= W5_BREAK; 729*53905Smckusick scc_write_reg(chan, WR5, bit); 730*53905Smckusick scc->scc_param = param; 731*53905Smckusick (void) splx(s); 732*53905Smckusick return (0); 733*53905Smckusick } 734*53905Smckusick 735*53905Smckusick scc_get_param(chan) 736*53905Smckusick int chan; 737*53905Smckusick { 738*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 739*53905Smckusick 740*53905Smckusick scc->scc_param = (scc->scc_param & ~(RI|DSR)) | get_ri_dsr(chan); 741*53905Smckusick return (scc->scc_param); 742*53905Smckusick } 743*53905Smckusick 744*53905Smckusick scc_get_status(chan) 745*53905Smckusick int chan; 746*53905Smckusick { 747*53905Smckusick 748*53905Smckusick return (sccsw[chan].scc_status); 749*53905Smckusick } 750*53905Smckusick 751*53905Smckusick scc_set_status(chan, stat) 752*53905Smckusick int chan, stat; 753*53905Smckusick { 754*53905Smckusick 755*53905Smckusick sccsw[chan].scc_status = stat; 756*53905Smckusick 757*53905Smckusick return (0); 758*53905Smckusick } 759*53905Smckusick 760*53905Smckusick scc_flush(chan) 761*53905Smckusick int chan; 762*53905Smckusick { 763*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 764*53905Smckusick 765*53905Smckusick if (scc->scc_status & OACTIVE) 766*53905Smckusick scc->scc_status |= OFLUSH; 767*53905Smckusick else if (scc->x_dma.dma_count > 0) { 768*53905Smckusick scc->x_dma.dma_count = 0; 769*53905Smckusick #if NRS > 0 770*53905Smckusick rsxint(chan); 771*53905Smckusick #endif 772*53905Smckusick } 773*53905Smckusick return (0); 774*53905Smckusick } 775*53905Smckusick 776*53905Smckusick scc_start(chan) 777*53905Smckusick int chan; 778*53905Smckusick { 779*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 780*53905Smckusick 781*53905Smckusick if ((scc->scc_status & OACTIVE) == 0 && scc->x_dma.dma_count > 0) { 782*53905Smckusick scc->scc_port->data = *(scc->x_dma.dma_addr)++; 783*53905Smckusick SCCWAIT; 784*53905Smckusick scc->x_dma.dma_count--; 785*53905Smckusick scc->scc_status |= OACTIVE; 786*53905Smckusick } 787*53905Smckusick return (0); 788*53905Smckusick } 789*53905Smckusick 790*53905Smckusick scc_stop(chan) 791*53905Smckusick int chan; 792*53905Smckusick { 793*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 794*53905Smckusick 795*53905Smckusick if (scc->scc_status & OACTIVE) 796*53905Smckusick scc->scc_status |= OSTOP; 797*53905Smckusick return (0); 798*53905Smckusick } 799*53905Smckusick 800*53905Smckusick scc_write(chan, buf, count) 801*53905Smckusick int chan; 802*53905Smckusick caddr_t buf; 803*53905Smckusick int count; 804*53905Smckusick { 805*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 806*53905Smckusick 807*53905Smckusick if (count <= 0) 808*53905Smckusick return (0); 809*53905Smckusick scc->x_dma.dma_addr = buf; 810*53905Smckusick scc->x_dma.dma_count = count; 811*53905Smckusick scc_start(chan); 812*53905Smckusick return (count); 813*53905Smckusick } 814*53905Smckusick 815*53905Smckusick scc_error_write(chan, buf, count) 816*53905Smckusick int chan; 817*53905Smckusick register char *buf; 818*53905Smckusick register int count; 819*53905Smckusick { 820*53905Smckusick register int i; 821*53905Smckusick 822*53905Smckusick for (i = 0; i < count; i++) 823*53905Smckusick scc_putc(chan, *buf++); 824*53905Smckusick return (i); 825*53905Smckusick } 826*53905Smckusick 827*53905Smckusick scc_reset(chan) 828*53905Smckusick int chan; 829*53905Smckusick { 830*53905Smckusick register Scc_channel *scc = &sccsw[chan]; 831*53905Smckusick 832*53905Smckusick while (scc_getc(chan) != -1) 833*53905Smckusick ; 834*53905Smckusick scc->scc_status &= ~CHAN_ACTIVE; 835*53905Smckusick } 836