Annotation of Gnu-Mach/device/chario.c, revision 1.1.1.5

1.1.1.2   root        1: /*
1.1       root        2:  * Mach Operating System
                      3:  * Copyright (c) 1993-1988 Carnegie Mellon University
                      4:  * All Rights Reserved.
1.1.1.2   root        5:  *
1.1       root        6:  * Permission to use, copy, modify and distribute this software and its
                      7:  * documentation is hereby granted, provided that both the copyright
                      8:  * notice and this permission notice appear in all copies of the
                      9:  * software, derivative works or modified versions, and any portions
                     10:  * thereof, and that both notices appear in supporting documentation.
1.1.1.2   root       11:  *
1.1       root       12:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     13:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     14:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1.1.1.2   root       15:  *
1.1       root       16:  * Carnegie Mellon requests users of this software to return to
1.1.1.2   root       17:  *
1.1       root       18:  *  Software Distribution Coordinator  or  [email protected]
                     19:  *  School of Computer Science
                     20:  *  Carnegie Mellon University
                     21:  *  Pittsburgh PA 15213-3890
1.1.1.2   root       22:  *
1.1       root       23:  * any improvements or extensions that they make and grant Carnegie Mellon
                     24:  * the rights to redistribute these changes.
                     25:  */
                     26: /*
                     27:  *     Author: David B. Golub, Carnegie Mellon University
                     28:  *     Date:   8/88
                     29:  *
                     30:  *     TTY io.
                     31:  *     Compatibility with old TTY device drivers.
                     32:  */
                     33: 
                     34: #include <mach/kern_return.h>
                     35: #include <mach/mig_errors.h>
                     36: #include <mach/vm_param.h>
                     37: #include <machine/machspl.h>           /* spl definitions */
                     38: 
                     39: #include <ipc/ipc_port.h>
                     40: 
                     41: #include <kern/lock.h>
                     42: #include <kern/queue.h>
                     43: 
                     44: #include <vm/vm_map.h>
                     45: #include <vm/vm_kern.h>
1.1.1.4   root       46: #include <vm/vm_user.h>
1.1       root       47: 
                     48: #include <device/device_types.h>
                     49: #include <device/io_req.h>
                     50: #include <device/ds_routines.h>
1.1.1.4   root       51: #include <device/device_reply.user.h>
1.1.1.5 ! root       52: #include <device/chario.h>
1.1       root       53: 
                     54: #include <device/tty.h>
                     55: 
                     56: /* If you change these, check that tty_outq_size and tty_inq_size
                     57:  * is greater than largest tthiwat entry.
                     58:  */
1.1.1.3   root       59: short  tthiwat[NSPEEDS] =
                     60:    { 100,100,100,100,100,100,100,200,200,400,400,400,650,650,1300,2000,
                     61:      2000,2000 };
                     62: short  ttlowat[NSPEEDS] =
                     63:    {  30, 30, 30, 30, 30, 30, 30, 50, 50,120,120,120,125,125, 125, 125,
                     64:      125,125 };
1.1       root       65: 
                     66: /*
                     67:  * Fake 'line discipline' switch for the benefit of old code
                     68:  * that wants to call through it.
                     69:  */
                     70: struct ldisc_switch    linesw[] = {
                     71:        {
                     72:            char_read,
                     73:            char_write,
                     74:            ttyinput,
                     75:            ttymodem,
                     76:            tty_output
                     77:        }
                     78: };
                     79: 
                     80: /*
                     81:  * Sizes for input and output circular buffers.
                     82:  */
1.1.1.5 ! root       83: const unsigned int     tty_inq_size = 4096;    /* big nuf */
        !            84: const unsigned int     tty_outq_size = 2048;   /* Must be bigger that tthiwat */
        !            85: boolean_t              pdma_default = TRUE;    /* turn pseudo dma on by default */
