[BACK]Return to scn.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / pc532 / dev

Annotation of src/sys/arch/pc532/dev/scn.c, Revision 1.22

1.22    ! phil        1: /*     $NetBSD: scn.c,v 1.21 1995/08/30 23:51:40 phil Exp $ */
1.12      cgd         2:
1.19      phil        3: /*
1.1       phil        4:  * Copyright (c) 1991 The Regents of the University of California.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  *
1.12      cgd        35:  *     @(#)com.c       7.5 (Berkeley) 5/16/91
1.1       phil       36:  */
                     37:
                     38: #include "scn.h"
                     39:
                     40: #if NSCN > 0
                     41:
1.5       phil       42: /* #define KERN_MORE */
                     43:
1.1       phil       44: /* The pc532 has 4 duarts! */
                     45: #define NLINES 8
                     46:
                     47: /*
                     48:  * scn2681 driver for the pc532.  Phil Nelson  Feb 8, 1993
                     49:  *
                     50:  */
1.11      phil       51: #include <sys/param.h>
                     52: #include <sys/systm.h>
                     53: #include <sys/ioctl.h>
                     54: #include <sys/select.h>
                     55: #include <sys/tty.h>
                     56: #include <sys/proc.h>
                     57: #include <sys/user.h>
                     58: #include <sys/conf.h>
                     59: #include <sys/file.h>
                     60: #include <sys/uio.h>
                     61: #include <sys/kernel.h>
                     62: #include <sys/syslog.h>
                     63: #include <sys/types.h>
1.13      phil       64: #include <sys/device.h>
1.11      phil       65:
                     66: #include <dev/cons.h>
                     67:
                     68: #include <machine/icu.h>
1.1       phil       69:
                     70: #include "scnreg.h"
                     71:
                     72: #include "sl.h"
                     73:
1.16      phil       74: struct scn_softc {
                     75:        struct device      scn_dev;
                     76:        struct tty        *scn_tty;
                     77:        struct rs232_s     scn_line;
                     78:        char               scn_swflags;
                     79: #define SCN_SW_SOFTCAR 0x01
                     80: #define SCN_SW_CLOCAL  0x02
                     81: #define SCN_SW_CRTSCTS 0x04
                     82: };
                     83:
                     84: int    scnprobe __P((struct device *, void *, void *));
                     85: void    scnattach __P((struct device *, struct device *, void *));
                     86: int     scnintr __P((int));
                     87: int    scnparam __P((struct tty *, struct termios *));
                     88: void   scnstart __P((struct tty *));
                     89: int    scnopen __P((dev_t, int, int, struct proc *));
                     90: int    scnclose __P((dev_t, int, int, struct proc *));
1.1       phil       91:
1.13      phil       92: struct cfdriver scncd =
                     93:       {        NULL, "scn", scnprobe, scnattach,
1.16      phil       94:        DV_TTY, sizeof(struct scn_softc), NULL, 0 };
1.1       phil       95:
1.16      phil       96: /* int scnsoftCAR;
                     97: int    scn_active;  To Be Deleted ... */
1.1       phil       98: int    scnconsole = SCN_CONSOLE;
1.5       phil       99: int    scnconsinit = 0;
1.1       phil      100: int    scndefaultrate = TTYDEF_SPEED;
                    101: int    scnmajor;
                    102:
                    103: struct duart_info  uart[(NLINES+1)/2];
1.16      phil      104: /* struct rs232_s line[NLINES];
                    105:    struct tty *scn_tty[NLINES];  To be deleted. */
1.1       phil      106:
                    107: struct speedtab scnspeedtab[] = {
                    108:        0,      0x40,   /* code for line-hangup */
                    109:        50,     0x00,
                    110:        75,     0x10,
                    111:        110,    0x21,
                    112:        134,    0x22,
                    113:        150,    0x13,
                    114:        200,    0x03,
                    115:        300,    0x24,
                    116:        600,    0x25,
                    117:        1050,   0x07,
                    118:        1200,   0x26,
                    119:        1800,   0x1a,
                    120:        2000,   0x17,
                    121:        2400,   0x28,
                    122:        4800,   0x29,
                    123:        7200,   0x0a,
                    124:        9600,   0x2b,
                    125:        19200,  0x1c,
                    126:        38400,  0x0c,
                    127:        57600,  0x60,   /* An illegal speed....? */
                    128:        -1,     -1
                    129: };
                    130:
                    131: #define getspeedcode(sp,val) \
                    132:        { int i=0; \
                    133:          while (scnspeedtab[i].sp_speed != -1 && \
                    134:                 scnspeedtab[i].sp_speed != sp) \
                    135:            i++; \
                    136:          val = scnspeedtab[i].sp_code; \
                    137:        }
                    138:
                    139: /* Unit is 0-7. Other parts of the minor number are things like
1.5       phil      140:    hardware cts/rts handshaking.  (XXX how?) */
                    141:
1.1       phil      142: #define UNIT(x)        (minor(x) & 0x7)
                    143:
                    144: /* Which uart is the device on? */
                    145: #define UART(x) (UNIT(x) >> 1)
                    146:
                    147: extern struct tty *constty;
                    148:
                    149: #ifdef KGDB
                    150: #include "machine/remote-sl.h"
                    151:
                    152: extern int kgdb_dev;
                    153: extern int kgdb_rate;
                    154: extern int kgdb_debug_init;
                    155: #endif
                    156:
                    157:
                    158: /* Debug routine to print out the rs line structures. */
