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

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

unix.superglobalmegacorp.com

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