1.1       root       86: 
                     87: /*
1.1.1.2   root       88:  * compute pseudo-dma tables
1.1       root       89:  */
                     90: 
                     91: int pdma_timeouts[NSPEEDS]; /* how many ticks in timeout */
                     92: int pdma_water_mark[NSPEEDS];
                     93: 
                     94: 
                     95: void chario_init(void)
                     96: {
                     97:   /* the basic idea with the timeouts is two allow enough
                     98:      time for a character to show up if data is coming in at full data rate
                     99:      plus a little slack. 2 ticks is considered slack
                    100:      Below 300 baud we just glob a character at a time */
                    101: #define _PR(x) ((hz/x) + 2)
                    102: 
                    103:   int i;
                    104: 
                    105:   for (i = B0; i < B300; i++)
                    106:     pdma_timeouts[i] = 0;
1.1.1.2   root      107: 
1.1       root      108:   pdma_timeouts[B300] = _PR(30);
                    109:   pdma_timeouts[B600] = _PR(60);
                    110:   pdma_timeouts[B1200] = _PR(120);
                    111:   pdma_timeouts[B1800] = _PR(180);
                    112:   pdma_timeouts[B2400] = _PR(240);
                    113:   pdma_timeouts[B4800] = _PR(480);
                    114:   pdma_timeouts[B9600] = _PR(960);
                    115:   pdma_timeouts[EXTA]  = _PR(1440); /* >14400 baud */
                    116:   pdma_timeouts[EXTB]  = _PR(1920); /* >19200 baud */
1.1.1.3   root      117:   pdma_timeouts[B57600] = _PR(5760);
                    118:   pdma_timeouts[B115200] = _PR(11520);
1.1       root      119: 
                    120:   for (i = B0; i < B300; i++)
                    121:     pdma_water_mark[i] = 0;
                    122: 
                    123:   /* for the slow speeds, we try to buffer 0.02 of the baud rate
                    124:      (20% of the character rate). For the faster lines,
                    125:      we try to buffer 1/2 the input queue size */
                    126: 
                    127: #undef _PR
                    128: #define _PR(x) (0.20 * x)
                    129: 
                    130:   pdma_water_mark[B300] = _PR(120);
                    131:   pdma_water_mark[B600] = _PR(120);
                    132:   pdma_water_mark[B1200] = _PR(120);
                    133:   pdma_water_mark[B1800] = _PR(180);
                    134:   pdma_water_mark[B2400] = _PR(240);
                    135:   pdma_water_mark[B4800] = _PR(480);
                    136:   i = tty_inq_size/2;
                    137:   pdma_water_mark[B9600] = i;
                    138:   pdma_water_mark[EXTA]  = i; /* >14400 baud */
                    139:   pdma_water_mark[EXTB]  = i; /* >19200 baud */
1.1.1.3   root      140:   pdma_water_mark[B57600] = i;
                    141:   pdma_water_mark[B115200] = i;
1.1       root      142: 
1.1.1.2   root      143:   return;
1.1       root      144: }
                    145: 
                    146: /*
                    147:  * Open TTY, waiting for CARR_ON.
                    148:  * No locks may be held.
                    149:  * May run on any CPU.
                    150:  */
                    151: io_return_t char_open(
                    152:        int             dev,
                    153:        struct tty *    tp,
                    154:        dev_mode_t      mode,
                    155:        io_req_t        ior)
                    156: {
                    157:        spl_t   s;
                    158:        io_return_t     rc = D_SUCCESS;
                    159: 
                    160:        s = spltty();
                    161:        simple_lock(&tp->t_lock);
                    162: 
                    163:        tp->t_dev = dev;
                    164: 
                    165:        if (tp->t_mctl)
                    166:                (*tp->t_mctl)(tp, TM_DTR, DMSET);
                    167: 
                    168:        if (pdma_default)
                    169:          tp->t_state |= TS_MIN;
                    170: 
                    171:        if ((tp->t_state & TS_CARR_ON) == 0) {
                    172:            /*
                    173:             * No carrier.
                    174:             */
                    175:            if (mode & D_NODELAY) {
                    176:                tp->t_state |= TS_ONDELAY;
                    177:            }
                    178:            else {
                    179:                /*
                    180:                 * Don`t return from open until carrier detected.
                    181:                 */
                    182:                tp->t_state |= TS_WOPEN;
                    183: 
                    184:                ior->io_dev_ptr = (char *)tp;
                    185: 
                    186:                queue_delayed_reply(&tp->t_delayed_open, ior, char_open_done);
                    187:                rc = D_IO_QUEUED;
                    188:                goto out;
                    189:            }
                    190:        }
                    191:        tp->t_state |= TS_ISOPEN;
                    192:        if (tp->t_mctl)
                    193:                (*tp->t_mctl)(tp, TM_RTS, DMBIS);
                    194: out:
                    195:        simple_unlock(&tp->t_lock);
                    196:        splx(s);
                    197:        return rc;
                    198: }
                    199: 
                    200: /*
                    201:  * Retry wait for CARR_ON for open.
                    202:  * No locks may be held.
                    203:  * May run on any CPU.
                    204:  */
                    205: boolean_t char_open_done(
                    206:        io_req_t        ior)
                    207: {
1.1.1.4   root      208:        struct tty *tp = (struct tty *)ior->io_dev_ptr;
1.1       root      209:        spl_t s = spltty();
                    210: 
                    211:        simple_lock(&tp->t_lock);
                    212:        if ((tp->t_state & TS_ISOPEN) == 0) {
                    213:            queue_delayed_reply(&tp->t_delayed_open, ior, char_open_done);
                    214:            simple_unlock(&tp->t_lock);
                    215:            splx(s);
                    216:            return FALSE;
                    217:        }
                    218: 
                    219:        tp->t_state |= TS_ISOPEN;
                    220:        tp->t_state &= ~TS_WOPEN;
                    221: 
                    222:        if (tp->t_mctl)
                    223:                (*tp->t_mctl)(tp, TM_RTS, DMBIS);
                    224: 
                    225:        simple_unlock(&tp->t_lock);
                    226:        splx(s);
                    227: 
                    228:        ior->io_error = D_SUCCESS;
                    229:        (void) ds_open_done(ior);
                    230:        return TRUE;
                    231: }
                    232: 
                    233: boolean_t tty_close_open_reply(
                    234:        io_req_t        ior)
                    235: {
                    236:        ior->io_error = D_DEVICE_DOWN;
                    237:        (void) ds_open_done(ior);
                    238:        return TRUE;
                    239: }
                    240: 
                    241: /*
                    242:  * Write to TTY.
                    243:  * No locks may be held.
                    244:  * Calls device start routine; must already be on master if
                    245:  * device needs to run on master.
                    246:  */
                    247: io_return_t char_write(
1.1.1.4   root      248:        struct tty *    tp,
                    249:        io_req_t        ior)