1.16      phil      159: void print_rs (struct rs232_s *rs)
1.1       phil      160: {
                    161:   printf ("\nline frame overrun parity break\n");
                    162:   printf ("tty%1d state=%2x  f=%2d o=%2d p=%2d b=%2d in=%x, out=%x grp=%d\n",
1.16      phil      163:              rs->unit, rs->framing_errors, rs->overrun_errors,
1.1       phil      164:             rs->parity_errors, rs->break_interrupts,
                    165:             rs->uart->i_speed[rs->a_or_b], rs->uart->o_speed[rs->a_or_b],
                    166:             rs->uart->speed_grp);
                    167: }
                    168:
                    169:
                    170: /*==========================================================================*
                    171:  *                             scn_config                                  *
                    172:  *==========================================================================*/
                    173: static
                    174: int scn_config(unit, in_speed, out_speed, parity, stop_bits, data_bits )
                    175: int unit;                      /* which rs line */
                    176: int in_speed;                  /* input speed: 110, 300, 1200, etc */
                    177: int out_speed;                 /* output speed: 110, 300, 1200, etc */
                    178: int parity;                    /* some parity */
                    179: int stop_bits;                 /* 2 (110 baud) or 1 (other speeds) */
                    180: int data_bits;                 /* 5, 6, 7, or 8 */
                    181: {
                    182: /* Set various line control parameters for RS232 I/O. */
                    183:
                    184:   register struct rs232_s *rs;
                    185:   char mr1_val, mr2_val;
                    186:   int  sp_grp, sp_both;
                    187:   char set_speed;            /* Non zero if we need to set the speed. */
                    188:   char a_or_b;               /* Used for ease of access. */
                    189:   int in_code;
                    190:   int out_code;
                    191:   int x;
                    192:
                    193:   /* Get the speed codes. */
                    194:   getspeedcode(in_speed,in_code);
                    195:   getspeedcode(out_speed,out_code);
                    196:
                    197:   /* Check for speed errors. */
                    198:   if (in_code == -1 || out_code == -1)
                    199:     return (EINVAL);
                    200:
                    201:   /* Set up rs pointer. */
1.16      phil      202:   if (unit >= scncd.cd_ndevs)
                    203:        return  ENXIO;
                    204:   rs = &((struct scn_softc *)scncd.cd_devs[unit])->scn_line;
1.1       phil      205:   a_or_b = rs->a_or_b;
                    206:
                    207:   /* Check out the Speeds. There are two groups of speeds.  If the new
                    208:      speeds are not in the same group, or the other line is not the same
                    209:      speed of the other group, do not change the speeds.  Also, if the
                    210:      in speed and the out speed are in different groups, use the in speed. */
                    211:
                    212:   set_speed = FALSE;
                    213:   if ( (in_code != rs->uart->i_code[a_or_b])
                    214:       || (out_code != rs->uart->o_code[a_or_b])) {
                    215:
                    216:     /* We need to set the speeds .*/
                    217:     set_speed = TRUE;
                    218:
                    219:     if ( ((in_code & LC_SP_GRP) != (out_code & LC_SP_GRP))
                    220:        && (((in_code | out_code) & LC_SP_BOTH) != 1) ) {
                    221:       /* Input speed and output speed are different groups. */
                    222:       return (EINVAL);
                    223:     }
                    224:
                    225:     sp_grp = ((in_code | out_code) & LC_SP_GRP)>>4;
                    226:     sp_both = in_code & out_code & LC_SP_BOTH;
                    227:
                    228:     /* Check for compatibility and set the uart values */
                    229:     if (sp_both)
                    230:       sp_grp = rs->uart->speed_grp;
                    231:     else
                    232:       if ((sp_grp != rs->uart->speed_grp)
                    233:          && !(rs->uart->i_code[1-a_or_b] & rs->uart->o_code[1-a_or_b]
                    234:               & LC_SP_BOTH)) {
                    235:        /* Can't change group, don`t change the speed rates. */
                    236:        return (EINVAL);
                    237:       }
                    238:     rs->uart->i_code[a_or_b] = in_code;
                    239:     rs->uart->o_code[a_or_b] = out_code;
                    240:     rs->uart->i_speed[a_or_b] = in_speed;
                    241:     rs->uart->o_speed[a_or_b] = out_speed;
                    242:   }
                    243:
                    244:   /* Lock out interrupts while setting the parameters.  (Just for safety.)
                    245:    */
                    246:   x=spltty();
                    247:   WR_ADR (u_char, rs->cmd_port, CMD_MR1);
                    248:   mr1_val = RD_ADR (u_char, rs->mr_port);
                    249:   mr2_val = RD_ADR (u_char, rs->mr_port);
                    250:   if ((((mr1_val & 0xe0) | parity | data_bits) != mr1_val) ||
                    251:       (((mr2_val & 0xf0) | stop_bits) != mr2_val)) {
                    252:     WR_ADR (u_char, rs->cmd_port, CMD_MR1);
                    253:     WR_ADR (u_char, rs->mr_port, (mr1_val & 0xe0) | parity | data_bits);
                    254:     WR_ADR (u_char, rs->mr_port, (mr2_val & 0xf0) | stop_bits);
                    255:   }
                    256:   if (set_speed) {
                    257:     if (rs->uart->speed_grp != sp_grp) {
                    258:        /* Change the group! */
                    259:        rs->uart->speed_grp = sp_grp;
                    260:        WR_ADR (u_char, rs->acr_port, (sp_grp << 7) | rs->uart->acr_int_bits);
                    261:     }
                    262:     WR_ADR (u_char, rs->speed_port, ((in_code & 0x0f) << 4)
                    263:                                        | (out_code & 0x0f));
                    264:   }
                    265:   DELAY(96000/out_speed);
                    266:
                    267:   splx(x);
                    268:   return (0);
                    269: }
                    270:
                    271:
1.13      phil      272: scnprobe(parent, cf, aux)
                    273:        struct device   *parent;
1.16      phil      274:        void            *cf;
1.13      phil      275:        void            *aux;
1.1       phil      276: {
1.16      phil      277:   int unit = ((struct cfdata *)cf)->cf_unit;
1.5       phil      278:
                    279:   if (unit >= NLINES) {
                    280:     return(0);  /* dev is "not working." */
                    281:   } else {
                    282:     return(1);  /* dev is "working." */
1.1       phil      283:   }
                    284: }
                    285:
1.13      phil      286: void
1.16      phil      287: scnattach(parent, self, aux)
                    288:        struct device   *parent, *self;
