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

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

unix.superglobalmegacorp.com

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