1.1       root      250: {
                    251:        spl_t           s;
1.1.1.4   root      252:        int     count;
                    253:        char    *data;
1.1.1.5 ! root      254:        vm_offset_t     addr = 0;
1.1       root      255:        io_return_t     rc = D_SUCCESS;
                    256: 
                    257:        data  = ior->io_data;
                    258:        count = ior->io_count;
                    259:        if (count == 0)
                    260:            return rc;
                    261: 
                    262:        if (!(ior->io_op & IO_INBAND)) {
                    263:            /*
                    264:             * Copy out-of-line data into kernel address space.
                    265:             * Since data is copied as page list, it will be
                    266:             * accessible.
                    267:             */
                    268:            vm_map_copy_t copy = (vm_map_copy_t) data;
                    269:            kern_return_t kr;
                    270: 
                    271:            kr = vm_map_copyout(device_io_map, &addr, copy);
                    272:            if (kr != KERN_SUCCESS)
                    273:                return kr;
                    274:            data = (char *) addr;
                    275:        }
                    276: 
                    277:        /*
                    278:         * Check for tty operating.
                    279:         */
                    280:        s = spltty();
                    281:        simple_lock(&tp->t_lock);
                    282: 
                    283:        if ((tp->t_state & TS_CARR_ON) == 0) {
                    284: 
                    285:            if ((tp->t_state & TS_ONDELAY) == 0) {
                    286:                /*
                    287:                 * No delayed writes - tell caller that device is down
                    288:                 */
                    289:                rc = D_IO_ERROR;
                    290:                goto out;
                    291:            }
                    292: 
                    293:            if (ior->io_mode & D_NOWAIT) {
                    294:                rc = D_WOULD_BLOCK;
                    295:                goto out;
                    296:            }
                    297:        }
                    298: 
                    299:        /*
                    300:         * Copy data into the output buffer.
                    301:         * Report the amount not copied.
                    302:         */
                    303: 
                    304:        ior->io_residual = b_to_q(data, count, &tp->t_outq);
                    305: 
                    306:        /*
                    307:         * Start hardware output.
                    308:         */
                    309: 
                    310:        tp->t_state &= ~TS_TTSTOP;
                    311:        tty_output(tp);
                    312: 
                    313:        if (tp->t_outq.c_cc > TTHIWAT(tp) ||
                    314:            (tp->t_state & TS_CARR_ON) == 0) {
                    315: 
                    316:            /*
                    317:             * Do not send reply until some characters have been sent.
                    318:             */
                    319:            ior->io_dev_ptr = (char *)tp;
                    320:            queue_delayed_reply(&tp->t_delayed_write, ior, char_write_done);
                    321: 
                    322:            rc = D_IO_QUEUED;
                    323:        }
                    324: out:
                    325:        simple_unlock(&tp->t_lock);
                    326:        splx(s);
                    327: 
                    328:        if (!(ior->io_op & IO_INBAND))
                    329:            (void) vm_deallocate(device_io_map, addr, ior->io_count);
                    330:        return rc;
                    331: }
                    332: 
                    333: /*
                    334:  * Retry wait for output queue emptied, for write.
                    335:  * No locks may be held.
                    336:  * May run on any CPU.
                    337:  */
                    338: boolean_t char_write_done(
1.1.1.4   root      339:        io_req_t        ior)
1.1       root      340: {
1.1.1.4   root      341:        struct tty *tp = (struct tty *)ior->io_dev_ptr;
                    342:        spl_t s = spltty();
1.1       root      343: 
                    344:        simple_lock(&tp->t_lock);
                    345:        if (tp->t_outq.c_cc > TTHIWAT(tp) ||
                    346:            (tp->t_state & TS_CARR_ON) == 0) {
                    347: 
                    348:            queue_delayed_reply(&tp->t_delayed_write, ior, char_write_done);
                    349:            simple_unlock(&tp->t_lock);
                    350:            splx(s);
                    351:            return FALSE;
                    352:        }
                    353:        simple_unlock(&tp->t_lock);
                    354:        splx(s);
                    355: 
                    356:        if (IP_VALID(ior->io_reply_port)) {
                    357:          (void) (*((ior->io_op & IO_INBAND) ?
                    358:                    ds_device_write_reply_inband :
                    359:                    ds_device_write_reply))(ior->io_reply_port,
                    360:                                            ior->io_reply_port_type,
                    361:                                            ior->io_error,
                    362:                                            (int) (ior->io_total -
                    363:                                                   ior->io_residual));
                    364:        }
                    365:        mach_device_deallocate(ior->io_device);
                    366:        return TRUE;
                    367: }
                    368: 
                    369: boolean_t tty_close_write_reply(
1.1.1.4   root      370:        io_req_t        ior)
1.1       root      371: {
                    372:        ior->io_residual = ior->io_count;
                    373:        ior->io_error = D_DEVICE_DOWN;
                    374:        (void) ds_write_done(ior);
                    375:        return TRUE;
                    376: }
                    377: 
                    378: /*
                    379:  * Read from TTY.
                    380:  * No locks may be held.
                    381:  * May run on any CPU - does not talk to device driver.
                    382:  */
                    383: io_return_t char_read(
1.1.1.4   root      384:        struct tty *tp,
                    385:        io_req_t ior)