1.13      phil      289:        void            *aux;
1.1       phil      290: {
1.17      phil      291:   static char scnints[4] = { IR_TTY0, IR_TTY1, IR_TTY2, IR_TTY3 };
1.16      phil      292:   struct  scn_softc *sc = (void *) self;
                    293:   struct  tty  *tp;
                    294:   u_char  unit = sc->scn_dev.dv_unit;
                    295:   u_char  duart = unit >> 1;
                    296:   register struct rs232_s *rs = &sc->scn_line;
1.1       phil      297:   int  x;
                    298:   int speed;
                    299:   long line_base;
                    300:   long uart_base;
                    301:   long scn_first_adr;
                    302:
                    303:   if (unit == 0)  DELAY(5);  /* Let the output go out.... */
                    304:
1.16      phil      305:   sc->scn_swflags |= SCN_SW_SOFTCAR;
1.1       phil      306:
                    307:   /* Record unit number, uart, channel a_or_b. */
                    308:   rs->unit = unit;
1.17      phil      309:   rs->uart = &uart[unit >> 1];
1.1       phil      310:   rs->a_or_b = unit % 2;
                    311:
1.17      phil      312:   /* Establish interrupt vector */
                    313:   if (rs->a_or_b == 0) {
                    314:     /* Arg 0 is special, so we must pass "unit + 1" */
                    315:     intr_establish(scnints[unit >> 1], (void (*)(void *))scnintr,
1.20      phil      316:        (void *)(unit + 1), sc->scn_dev.dv_xname, IPL_TTY, FALLING_EDGE);
1.17      phil      317:   }
                    318:
1.1       phil      319:   /* Precalculate port numbers for speed. Magic numbers in the code (once). */
                    320:   scn_first_adr = SCN_FIRST_MAP_ADR;  /* to get around a gcc bug. */
                    321:   line_base = scn_first_adr + LINE_SZ * unit;
                    322:   uart_base = scn_first_adr + UART_SZ * duart;
                    323:   rs->xmit_port = DATA_ADR;
                    324:   rs->recv_port = DATA_ADR;
                    325:   rs->mr_port = MR_ADR;
                    326:   rs->stat_port = STAT_ADR;
                    327:   rs->speed_port = SPEED_ADR;
                    328:   rs->cmd_port = CMD_ADR;
                    329:   rs->acr_port = ACR_ADR;
                    330:   rs->ip_port = IP_ADR;
                    331:   rs->opset_port = SET_OP_ADR;
                    332:   rs->opclr_port = CLR_OP_ADR;
                    333:
                    334:   /* Initialize error counts */
                    335:   rs->framing_errors = 0;
                    336:   rs->overrun_errors = 0;
                    337:   rs->parity_errors = 0;
                    338:   rs->break_interrupts = 0;
                    339:
                    340:   /* Set up the hardware to a base state, in particular
                    341:    *   o reset transmitter and receiver
                    342:    *   o set speeds and configurations
                    343:    *   o receiver interrupts only (RxRDY and BREAK)
                    344:    */
                    345:
                    346:   x = spltty();
                    347:   istop(rs);                   /* CTS off... */
                    348:
                    349:   WR_ADR (u_char, rs->cmd_port, CMD_DIS_RX | CMD_DIS_TX);
                    350:   WR_ADR (u_char, rs->cmd_port, CMD_RESET_RX);
                    351:   WR_ADR (u_char, rs->cmd_port, CMD_RESET_TX);
                    352:   WR_ADR (u_char, rs->cmd_port, CMD_RESET_ERR);
                    353:   WR_ADR (u_char, rs->cmd_port, CMD_RESET_BRK);
                    354:   WR_ADR (u_char, rs->cmd_port, CMD_MR1);
                    355:   WR_ADR (u_char, rs->mr_port, 0);     /* No receiver control of RTS. */
                    356:   WR_ADR (u_char, rs->mr_port, 0);
1.8       phil      357: #if 1
                    358:   if (unit != 0) {
                    359:     WR_ADR (u_char, rs->mr_port, 0x80);  /* Enable receiver control of RTS */
                    360:     WR_ADR (u_char, rs->mr_port, 0x10);  /* Enable CTS transmitter control */
                    361:   }
1.1       phil      362: #endif
                    363:
                    364:   /* Initialize the uart structure if this is channel A. */
                    365:   if (rs->a_or_b == 0) {
                    366:     /* uart ports */
                    367:     rs->uart->isr_port = ISR_ADR;
                    368:     rs->uart->imr_port = IMR_ADR;
                    369:     rs->uart->ipcr_port = IPCR_ADR;
                    370:     rs->uart->opcr_port = OPCR_ADR;
                    371:
                    372:     /* Disable all interrupts. */
                    373:     WR_ADR (u_char, rs->uart->imr_port, 0);
                    374:     rs->uart->imr_int_bits = 0;
                    375:
                    376:     /* Output port config */
                    377:     WR_ADR (u_char, rs->uart->opcr_port, 0);
                    378:
                    379:     /* Speeds... */
                    380:     rs->uart->speed_grp = 1;
                    381:     rs->uart->acr_int_bits = 0;
                    382:     /* Set initial speed to an illegal code that can be changed to
                    383:        any other baud. */
                    384:     rs->uart->i_code[0] = rs->uart->o_code[0] =
                    385:       rs->uart->i_code[1] = rs->uart->o_code[1] = 0x2f;
                    386:     rs->uart->i_speed[0] = rs->uart->o_speed[0] =
                    387:       rs->uart->i_speed[1] = rs->uart->o_speed[1] = 0x0;
                    388:   }
                    389:
                    390: #if 0
                    391:   rs->uart->acr_int_bits |= ACR_CTS << rs->a_or_b;     /* Set CTS int */
                    392: #endif
                    393:   WR_ADR (u_char, rs->acr_port,
                    394:         (rs->uart->speed_grp << 7) | rs->uart->acr_int_bits);
1.22    ! phil      395:   scn_config(unit, scndefaultrate, scndefaultrate,
1.1       phil      396:         LC_NONE, LC_STOP1, LC_BITS8);
                    397:
                    398:   /* Turn on the Rx and Tx. */
                    399:   WR_ADR (u_char, rs->cmd_port, CMD_ENA_RX | CMD_ENA_TX);
                    400:
                    401:   /* Set up the interrupts. */
                    402:   rs->uart->imr_int_bits
1.19      phil      403:      |= (/*IMR_RX_INT | IMR_TX_INT |*/ unit?IMR_BRK_INT:0) << (4*rs->a_or_b) | IMR_IP_INT;
1.1       phil      404:   WR_ADR (u_char, rs->uart->imr_port, rs->uart->imr_int_bits);
                    405:
                    406:   splx(x);
                    407:
                    408: #ifdef KGDB
                    409:        if (kgdb_dev == makedev(scnmajor, unit+1)) {
                    410:                if (scnconsole == unit)
                    411:                        kgdb_dev = -1;  /* can't debug over console port */
                    412:                else {
                    413:                        (void) scninit(unit, kgdb_rate);
                    414:                        if (kgdb_debug_init) {
                    415:                                /*
                    416:                                 * Print prefix of device name,
                    417:                                 * let kgdb_connect print the rest.
                    418:                                 */
                    419:                                printf("scn%d: ", unit);
                    420:                                kgdb_connect(1);
                    421:                        } else
                    422:                                printf("scn%d: kgdb enabled\n", unit);
                    423:                }
                    424:        }
                    425: #endif
                    426:
1.4       phil      427:   /* print the device number... */
1.13      phil      428:   printf (" addr 0x%x\n", line_base);
1.1       phil      429: }
                    430:
                    431: /* ARGSUSED */
                    432: scnopen(dev_t dev, int flag, int mode, struct proc *p)
                    433: {
1.16      phil      434:        struct  scn_softc *sc;
1.1       phil      435:        register struct tty *tp;
                    436:        register int unit = UNIT(dev);
1.16      phil      437:        register struct rs232_s *rs;
1.1       phil      438:        int error = 0;
1.7       phil      439:        int x;
                    440:
1.16      phil      441:        /* Set up rs pointer. */
                    442:        if (unit >= scncd.cd_ndevs)
                    443:                return ENXIO;
                    444:        sc = scncd.cd_devs[unit];
                    445:        if (!sc)
                    446:                return ENXIO;
                    447:        rs = &sc->scn_line;
1.7       phil      448:
                    449:        x = spltty();
                    450:
1.16      phil      451:        if(!sc->scn_tty) {
                    452:                tp = sc->scn_tty = ttymalloc();
1.1       phil      453:        } else
1.16      phil      454:                tp = sc->scn_tty;
                    455:
1.1       phil      456:        tp->t_oproc = scnstart;
                    457:        tp->t_param = scnparam;
                    458:        tp->t_dev = dev;
                    459:        if ((tp->t_state & TS_ISOPEN) == 0) {
                    460:                tp->t_state |= TS_WOPEN;
                    461:                ttychars(tp);
1.7       phil      462:                tp->t_iflag = TTYDEF_IFLAG;
                    463:                tp->t_oflag = TTYDEF_OFLAG;
                    464:                tp->t_cflag = TTYDEF_CFLAG;
1.16      phil      465:                if (sc->scn_swflags & SCN_SW_CLOCAL)
1.7       phil      466:                        tp->t_cflag |= CLOCAL;
1.16      phil      467:                if (sc->scn_swflags & SCN_SW_CRTSCTS)
                    468:                        tp->t_cflag |= CRTSCTS;
1.7       phil      469:                tp->t_lflag = TTYDEF_LFLAG;
                    470:                tp->t_ispeed = tp->t_ospeed = scndefaultrate;
1.1       phil      471:                scnparam(tp, &tp->t_termios);
                    472:                ttsetwater(tp);
                    473:
                    474:                /* Turn on DTR and RTS. */
                    475:                istart(rs);
                    476:                rx_ints_on (rs);
1.7       phil      477:
                    478:                /* Carrier?  XXX fix more like i386 */
1.16      phil      479:                if ((sc->scn_swflags & SCN_SW_SOFTCAR) || get_dcd(rs))
1.7       phil      480:                        tp->t_state |= TS_CARR_ON;
                    481:        } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) {
                    482:                splx(x);
1.1       phil      483:                return (EBUSY);
                    484:        }
                    485:
1.7       phil      486:        /* wait for carrier if necessary */
                    487:        if ((flag & O_NONBLOCK) == 0)
                    488:                while ((tp->t_cflag & CLOCAL) == 0 &&
                    489:                    (tp->t_state & TS_CARR_ON) == 0) {
                    490:                        tp->t_state |= TS_WOPEN;
                    491:                        error = ttysleep(tp, (caddr_t)&tp->t_rawq,
                    492:                            TTIPRI | PCATCH, ttopen, 0);
                    493:                        if (error) {
                    494:                                /* XXX should turn off chip if we're the
                    495:                                   only waiter */
                    496:                                splx(x);
                    497:                                return error;
                    498:                        }
                    499:                }
                    500:        splx(x);
                    501:
                    502:        return (*linesw[tp->t_line].l_open)(dev, tp);
1.1       phil      503: }
                    504:
                    505: /*ARGSUSED*/
                    506: scnclose(dev, flag, mode, p)
                    507:        dev_t dev;
                    508:        int flag, mode;
                    509:        struct proc *p;
                    510: {
                    511:        register int unit = UNIT(dev);
1.16      phil      512:        struct   scn_softc *sc = scncd.cd_devs[unit];
                    513:        register struct tty *tp = sc->scn_tty;
                    514:        register struct rs232_s *rs = &sc->scn_line;
1.1       phil      515:
                    516:        (*linesw[tp->t_line].l_close)(tp, flag);
                    517: #ifdef KGDB
                    518:        /* do not disable interrupts if debugging */
                    519:        if (kgdb_dev != makedev(scnmajor, unit))
                    520: #endif
                    521:        if ((tp->t_state&TS_ISOPEN) == 0)
                    522:                rx_ints_off (rs);
                    523:        if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
                    524:            (tp->t_state&TS_ISOPEN) == 0) {
                    525:                WR_ADR (u_char, rs->opclr_port, DTR_BIT << rs->a_or_b);
                    526:                DELAY (10);
                    527:                WR_ADR (u_char, rs->opset_port, DTR_BIT << rs->a_or_b);
                    528:        }
1.5       phil      529:        ttyclose(tp);
1.6       phil      530: #if 0
                    531:        if ((tp->t_state&TS_ISOPEN) == 0) {
                    532:                ttyfree(tp);
1.16      phil      533:                sc->scn_tty = (struct tty *)NULL;
1.6       phil      534:        }
1.5       phil      535: #endif
1.1       phil      536:        return(0);
                    537: }
                    538:
                    539: scnread(dev, uio, flag)
                    540:        dev_t dev;
                    541:        struct uio *uio;
                    542: {
1.16      phil      543:        register struct scn_softc *sc = scncd.cd_devs[UNIT(dev)];
                    544:        register struct tty *tp = sc->scn_tty;
1.1       phil      545:
                    546:        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
                    547: }
                    548:
                    549: scnwrite(dev, uio, flag)
                    550:        dev_t dev;
                    551:        struct uio *uio;
                    552: {
1.16      phil      553:        register struct scn_softc *sc = scncd.cd_devs[UNIT(dev)];
                    554:        register struct tty *tp = sc->scn_tty;
1.1       phil      555:
                    556:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
                    557: }
                    558:
1.16      phil      559: struct tty *
                    560: scntty(dev)
                    561:        dev_t dev;
                    562: {
                    563:        register struct scn_softc *sc = scncd.cd_devs[UNIT(dev)];
                    564:        register struct tty *tp = sc->scn_tty;
                    565:
                    566:        return (tp);
                    567: }
                    568:
1.8       phil      569: void cts_int (struct rs232_s *rs, struct tty *tp)
                    570: {
                    571: }
                    572:
1.1       phil      573: #if 0
                    574: scnintr(int uart_no)
                    575: {
                    576:   int line0 = uart_no << 1;
                    577:   int line1 = (uart_no << 1)+1;
                    578:
1.16      phil      579:   register struct scn_softc *sc0 = scncd.cd_devs[line0];
                    580:   register struct scn_softc *sc1 = scncd.cd_devs[line1];
                    581:
                    582:   register struct tty *tp0 = sc0->scn_tty;
                    583:   register struct tty *tp1 = sc1->scn_tty;
                    584:
                    585:   register struct rs232_s *rs0 = &sc0->scn_line;
                    586:   register struct rs232_s *rs1 = &sc1->scn_line;
1.1       phil      587:
                    588:   register struct duart_info *uart = rs0->uart;
                    589:
                    590:   char   rs_work = TRUE;
                    591:
                    592:   u_char   rs_stat;
                    593:   u_char   rs_ipcr;
                    594:   u_char   ch;
                    595:
                    596:
                    597:   rs_stat = RD_ADR(u_char, uart->isr_port);
                    598:   printf ("scnintr, rs_stat = 0x%x\n", rs_stat);
                    599:
                    600:        if (rs_stat & IMR_BRK_INT) {
                    601:                /* A break interrupt! */
                    602:                rs0->lstatus = RD_ADR(u_char, rs0->stat_port);
                    603:                printf ("lstatus = 0x%x\n", rs0->lstatus);
                    604:                if (rs0->lstatus & SR_BREAK) {
                    605:                        ++rs0->break_interrupts;
                    606:                        RD_ADR(u_char, rs0->recv_port); /* Toss zero character. */
                    607:                        rs_stat &= ~IMR_RX_INT;
                    608:                }
                    609:                WR_ADR (u_char, rs0->cmd_port, CMD_RESET_BRK);
                    610:                rs0->lstatus = RD_ADR(u_char, rs0->stat_port);
                    611:                printf ("lstatus = 0x%x\n", rs0->lstatus);
                    612:        }
                    613:        if (rs_stat & IMR_RX_INT) {
                    614:                ch = RD_ADR(u_char, rs0->recv_port);
                    615:                printf ("input ch = \"%c\"\n", ch);
                    616:        }
                    617: }
                    618: /* Change this for real interrupts! */
                    619: _scnintr(int uart_no)
                    620:
                    621: #else
                    622:
                    623: /* Change this for real interrupts! */