1.1       root      386: {
                    387:        spl_t           s;
                    388:        kern_return_t   rc;
                    389: 
                    390:        /*
                    391:         * Allocate memory for read buffer.
                    392:         */
                    393:        rc = device_read_alloc(ior, (vm_size_t)ior->io_count);
                    394:        if (rc != KERN_SUCCESS)
                    395:            return rc;
                    396: 
                    397:        s = spltty();
                    398:        simple_lock(&tp->t_lock);
                    399:        if ((tp->t_state & TS_CARR_ON) == 0) {
                    400: 
                    401:            if ((tp->t_state & TS_ONDELAY) == 0) {
                    402:                /*
                    403:                 * No delayed writes - tell caller that device is down
                    404:                 */
                    405:                rc = D_IO_ERROR;
                    406:                goto out;
                    407:            }
                    408: 
                    409:            if (ior->io_mode & D_NOWAIT) {
                    410:                rc = D_WOULD_BLOCK;
                    411:                goto out;
                    412:            }
                    413: 
                    414:        }
                    415: 
                    416:        if (tp->t_inq.c_cc <= 0 ||
                    417:            (tp->t_state & TS_CARR_ON) == 0) {
                    418: 
                    419:            ior->io_dev_ptr = (char *)tp;
                    420:            queue_delayed_reply(&tp->t_delayed_read, ior, char_read_done);
                    421:            rc = D_IO_QUEUED;
                    422:            goto out;
                    423:        }
1.1.1.2   root      424: 
1.1       root      425:        ior->io_residual = ior->io_count - q_to_b(&tp->t_inq,
                    426:                                                  ior->io_data,
                    427:                                                  (int)ior->io_count);
                    428:        if (tp->t_state & TS_RTS_DOWN) {
                    429:            (*tp->t_mctl)(tp, TM_RTS, DMBIS);
                    430:            tp->t_state &= ~TS_RTS_DOWN;
                    431:        }
                    432: 
                    433:     out:
                    434:        simple_unlock(&tp->t_lock);
                    435:        splx(s);
                    436:        return rc;
                    437: }
                    438: 
                    439: /*
                    440:  * Retry wait for characters, for read.
                    441:  * No locks may be held.
                    442:  * May run on any CPU - does not talk to device driver.
                    443:  */
                    444: boolean_t char_read_done(
1.1.1.4   root      445:        io_req_t        ior)
1.1       root      446: {
1.1.1.4   root      447:        struct tty *tp = (struct tty *)ior->io_dev_ptr;
                    448:        spl_t s = spltty();
1.1       root      449: 
                    450:        simple_lock(&tp->t_lock);
                    451: 
                    452:        if (tp->t_inq.c_cc <= 0 ||
                    453:            (tp->t_state & TS_CARR_ON) == 0) {
                    454: 
                    455:            queue_delayed_reply(&tp->t_delayed_read, ior, char_read_done);
                    456:            simple_unlock(&tp->t_lock);
                    457:            splx(s);
                    458:            return FALSE;
                    459:        }
                    460: 
                    461:        ior->io_residual = ior->io_count - q_to_b(&tp->t_inq,
                    462:                                                  ior->io_data,
                    463:                                                  (int)ior->io_count);
                    464:        if (tp->t_state & TS_RTS_DOWN) {
                    465:            (*tp->t_mctl)(tp, TM_RTS, DMBIS);
                    466:            tp->t_state &= ~TS_RTS_DOWN;
                    467:        }
                    468: 
                    469:        simple_unlock(&tp->t_lock);
                    470:        splx(s);
                    471: 
                    472:        (void) ds_read_done(ior);
                    473:        return TRUE;
                    474: }
                    475: 
                    476: boolean_t tty_close_read_reply(
1.1.1.4   root      477:        io_req_t        ior)
1.1       root      478: {
                    479:        ior->io_residual = ior->io_count;
                    480:        ior->io_error = D_DEVICE_DOWN;
                    481:        (void) ds_read_done(ior);
                    482:        return TRUE;
                    483: }
                    484: 
                    485: /*
                    486:  * Close the tty.
                    487:  * Tty must be locked (at spltty).
                    488:  * Iff modem control should run on master.
                    489:  */
                    490: void ttyclose(
1.1.1.4   root      491:        struct tty *tp)
1.1       root      492: {
1.1.1.4   root      493:        io_req_t        ior;
1.1       root      494: 
                    495:        /*
                    496:         * Flush the read and write queues.  Signal
                    497:         * the open queue so that those waiting for open
                    498:         * to complete will see that the tty is closed.
                    499:         */
                    500:        while ((ior = (io_req_t)dequeue_head(&tp->t_delayed_read)) != 0) {
                    501:            ior->io_done = tty_close_read_reply;
                    502:            iodone(ior);
                    503:        }
                    504:        while ((ior = (io_req_t)dequeue_head(&tp->t_delayed_write)) != 0) {
                    505:            ior->io_done = tty_close_write_reply;
                    506:            iodone(ior);
                    507:        }
                    508:        while ((ior = (io_req_t)dequeue_head(&tp->t_delayed_open)) != 0) {
                    509:            ior->io_done = tty_close_open_reply;
                    510:            iodone(ior);
                    511:        }
                    512: 
                    513:        /* Close down modem */
                    514:        if (tp->t_mctl) {
                    515:                (*tp->t_mctl)(tp, TM_BRK|TM_RTS, DMBIC);
                    516:                if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN)==0)
                    517:                        (*tp->t_mctl)(tp, TM_HUP, DMSET);
                    518:        }
                    519: 
                    520:        /* only save buffering bit, and carrier */
                    521:        tp->t_state = tp->t_state & (TS_MIN|TS_CARR_ON);
                    522: }
                    523: 
                    524: /*
                    525:  * Port-death routine to clean up reply messages.
                    526:  */
                    527: boolean_t
                    528: tty_queue_clean(
1.1.1.5 ! root      529:        queue_t                 q,
        !           530:        const ipc_port_t        port,
        !           531:        boolean_t               (*routine)(io_req_t) )