1.17      phil      624: scnintr(int line1)
1.1       phil      625: #endif
                    626: {
1.17      phil      627:   register struct scn_softc *sc0 = scncd.cd_devs[line1 - 1];
1.16      phil      628:   register struct scn_softc *sc1 = scncd.cd_devs[line1];
                    629:
                    630:   register struct tty *tp0 = sc0->scn_tty;
                    631:   register struct tty *tp1 = sc1->scn_tty;
                    632:
                    633:   register struct rs232_s *rs0 = &sc0->scn_line;
                    634:   register struct rs232_s *rs1 = &sc1->scn_line;
1.1       phil      635:
                    636:   register struct duart_info *uart = rs0->uart;
                    637:
                    638:   char   rs_work = TRUE;
                    639:
                    640:   u_char   rs_stat;
                    641:   u_char   rs_ipcr;
                    642:   u_char   ch;
1.19      phil      643:
1.21      phil      644: #ifdef CON_BRK_PANIC
                    645:   u_char   nr_brk = 0;
                    646: #endif
                    647:
1.1       phil      648:   while (rs_work) {
                    649:        /* Loop to pick up ALL pending interrupts for device.
                    650:         */
                    651:        rs_work = FALSE;
                    652:        rs_stat = RD_ADR(u_char, uart->isr_port);
                    653: /* if (rs_stat & ~(IMR_TX_INT | IMR_TXB_INT)) printf ("scn intr rs_stat = 0x%x\n", rs_stat); */
                    654:        if ((rs_stat & IMR_TX_INT) && (tp0 != NULL)
                    655:            && (tp0->t_state & TS_BUSY)) {
                    656:                /* output char done. */
1.7       phil      657:                tp0->t_state &= ~(TS_BUSY|TS_FLUSH);
1.1       phil      658:                tx_ints_off(rs0);
                    659:                if (tp0->t_line)
                    660:                        (*linesw[tp0->t_line].l_start)(tp0);
                    661:                else
                    662:                        scnstart(tp0);
                    663:                rs_work = TRUE;
                    664:        }
                    665:        if (rs_stat & IMR_BRK_INT && (tp0 != NULL)) {
                    666:                /* A break interrupt! */
                    667:                rs0->lstatus = RD_ADR(u_char, rs0->stat_port);
                    668:                if (rs0->lstatus & SR_BREAK) {
                    669:                        ++rs0->break_interrupts;
1.19      phil      670:                        RD_ADR(u_char, rs0->recv_port); /* Toss zero character. */
                    671:                        rs_stat &= ~IMR_RX_INT;
1.1       phil      672:                }
                    673:                WR_ADR (u_char, rs0->cmd_port, CMD_RESET_BRK);
                    674:                rs_work = TRUE;
1.21      phil      675: #ifdef CON_BRK_PANIC
1.19      phil      676:                if (line1 == 1 && (rs0->lstatus & SR_BREAK)) {
1.21      phil      677:                        if (++nr_brk >= 3) {
                    678:                                char c;
                    679:                                printf("\r\nDo you want a dump (y/n)? ");
                    680:                                do
                    681:                                        c = cngetc();
                    682:                                while (c != 'y' && c != 'n');
                    683:                                printf("%c\r\n", c);
                    684:                                if (c == 'y') {
                    685:                                        panic("Panic Button");
                    686:                                }
1.19      phil      687:                        }
                    688:                }
1.21      phil      689: #endif
1.1       phil      690:        }
                    691:        if (rs_stat & IMR_RX_INT && (tp0 != NULL)) {
                    692:                ch = RD_ADR(u_char, rs0->recv_port);
                    693:                if (tp0->t_state & TS_ISOPEN)
                    694:                        (*linesw[tp0->t_line].l_rint)(ch, tp0);
                    695:                rs_work = TRUE;
1.21      phil      696: #ifdef CON_BRK_PANIC
                    697:                if (line1 == 1) nr_brk = 0;
                    698: #endif
1.1       phil      699:        }
                    700:        if ((rs_stat & IMR_TXB_INT)  && (tp1 != NULL)
                    701:             && (tp1->t_state & TS_BUSY)) {
                    702:                /* output char done. */
1.7       phil      703:                tp1->t_state &= ~(TS_BUSY|TS_FLUSH);
                    704:                tx_ints_off(rs1);
1.1       phil      705:                if (tp1->t_line)
                    706:                        (*linesw[tp1->t_line].l_start)(tp1);
                    707:                else
                    708:                        scnstart(tp1);
                    709:                rs_work = TRUE;
                    710:        }
                    711:        if (rs_stat & IMR_BRKB_INT && (tp1 != NULL)) {
                    712:                /* A break interrupt! */
                    713:                rs1->lstatus = RD_ADR(u_char, rs1->stat_port);
                    714:                if (rs1->lstatus & SR_BREAK) {
                    715:                        ++rs1->break_interrupts;
1.19      phil      716:                        RD_ADR(u_char, rs1->recv_port); /* Toss zero character. */
                    717:                        rs_stat &= ~IMR_RXB_INT;
1.1       phil      718:                }
                    719:                WR_ADR (u_char, rs1->cmd_port, CMD_RESET_BRK);
                    720:                rs_work = TRUE;
                    721:        }
                    722:        if (rs_stat & IMR_RXB_INT && (tp1 != NULL)) {
                    723:                ch = RD_ADR(u_char, rs1->recv_port);
                    724:                if (tp1->t_state & TS_ISOPEN)
                    725:                        (*linesw[tp1->t_line].l_rint)(ch, tp1);
                    726:                rs_work = TRUE;
                    727:        }
                    728:        if (rs_stat & IMR_IP_INT) {
                    729:                rs_work = TRUE;
                    730:                rs_ipcr = RD_ADR (u_char, uart->ipcr_port);
                    731: #if 0
                    732:        /* RTS/CTS stuff! */
                    733:                if (rs_ipcr & IPCR_CTS)
1.8       phil      734:                        cts_int(rs0, tp0);
1.1       phil      735:                if (rs_ipcr & (IPCR_CTS << 1))
1.8       phil      736:                        cts_int(rs1, tp1);
                    737: #endif
                    738: #if 0
                    739:                if (rs_ipcr & ACR_DCD)
                    740:                        dcd_int(rs0, tp0);
                    741:                if (rs_ipcr & (ACR_DCD << 1))
                    742:                        dcd_int(rs1, tp1);
1.1       phil      743: #endif
                    744:        }
                    745:   }
                    746: }
                    747:
                    748:
1.3       phil      749: scnioctl(dev, cmd, data, flag, p)
1.1       phil      750:        dev_t dev;
1.3       phil      751:        int cmd;
1.1       phil      752:        caddr_t data;
1.3       phil      753:        int flag;
                    754:        struct proc *p;
1.1       phil      755: {
                    756:        register int unit = UNIT(dev);
1.16      phil      757:        register struct scn_softc *sc = scncd.cd_devs[unit];
                    758:        register struct tty *tp = sc->scn_tty;
                    759:        register struct rs232_s *rs = &sc->scn_line;
1.1       phil      760:        register scn;
                    761:        register int error;
1.5       phil      762:
1.3       phil      763:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1.1       phil      764:        if (error >= 0)
                    765:                return (error);
1.3       phil      766:        error = ttioctl(tp, cmd, data, flag, p);
1.1       phil      767:        if (error >= 0)
                    768:                return (error);
                    769:
                    770:        switch (cmd) {
                    771:
                    772:        case TIOCSBRK:
                    773:                WR_ADR(u_char, rs->cmd_port, CMD_START_BRK);
                    774:                break;
                    775:
                    776:        case TIOCCBRK:
                    777:                WR_ADR (u_char, rs->cmd_port, CMD_STOP_BRK);
                    778:                break;
                    779:
                    780:        case TIOCSDTR:
1.8       phil      781:                WR_ADR(u_char, rs->opset_port,
                    782:                         (DTR_BIT | RTS_BIT) << rs->a_or_b);
1.1       phil      783:                break;
                    784:
                    785:        case TIOCCDTR:
1.8       phil      786:                WR_ADR(u_char, rs->opclr_port,
                    787:                         (DTR_BIT | RTS_BIT) << rs->a_or_b);
1.1       phil      788:                break;
                    789:
                    790:        case TIOCMSET:
                    791: /*             (void) scnmctl(dev, *(int *)data, DMSET); */
                    792:                rs->scn_bits = *(long *)data;
                    793:                break;
                    794:
                    795:        case TIOCMBIS:
                    796: /*             (void) scnmctl(dev, *(int *)data, DMBIS); */
                    797:                rs->scn_bits |= *(int *)data;
                    798:                break;
                    799:
                    800:        case TIOCMBIC:
                    801: /*             (void) scnmctl(dev, *(int *)data, DMBIC); */
                    802:                rs->scn_bits &= ~(*(int *)data);
                    803:                break;
                    804:
                    805:        case TIOCMGET:
                    806: /*             *(int *)data = scnmctl(dev, 0, DMGET); */
                    807:                *(int *)data = rs->scn_bits;
                    808:                break;
                    809:
1.8       phil      810: /* 386 case TIOCGFLAGS: {
                    811:                int bits = 0;
                    812:
                    813:                if (sc->sc_swflags & COM_SW_SOFTCAR)
                    814:                        bits |= TIOCFLAG_SOFTCAR;
                    815:                if (sc->sc_swflags & COM_SW_CLOCAL)
                    816:                        bits |= TIOCFLAG_CLOCAL;
                    817:                if (sc->sc_swflags & COM_SW_CRTSCTS)
                    818:                        bits |= TIOCFLAG_CRTSCTS;
                    819:                if (sc->sc_swflags & COM_SW_MDMBUF)
                    820:                        bits |= TIOCFLAG_MDMBUF;
                    821:
                    822:                *(int *)data = bits;
                    823:                break;
                    824:        }
                    825:        case TIOCSFLAGS: {
                    826:                int userbits, driverbits = 0;
                    827:
                    828:                error = suser(p->p_ucred, &p->p_acflag);
                    829:                if (error != 0)
                    830:                        return(EPERM);
                    831:
                    832:                userbits = *(int *)data;
                    833:                if ((userbits & TIOCFLAG_SOFTCAR) ||
                    834:                    (sc->sc_hwflags & COM_HW_CONSOLE))
                    835:                        driverbits |= COM_SW_SOFTCAR;
                    836:                if (userbits & TIOCFLAG_CLOCAL)
                    837:                        driverbits |= COM_SW_CLOCAL;
                    838:                if (userbits & TIOCFLAG_CRTSCTS)
                    839:                        driverbits |= COM_SW_CRTSCTS;
                    840:                if (userbits & TIOCFLAG_MDMBUF)
                    841:                        driverbits |= COM_SW_MDMBUF;
                    842:
                    843:                sc->sc_swflags = driverbits;
                    844:                break;
                    845:        }
                    846: */
1.1       phil      847:        default:
                    848:                return (ENOTTY);
                    849:        }
                    850:        return (0);
                    851: }
                    852:
                    853: scnparam(tp, t)
                    854:        register struct tty *tp;
                    855:        register struct termios *t;
                    856: {
                    857:   int cflag = t->c_cflag;
                    858:   int unit = UNIT(tp->t_dev);
1.16      phil      859:   register struct scn_softc *sc = scncd.cd_devs[unit];
1.1       phil      860:   int parity = LC_NONE,
                    861:       stop_bits = LC_STOP1,
                    862:       data_bits = LC_BITS8;
                    863:   int error;
1.16      phil      864:   struct rs232_s *rs = &sc->scn_line;
1.1       phil      865:
                    866:   /* Is this a hang up? */
                    867:   if (t->c_ospeed == B0) {
                    868:        WR_ADR (u_char, rs->opclr_port, DTR_BIT << rs->a_or_b);
                    869:        DELAY (10);
                    870:        WR_ADR (u_char, rs->opset_port, DTR_BIT << rs->a_or_b);
                    871:        return(0);
                    872:   }
                    873:
                    874:   /* Parity? */
                    875:   if (cflag&PARENB) {
                    876:        if ((cflag&PARODD) == 0)
                    877:                parity = LC_EVEN;
                    878:        else
                    879:                parity = LC_ODD;
                    880:   }
                    881:
                    882:  /* Stop bits. */
                    883:  if (cflag&CSTOPB)
                    884:        stop_bits = LC_STOP1;
                    885:
                    886:   /* Data bits. */
                    887:   switch (cflag&CSIZE) {
                    888:   case CS5:
                    889:        data_bits = LC_BITS5; break;
                    890:   case CS6:
                    891:        data_bits = LC_BITS6; break;
                    892:   case CS7:
                    893:        data_bits = LC_BITS7; break;
                    894:   case CS8:
                    895:        data_bits = LC_BITS8; break;
                    896:   }
                    897:
                    898:   error = scn_config (unit, t->c_ispeed, t->c_ospeed, parity, stop_bits,
                    899:                         data_bits);
                    900:
                    901:   /* If successful, copy to tty */
                    902:   if (!error) {
                    903:         tp->t_ispeed = t->c_ispeed;
                    904:         tp->t_ospeed = t->c_ospeed;
                    905:         tp->t_cflag = cflag;
                    906:   }
                    907:
                    908:   return (error);
                    909: }
1.3       phil      910:
                    911: void