1.1       root      532: {
1.1.1.4   root      533:        io_req_t        ior;
1.1       root      534: 
                    535:        ior = (io_req_t)queue_first(q);
                    536:        while (!queue_end(q, (queue_entry_t)ior)) {
                    537:            if (ior->io_reply_port == port) {
                    538:                remqueue(q, (queue_entry_t)ior);
                    539:                ior->io_done = routine;
                    540:                iodone(ior);
                    541:                return TRUE;
                    542:            }
                    543:            ior = ior->io_next;
                    544:        }
                    545:        return FALSE;
                    546: }
                    547: 
                    548: /*
                    549:  * Handle port-death (dead reply port) for tty.
                    550:  * No locks may be held.
                    551:  * May run on any CPU.
                    552:  */
                    553: boolean_t
                    554: tty_portdeath(
1.1.1.5 ! root      555:        struct tty *            tp,
        !           556:        const ipc_port_t        port)
1.1       root      557: {
1.1.1.4   root      558:        spl_t   spl = spltty();
                    559:        boolean_t       result;
1.1       root      560: 
                    561:        simple_lock(&tp->t_lock);
                    562: 
                    563:        /*
                    564:         * The queues may never have been initialized
                    565:         */
                    566:        if (tp->t_delayed_read.next == 0) {
                    567:            result = FALSE;
                    568:        }
                    569:        else {
                    570:            result =
                    571:                tty_queue_clean(&tp->t_delayed_read,  port,
                    572:                                tty_close_read_reply)
                    573:             || tty_queue_clean(&tp->t_delayed_write, port,
                    574:                                tty_close_write_reply)
                    575:             || tty_queue_clean(&tp->t_delayed_open,  port,
                    576:                                tty_close_open_reply);
                    577:        }
                    578:        simple_unlock(&tp->t_lock);
                    579:        splx(spl);
                    580: 
                    581:        return result;
                    582: }
                    583: 
                    584: /*
                    585:  * Get TTY status.
                    586:  * No locks may be held.
                    587:  * May run on any CPU.
                    588:  */
                    589: io_return_t tty_get_status(
1.1.1.4   root      590:        struct tty *tp,
1.1       root      591:        dev_flavor_t    flavor,
                    592:        int *           data,           /* pointer to OUT array */
                    593:        natural_t       *count)         /* out */
                    594: {
                    595:        spl_t           s;
                    596: 
                    597:        switch (flavor) {
                    598:            case TTY_STATUS:
                    599:            {
1.1.1.4   root      600:                struct tty_status *tsp =
1.1       root      601:                        (struct tty_status *) data;
                    602: 
                    603:                if (*count < TTY_STATUS_COUNT)
                    604:                    return (D_INVALID_OPERATION);
                    605: 
                    606:                s = spltty();
                    607:                simple_lock(&tp->t_lock);
                    608: 
                    609:                tsp->tt_ispeed = tp->t_ispeed;
                    610:                tsp->tt_ospeed = tp->t_ospeed;
                    611:                tsp->tt_breakc = tp->t_breakc;
                    612:                tsp->tt_flags  = tp->t_flags;
                    613:                if (tp->t_state & TS_HUPCLS)
                    614:                    tsp->tt_flags |= TF_HUPCLS;
                    615: 
                    616:                simple_unlock(&tp->t_lock);
                    617:                splx(s);
                    618: 
                    619:                *count = TTY_STATUS_COUNT;
                    620:                break;
                    621: 
                    622:            }
                    623:            default:
                    624:                return D_INVALID_OPERATION;
                    625:        }
                    626:        return D_SUCCESS;
                    627: }
                    628: 
                    629: /*
                    630:  * Set TTY status.
                    631:  * No locks may be held.
                    632:  * Calls device start or stop routines; must already be on master if
                    633:  * device needs to run on master.
                    634:  */
                    635: io_return_t tty_set_status(
1.1.1.4   root      636:        struct tty *tp,
1.1       root      637:        dev_flavor_t    flavor,
                    638:        int *           data,
                    639:        natural_t       count)
                    640: {
                    641:        int     s;
                    642: 
                    643:        switch (flavor) {
                    644:            case TTY_FLUSH:
                    645:            {
1.1.1.4   root      646:                int     flags;
1.1       root      647:                if (count < TTY_FLUSH_COUNT)
                    648:                    return D_INVALID_OPERATION;
                    649: 
                    650:                flags = *data;
                    651:                if (flags == 0)
                    652:                    flags = D_READ | D_WRITE;
                    653: 
                    654:                s = spltty();
                    655:                simple_lock(&tp->t_lock);
                    656:                tty_flush(tp, flags);
                    657:                simple_unlock(&tp->t_lock);
                    658:                splx(s);
                    659: 
                    660:                break;
                    661:            }
                    662:            case TTY_STOP:
                    663:                /* stop output */
                    664:                s = spltty();
                    665:                simple_lock(&tp->t_lock);
                    666:                if ((tp->t_state & TS_TTSTOP) == 0) {
                    667:                    tp->t_state |= TS_TTSTOP;
                    668:                    (*tp->t_stop)(tp, 0);
                    669:                }
                    670:                simple_unlock(&tp->t_lock);
                    671:                splx(s);
                    672:                break;
                    673: 
                    674:            case TTY_START:
                    675:                /* start output */
                    676:                s = spltty();
                    677:                simple_lock(&tp->t_lock);
                    678:                if (tp->t_state & TS_TTSTOP) {
                    679:                    tp->t_state &= ~TS_TTSTOP;
                    680:                    tty_output(tp);
                    681:                }
                    682:                simple_unlock(&tp->t_lock);
                    683:                splx(s);
                    684:                break;
                    685: 
                    686:            case TTY_STATUS:
                    687:                /* set special characters and speed */
                    688:            {
1.1.1.4   root      689:                struct tty_status *tsp;
1.1       root      690: 
                    691:                if (count < TTY_STATUS_COUNT)
                    692:                    return D_INVALID_OPERATION;
                    693: 
                    694:                tsp = (struct tty_status *)data;
                    695: 
                    696:                if (tsp->tt_ispeed < 0 ||
                    697:                    tsp->tt_ispeed >= NSPEEDS ||
                    698:                    tsp->tt_ospeed < 0 ||
                    699:                    tsp->tt_ospeed >= NSPEEDS)
                    700:                {
                    701:                    return D_INVALID_OPERATION;
                    702:                }
                    703: 
                    704:                s = spltty();
                    705:                simple_lock(&tp->t_lock);
                    706: 
                    707:                tp->t_ispeed = tsp->tt_ispeed;
                    708:                tp->t_ospeed = tsp->tt_ospeed;
                    709:                tp->t_breakc = tsp->tt_breakc;
                    710:                tp->t_flags  = tsp->tt_flags & ~TF_HUPCLS;
                    711:                if (tsp->tt_flags & TF_HUPCLS)
                    712:                    tp->t_state |= TS_HUPCLS;
                    713: 
                    714:                simple_unlock(&tp->t_lock);
                    715:                splx(s);
                    716:                break;
                    717:            }
                    718:            default:
                    719:                return D_INVALID_OPERATION;
                    720:        }
                    721:        return D_SUCCESS;
                    722: }
                    723: 
                    724: 
                    725: /*
                    726:  * [internal]
                    727:  * Queue IOR on reply queue, to wait for TTY operation.
                    728:  * TTY must be locked (at spltty).
                    729:  */
                    730: void queue_delayed_reply(
                    731:        queue_t         qh,
                    732:        io_req_t        ior,
                    733:        boolean_t       (*io_done)(io_req_t) )
                    734: {
                    735:        ior->io_done = io_done;
                    736:        enqueue_tail(qh, (queue_entry_t)ior);
                    737: }
                    738: 
                    739: /*
                    740:  * Retry delayed IO operations for TTY.
                    741:  * TTY containing queue must be locked (at spltty).
                    742:  */
                    743: void tty_queue_completion(
1.1.1.4   root      744:        queue_t qh)
1.1       root      745: {
1.1.1.4   root      746:        io_req_t        ior;
1.1       root      747: 
                    748:        while ((ior = (io_req_t)dequeue_head(qh)) != 0) {
                    749:            iodone(ior);
                    750:        }
                    751: }
                    752: 
                    753: /*
                    754:  * Set the default special characters.
                    755:  * Since this routine is called whenever a tty has never been opened,
                    756:  * we can initialize the queues here.
                    757:  */
                    758: void ttychars(
1.1.1.4   root      759:        struct tty *tp)
1.1       root      760: {
                    761:        if ((tp->t_flags & TS_INIT) == 0) {
                    762:            /*
                    763:             * Initialize queues
                    764:             */
                    765:            queue_init(&tp->t_delayed_open);
                    766:            queue_init(&tp->t_delayed_read);
                    767:            queue_init(&tp->t_delayed_write);
                    768: 
                    769:            /*
                    770:             * Initialize character buffers
                    771:             */
                    772:            cb_alloc(&tp->t_inq,  tty_inq_size);
                    773: 
                    774:            /* if we might do modem flow control */
                    775:            if (tp->t_mctl && tp->t_inq.c_hog > 30)
                    776:                tp->t_inq.c_hog -= 30;
                    777: 
                    778:            cb_alloc(&tp->t_outq, tty_outq_size);
                    779: 
                    780:            /*
                    781:             * Mark initialized
                    782:             */
                    783:            tp->t_state |= TS_INIT;
                    784:        }
                    785: 
                    786:        tp->t_breakc = 0;
                    787: }
                    788: 
                    789: /*
                    790:  * Flush all TTY queues.
                    791:  * Called at spltty, tty already locked.
                    792:  * Calls device STOP routine; must already be on master if
                    793:  * device needs to run on master.
                    794:  */
                    795: void tty_flush(
1.1.1.4   root      796:        struct tty *tp,
1.1       root      797:        int     rw)
                    798: {
                    799:        if (rw & D_READ) {
                    800:            cb_clear(&tp->t_inq);
                    801:            tty_queue_completion(&tp->t_delayed_read);
                    802:        }
                    803:        if (rw & D_WRITE) {
                    804:            tp->t_state &= ~TS_TTSTOP;
                    805:            (*tp->t_stop)(tp, rw);
                    806:            cb_clear(&tp->t_outq);
                    807:            tty_queue_completion(&tp->t_delayed_write);
                    808:        }
                    809: }
1.1.1.2   root      810: 
1.1       root      811: /*
                    812:  * Restart character output after a delay timeout.
                    813:  * Calls device start routine - must be on master CPU.
                    814:  *
                    815:  *     Timeout routines are called only on master CPU.
                    816:  *     What if device runs on a different CPU?
                    817:  */
                    818: void ttrstrt(
1.1.1.4   root      819:        struct tty *tp)
1.1       root      820: {
1.1.1.4   root      821:        spl_t   s;
1.1       root      822: 
                    823:        s = spltty();
                    824:        simple_lock(&tp->t_lock);
                    825: 
                    826:        tp->t_state &= ~TS_TIMEOUT;
                    827:        ttstart (tp);
                    828: 
                    829:        simple_unlock(&tp->t_lock);
                    830:         splx(s);
                    831: }
                    832: 
                    833: /*
                    834:  * Start output on the typewriter. It is used from the top half
                    835:  * after some characters have been put on the output queue,
                    836:  * from the interrupt routine to transmit the next
                    837:  * character, and after a timeout has finished.
                    838:  *
                    839:  * Called at spltty, tty already locked.
                    840:  * Must be on master CPU if device runs on master.
                    841:  */
1.1.1.5 ! root      842: void ttstart(struct tty *tp)
1.1       root      843: {
                    844:        if ((tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0) {
                    845:            /*
                    846:             * Start up the hardware again
                    847:             */
                    848:            (*tp->t_start)(tp);
                    849: 
                    850:            /*
                    851:             * Wake up those waiting for write completion.
                    852:             */
                    853:            if (tp->t_outq.c_cc <= TTLOWAT(tp))
                    854:                tty_queue_completion(&tp->t_delayed_write);
                    855:        }
                    856: }
                    857: 
                    858: /*
                    859:  * Start character output, if the device is not busy or
                    860:  * stopped or waiting for a timeout.
                    861:  *
                    862:  * Called at spltty, tty already locked.
                    863:  * Must be on master CPU if device runs on master.
                    864:  */
                    865: void tty_output(
1.1.1.4   root      866:        struct tty *tp)
1.1       root      867: {
                    868:        if ((tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0) {
                    869:            /*
                    870:             * Not busy.  Start output.
                    871:             */
                    872:            (*tp->t_start)(tp);
                    873: 
                    874:            /*
                    875:             * Wake up those waiting for write completion.
                    876:             */
                    877:            if (tp->t_outq.c_cc <= TTLOWAT(tp))
                    878:                tty_queue_completion(&tp->t_delayed_write);
                    879:        }
                    880: }
                    881: 
                    882: /*
                    883:  * Send any buffered recvd chars up to user
                    884:  */
                    885: void ttypush(
1.1.1.4   root      886:        void * _tp)
1.1       root      887: {
1.1.1.4   root      888:        struct tty      *tp = _tp;
1.1       root      889:        spl_t   s = spltty();
1.1.1.4   root      890:        int     state;
1.1       root      891: 
                    892:        simple_lock(&tp->t_lock);
                    893: 
                    894:        /*
1.1.1.2   root      895:          The pdma timeout has gone off.
1.1       root      896:          If no character has been received since the timeout
                    897:          was set, push any pending characters up.
                    898:          If any characters were received in the last interval
                    899:          then just reset the timeout and the character received bit.
                    900:          */
                    901: 
                    902:        state = tp->t_state;
                    903: 
                    904:        if (state & TS_MIN_TO)
                    905:          {
                    906:            if (state & TS_MIN_TO_RCV)
                    907:              { /* a character was received */
                    908:                tp->t_state = state & ~TS_MIN_TO_RCV;
1.1.1.5 ! root      909:                timeout(ttypush, tp, pdma_timeouts[tp->t_ispeed]);
1.1       root      910:              }
                    911:            else
                    912:              {
                    913:                tp->t_state = state & ~TS_MIN_TO;
                    914:                if (tp->t_inq.c_cc) /* pending characters */
                    915:                  tty_queue_completion(&tp->t_delayed_read);
                    916:              }
                    917:          }
                    918:        else
                    919:          {
                    920:            tp->t_state = state & ~TS_MIN_TO_RCV;/* sanity */
                    921:          }
                    922: 
                    923:        simple_unlock(&tp->t_lock);
                    924:        splx(s);
                    925: }
                    926: 
                    927: /*
                    928:  * Put input character on input queue.
                    929:  *
                    930:  * Called at spltty, tty already locked.
                    931:  */
                    932: void ttyinput(
                    933:        unsigned int    c,
                    934:        struct tty      *tp)
                    935: {
                    936:   if (tp->t_inq.c_cc >= tp->t_inq.c_hog) {
                    937:     /*
                    938:      * Do not want to overflow input queue
                    939:      */
                    940:     if (tp->t_mctl) {
                    941:        (*tp->t_mctl)(tp, TM_RTS, DMBIC);
                    942:        tp->t_state |= TS_RTS_DOWN;
                    943:     }
                    944:     tty_queue_completion(&tp->t_delayed_read);
                    945:     return;
                    946: 
                    947:   }
                    948: 
                    949:   c &= 0xff;
                    950: 
                    951:   (void) putc(c, &tp->t_inq);
                    952:   if ((tp->t_state & TS_MIN) == 0 ||
                    953:        tp->t_inq.c_cc > pdma_water_mark[tp->t_ispeed])
                    954:      {
                    955:          /*
                    956:           * No input buffering, or input minimum exceeded.
                    957:           * Grab a request from input queue and queue it
                    958:           * to io_done thread.
                    959:           */
                    960:          if (tp->t_state & TS_MIN_TO) {
                    961:            tp->t_state &= ~(TS_MIN_TO|TS_MIN_TO_RCV);
                    962:            untimeout(ttypush, tp);
                    963:          }
                    964:          tty_queue_completion(&tp->t_delayed_read);
                    965:       }
                    966:       else {
                    967:        /*
1.1.1.2   root      968:         * Not enough characters.
                    969:         * If no timeout is set, initiate the timeout
1.1       root      970:         * Otherwise set the character received during timeout interval
                    971:         * flag.
                    972:         * One alternative approach would be just to reset the timeout
                    973:         * into the future, but this involves making a timeout/untimeout
                    974:         * call on every character.
                    975:         */
1.1.1.4   root      976:        int ptime = pdma_timeouts[tp->t_ispeed];
1.1       root      977:        if (ptime > 0)
                    978:          {
                    979:            if ((tp->t_state & TS_MIN_TO) == 0)
                    980:              {
                    981:                tp->t_state |= TS_MIN_TO;
                    982:                timeout(ttypush, tp, ptime);
                    983:              }
                    984:            else
                    985:              {
                    986:                tp->t_state |= TS_MIN_TO_RCV;
                    987:              }
                    988:          }
                    989:       }
                    990: }
                    991: 
                    992: /*
                    993:  * Put many characters on input queue.
                    994:  *
                    995:  * Called at spltty, tty already locked.
                    996:  */
                    997: void ttyinput_many(
                    998:        struct tty      *tp,
1.1.1.4   root      999:        char            *chars,
1.1       root     1000:        int             count)
                   1001: {
                   1002:        /*
1.1.1.2   root     1003:         * Do not want to overflow input queue
1.1       root     1004:         */
                   1005:        if (tp->t_inq.c_cc < tp->t_inq.c_hog)
1.1.1.5 ! root     1006:                count -= b_to_q(chars, count, &tp->t_inq);
1.1       root     1007: 
                   1008:        tty_queue_completion(&tp->t_delayed_read);
                   1009: }
                   1010: 
                   1011: 
                   1012: /*
                   1013:  * Handle modem control transition on a tty.
                   1014:  * Flag indicates new state of carrier.
                   1015:  * Returns FALSE if the line should be turned off.
                   1016:  *
                   1017:  * Called at spltty, tty already locked.
                   1018:  */
                   1019: boolean_t ttymodem(
                   1020:        struct tty *    tp,
                   1021:        boolean_t       carrier_up)
                   1022: {
                   1023:        if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_flags & MDMBUF)) {
                   1024:            /*
                   1025:             * Flow control by carrier.  Carrier down stops
                   1026:             * output; carrier up restarts output.
                   1027:             */
                   1028:            if (carrier_up) {
                   1029:                tp->t_state &= ~TS_TTSTOP;
                   1030:                tty_output(tp);
                   1031:            }
                   1032:            else if ((tp->t_state&TS_TTSTOP) == 0) {
                   1033:                tp->t_state |= TS_TTSTOP;
                   1034:                (*tp->t_stop)(tp, 0);
                   1035:            }
                   1036:        }
                   1037:        else if (carrier_up) {
                   1038:            /*
                   1039:             * Carrier now on.
                   1040:             */
                   1041:            tp->t_state |= TS_CARR_ON;
                   1042:            tt_open_wakeup(tp);
                   1043:        }
                   1044:        else {
                   1045:            /*
                   1046:             * Lost carrier.
                   1047:             */
                   1048:            tp->t_state &= ~TS_CARR_ON;
                   1049:            if (tp->t_state & TS_ISOPEN &&
                   1050:                (tp->t_flags & NOHANG) == 0)
                   1051:            {
                   1052:                /*
                   1053:                 * Hang up TTY if carrier drops.
                   1054:                 * Need to alert users, somehow...
                   1055:                 */
                   1056:                tty_flush(tp, D_READ|D_WRITE);
                   1057:                return FALSE;
                   1058:            }
                   1059:        }
                   1060:        return TRUE;
                   1061: }
                   1062: 
                   1063: /*
                   1064:  * Similarly, handle transitions on the ClearToSend
                   1065:  * signal.  Nowadays, it is used by many modems as
                   1066:  * a flow-control device: they turn it down to stop
                   1067:  * us from sending more chars.  We do the same with
                   1068:  * the RequestToSend signal. [Yes, that is exactly
                   1069:  * why those signals are defined in the standard.]
                   1070:  *
                   1071:  * Tty must be locked and on master.
                   1072:  */
1.1.1.4   root     1073: void
1.1       root     1074: tty_cts(
                   1075:        struct tty *    tp,
                   1076:        boolean_t       cts_up)
                   1077: {
                   1078:        if (tp->t_state & TS_ISOPEN){
                   1079:                if (cts_up) {
                   1080:                        tp->t_state &= ~(TS_TTSTOP|TS_BUSY);
                   1081:                        tty_output(tp);
                   1082:                } else {
                   1083:                        tp->t_state |= (TS_TTSTOP|TS_BUSY);
                   1084:                        (*tp->t_stop)(tp, D_WRITE);
                   1085:                }
                   1086:        }
                   1087: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.