1.1       phil      912: scnstart(tp)
                    913:        register struct tty *tp;
                    914: {
                    915:        int s, c;
                    916:        int unit = UNIT(tp->t_dev);
1.16      phil      917:        register struct scn_softc *sc = scncd.cd_devs[unit];
                    918:        struct rs232_s *rs = &sc->scn_line;
1.1       phil      919:
                    920:        s = spltty();
1.7       phil      921:        if (tp->t_state & (TS_BUSY|TS_TTSTOP))
1.1       phil      922:                goto out;
                    923:        if (tp->t_outq.c_cc <= tp->t_lowat) {
                    924:                if (tp->t_state&TS_ASLEEP) {
                    925:                        tp->t_state &= ~TS_ASLEEP;
                    926:                        wakeup((caddr_t)&tp->t_outq);
                    927:                }
                    928:                selwakeup(&tp->t_wsel);
                    929:        }
                    930:        if (tp->t_outq.c_cc == 0)
                    931:                goto out;
1.7       phil      932:        tp->t_state |= TS_BUSY;
1.1       phil      933:        if (tx_rdy(rs)) {
                    934:                c = getc(&tp->t_outq);
                    935:                WR_ADR(u_char, rs->xmit_port, c);
                    936:                tx_ints_on(rs);
                    937:        }
                    938: out:
                    939:        splx(s);
                    940: }
                    941:
                    942: /*
                    943:  * Stop output on a line.
                    944:  */
                    945: /*ARGSUSED*/
                    946: scnstop(tp, flag)
                    947:        register struct tty *tp;
                    948: {
                    949:        register int s;
                    950:
                    951:        s = spltty();
                    952:        if (tp->t_state & TS_BUSY) {
                    953:                if ((tp->t_state&TS_TTSTOP)==0)
                    954:                        tp->t_state |= TS_FLUSH;
                    955:        }
                    956:        splx(s);
                    957: }
                    958:
                    959: /*
                    960:  * Following are all routines needed for SCN to act as console
                    961:  */
                    962:
                    963: scncnprobe(cp)
                    964:        struct consdev *cp;
                    965: {
                    966:        /* locate the major number */
                    967:        for (scnmajor = 0; scnmajor < nchrdev; scnmajor++)
                    968:                if (cdevsw[scnmajor].d_open == scnopen)
                    969:                        break;
                    970:
                    971:        /* make sure hardware exists?  XXX */
                    972:
                    973:        /* initialize required fields */
1.5       phil      974:        cp->cn_dev = makedev(scnmajor, SCN_CONSOLE);
1.1       phil      975:        cp->cn_pri = CN_NORMAL;
1.5       phil      976:        return 1;
1.1       phil      977: }
                    978:
                    979: scncninit(cp)
                    980:        struct consdev *cp;
                    981: {
                    982: #if 0
                    983:        int unit = UNIT(cp->cn_dev);
                    984:
                    985:        scninit(unit, scndefaultrate);
                    986:        scnconsole = unit;
                    987:        scnconsinit = 1;
                    988: #endif
                    989: }
                    990:
                    991: scninit(unit, rate)
                    992:        int unit, rate;
                    993: {
                    994: #if 0
                    995:        register int scn;
                    996:        int s;
                    997:        short stat;
                    998:
                    999: #ifdef lint
                   1000:        stat = unit; if (stat) return;
                   1001: #endif
                   1002:        scn = scn_addr[unit];
                   1003:        s = splhigh();
                   1004:        outb(com+com_cfcr, CFCR_DLAB);
                   1005:        rate = ttspeedtab(comdefaultrate, comspeedtab);
                   1006:        outb(com+com_data, rate & 0xFF);
                   1007:        outb(com+com_ier, rate >> 8);
                   1008:        outb(com+com_cfcr, CFCR_8BITS);
                   1009:        outb(com+com_ier, IER_ERXRDY | IER_ETXRDY);
                   1010:        outb(com+com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14);
                   1011:        stat = inb(com+com_iir);
                   1012:        splx(s);
                   1013: #endif
                   1014: }
                   1015:
                   1016: #if 0
                   1017: int
                   1018: scnselect(dev, rw, p)
                   1019:        dev_t dev;
                   1020:        int rw;
                   1021:        struct proc *p;
                   1022: {
                   1023:        register struct tty *tp = scn_tty[UNIT(dev)];
                   1024:        int nread;
                   1025:        int s = spltty();
                   1026:         struct proc *selp;
                   1027:
                   1028:        switch (rw) {
                   1029:
                   1030:        case FREAD:
                   1031:                nread = ttnread(tp);
                   1032:                if (nread > 0 ||
                   1033:                   ((tp->t_cflag&CLOCAL) == 0 && (tp->t_state&TS_CARR_ON) == 0))
                   1034:                        goto win;
                   1035:                selrecord(p, &tp->t_rsel);
                   1036:                break;
                   1037:
                   1038:        case FWRITE:
                   1039:                if (tp->t_outq.c_cc <= tp->t_lowat)
                   1040:                        goto win;
                   1041:                selrecord(p, &tp->t_wsel);
                   1042:                break;
                   1043:        }
                   1044:        splx(s);
                   1045:        return (0);
                   1046:   win:
                   1047:        splx(s);
                   1048:        return (1);
                   1049: }
1.5       phil     1050: #endif
                   1051:
                   1052:
                   1053: /* So the kernel can write in unmapped mode! */
                   1054: int _mapped = 0;
                   1055:
                   1056: /*
                   1057:  * Console kernel input character routine.
                   1058:  */
                   1059:
                   1060: char
                   1061: scncngetc(dev_t dev)
                   1062: {
                   1063:    char c;
1.19      phil     1064:    int x = spltty();
                   1065:    WR_ADR (u_char, SCN_FIRST_MAP_ADR + 14, (RTS_BIT | DTR_BIT));
1.5       phil     1066:    while (0 == (RD_ADR (u_char, SCN_CON_MAP_STAT) & SR_RX_RDY));
                   1067:    c = RD_ADR(u_char, SCN_CON_MAP_DATA);
                   1068:    splx(x);
                   1069:    return c;
                   1070: }
1.15      phil     1071:
                   1072: /* pc532 does not turn off console polling. */
                   1073: char
                   1074: scncnpollc(dev_t dev, int on)
                   1075: {
                   1076: }
                   1077:
1.5       phil     1078:
                   1079: /*
                   1080:  * Console kernel output character routine.
                   1081:  */
                   1082:
                   1083: /* A simple kernel level "more" for debugging output. */
                   1084: #ifdef KERN_MORE
                   1085: int ___lines = 0;
                   1086: #endif
                   1087:
                   1088: scncnputc (dev_t dev, char c)
                   1089: {
1.19      phil     1090:   int x = spltty();
1.5       phil     1091:
1.9       phil     1092:   if (c == '\n') scncnputc(dev,'\r');
1.5       phil     1093:   if (_mapped) {
                   1094:     while (0 == (RD_ADR (u_char, SCN_CON_MAP_STAT) & SR_TX_RDY));
                   1095:     WR_ADR (u_char, SCN_CON_MAP_DATA, c);
                   1096:     while (0 == (RD_ADR (u_char, SCN_CON_MAP_STAT) & SR_TX_RDY));
                   1097:     RD_ADR(u_char, SCN_CON_MAP_ISR);
                   1098:   } else {
                   1099:     while (0 == (RD_ADR (u_char, SCN_CON_STAT) & SR_TX_RDY));
                   1100:     WR_ADR (u_char, SCN_CON_DATA, c);
                   1101:     while (0 == (RD_ADR (u_char, SCN_CON_STAT) & SR_TX_RDY));
                   1102:     RD_ADR(u_char, SCN_CON_ISR);
                   1103:   }
                   1104: #ifdef KERN_MORE
                   1105:   if (c == '\n' && ___lines >= 0)
                   1106:     {
                   1107:      if (++___lines == 22) {
                   1108:        ___lines = 0;
1.9       phil     1109:        scncnputc(dev,'m');scncnputc(dev,'o');scncnputc(dev,'r');
                   1110:        scncnputc(dev,'e');scncnputc(dev,':');scncnputc(dev,' ');
1.13      phil     1111:        scncngetc(dev);
1.9       phil     1112:        scncnputc(dev,'\n');
1.5       phil     1113:      }
                   1114:   }
                   1115: #endif
                   1116:   splx(x);
                   1117: }
                   1118:
1.1       phil     1119: #endif

CVSweb <webmaster@jp.NetBSD.org>