darwin-xnu/bsd/dev/ppc/km.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
   3 *
   4 * @APPLE_LICENSE_HEADER_START@
   5 * 
   6 * The contents of this file constitute Original Code as defined in and
   7 * are subject to the Apple Public Source License Version 1.1 (the
   8 * "License").  You may not use this file except in compliance with the
   9 * License.  Please obtain a copy of the License at
  10 * http://www.apple.com/publicsource and read it before using this file.
  11 * 
  12 * This Original Code and all software distributed under the License are
  13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
  17 * License for the specific language governing rights and limitations
  18 * under the License.
  19 * 
  20 * @APPLE_LICENSE_HEADER_END@
  21 */
  22/*      Copyright (c) 1992 NeXT Computer, Inc.  All rights reserved. 
  23 *
  24 * km.m - kernel keyboard/monitor module, procedural interface.
  25 *
  26 * HISTORY
  27 */
  28
  29#include <sys/kernel.h>
  30#include <sys/tty.h>
  31
  32#include <dev/ppc/cons.h>
  33#include <sys/conf.h>
  34#include <sys/systm.h>
  35#include <sys/uio.h>
  36#include <sys/fcntl.h>          /* for kmopen */
  37#include <sys/errno.h>          
  38#include <sys/proc.h>           /* for kmopen */
  39#include <sys/msgbuf.h>
  40#include <sys/time.h>
  41#include <dev/kmreg_com.h>
  42#include <pexpert/pexpert.h>
  43
  44/*
  45 * 'Global' variables, shared only by this file and conf.c.
  46 */
  47struct tty *km_tty[1] = { &cons };
  48
  49/*
  50 * this works early on, after initialize_screen() but before autoconf (and thus
  51 * before we have a kmDevice).
  52 */
  53int disableConsoleOutput;
  54
  55static int initialized = 0;
  56
  57// Function prototypes
  58extern d_open_t         kmopen;
  59extern d_close_t        kmclose;
  60extern d_read_t         kmread;
  61extern d_write_t        kmwrite;
  62extern d_ioctl_t        kmioctl;
  63extern d_getc_t         kmgetc;
  64extern d_putc_t         kmputc;
  65
  66extern void kminit(void);
  67
  68// used by or implemented in the osfmk project
  69extern void cnputcusr(char);            // From osfmk
  70extern int  cngetc(void);               // From osfmk
  71extern void cons_cinput(char ch);       // Used by osfmk
  72
  73static int kmoutput(struct tty *tp);
  74static void kmtimeout(struct tty *tp);
  75static void kmstart(struct tty *tp);
  76
  77extern void KeyboardOpen(void);
  78
  79void
  80kminit(void)
  81{
  82         cons.t_dev = makedev(12, 0);
  83        initialized = 1;
  84}
  85/*
  86 * cdevsw interface to km driver.
  87 */
  88int 
  89kmopen(dev_t dev, int flag, __unused int devtype, struct proc *pp)
  90{
  91        int unit;
  92        struct tty *tp;
  93        struct winsize *wp;
  94        int ret;
  95        
  96        unit = minor(dev);
  97        if(unit >= 1)
  98                return (ENXIO);
  99
 100        tp = (struct tty *)&cons;
 101        tp->t_oproc = kmstart;
 102        tp->t_param = NULL;
 103        tp->t_dev = dev;
 104        
 105        if ( !(tp->t_state & TS_ISOPEN) ) {
 106                tp->t_iflag = TTYDEF_IFLAG;
 107                tp->t_oflag = TTYDEF_OFLAG;
 108                tp->t_cflag = (CREAD | CS8 | CLOCAL);
 109                tp->t_lflag = TTYDEF_LFLAG;
 110                tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
 111                termioschars(&tp->t_termios);
 112                ttsetwater(tp);
 113        } else if ((tp->t_state & TS_XCLUDE) && proc_suser(pp))
 114                return EBUSY;
 115
 116        tp->t_state |= TS_CARR_ON; /* lie and say carrier exists and is on. */
 117        ret = ((*linesw[tp->t_line].l_open)(dev, tp));
 118        {
 119                PE_Video video;
 120                wp = &tp->t_winsize;
 121                /* Magic numbers.  These are CHARWIDTH and CHARHEIGHT
 122                 * from osfmk/ppc/POWERMAC/video_console.c
 123                 */
 124                wp->ws_xpixel = 8;
 125                wp->ws_ypixel = 16;
 126
 127                if (flag & O_POPUP)
 128                        PE_initialize_console(0, kPETextScreen);
 129
 130                bzero(&video, sizeof(video));
 131                PE_current_console(&video);
 132                if( video.v_width != 0 && video.v_height != 0 ) {
 133                        wp->ws_col = video.v_width / wp->ws_xpixel;
 134                        wp->ws_row = video.v_height / wp->ws_ypixel;
 135                } else {
 136                        wp->ws_col = 100;
 137                        wp->ws_row = 36;
 138                }
 139        }
 140        return ret;
 141}
 142
 143int 
 144kmclose(__unused dev_t dev, __unused int flag, __unused int mode,
 145        __unused struct proc *p)
 146{
 147         
 148        struct tty *tp;
 149
 150        tp = &cons;
 151        (*linesw[tp->t_line].l_close)(tp,flag);
 152        ttyclose(tp);
 153        return (0);
 154}
 155
 156int 
 157kmread(__unused dev_t dev, struct uio *uio, int ioflag)
 158{
 159        register struct tty *tp;
 160 
 161        tp = &cons;
 162        return ((*linesw[tp->t_line].l_read)(tp, uio, ioflag));
 163}
 164
 165int 
 166kmwrite(__unused dev_t dev, struct uio *uio, int ioflag)
 167{
 168        register struct tty *tp;
 169 
 170        tp = &cons;
 171        return ((*linesw[tp->t_line].l_write)(tp, uio, ioflag));
 172}
 173
 174int 
 175kmioctl( __unused dev_t dev, u_long cmd, caddr_t data, int flag,
 176        struct proc *p)
 177{
 178        int error;
 179        struct tty *tp = &cons;
 180        struct winsize *wp;
 181        
 182        switch (cmd) {
 183                
 184
 185
 186            case KMIOCSIZE:
 187                wp = (struct winsize *)data;
 188                *wp = tp->t_winsize;
 189                return 0;
 190                
 191            case TIOCSWINSZ:
 192                /* Prevent changing of console size --
 193                 * this ensures that login doesn't revert to the
 194                 * termcap-defined size
 195                 */
 196                return EINVAL;
 197
 198            /* Bodge in the CLOCAL flag as the km device is always local */
 199            case TIOCSETA:
 200            case TIOCSETAW:
 201            case TIOCSETAF: {
 202                register struct termios *t = (struct termios *)data;
 203                t->c_cflag |= CLOCAL;
 204                /* No Break */
 205            }
 206            default:            
 207                error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
 208                if (ENOTTY != error)
 209                        return error;
 210                return ttioctl (tp, cmd, data, flag, p);
 211        }
 212}
 213
 214int 
 215kmputc(__unused dev_t dev, char c)
 216{
 217
 218        if( disableConsoleOutput)
 219                return( 0);
 220
 221        if(!initialized)
 222                return( 0);
 223
 224        if(c == '\n')
 225                cnputcusr('\r');
 226
 227        cnputcusr(c);
 228
 229        return 0;
 230}
 231
 232int 
 233kmgetc(__unused dev_t dev)
 234{
 235        int c;
 236        
 237        c= cngetc();
 238
 239        if (c == '\r') {
 240                c = '\n';
 241        }
 242        cnputcusr(c);
 243        return c;
 244}
 245
 246#if 0
 247int 
 248kmgetc_silent(
 249        __unused dev_t dev)
 250{
 251        int c;
 252        
 253        c= cngetc();
 254        if (c == '\r') {
 255                c = '\n';
 256        }
 257        return c;
 258}
 259#endif /* 0 */
 260
 261/*
 262 * Callouts from linesw.
 263 */
 264 
 265#define KM_LOWAT_DELAY  ((ns_time_t)1000)
 266
 267static void 
 268kmstart(struct tty *tp)
 269{
 270        if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
 271                goto out;
 272        if (tp->t_outq.c_cc == 0)
 273                goto out;
 274        tp->t_state |= TS_BUSY;
 275        kmoutput(tp);
 276        return;
 277
 278out:
 279        (*linesw[tp->t_line].l_start)(tp);
 280        return;
 281}
 282
 283static void
 284kmtimeout(struct tty *tp)
 285{
 286        boolean_t       funnel_state;
 287
 288        funnel_state = thread_funnel_set(kernel_flock, TRUE);
 289        kmoutput(tp);
 290        (void) thread_funnel_set(kernel_flock, funnel_state);
 291
 292
 293}
 294static int 
 295kmoutput(struct tty *tp)
 296{
 297        /*
 298         * FIXME - to be grokked...copied from m68k km.c.
 299         */
 300        char            buf[80];
 301        char            *cp;
 302        int             cc = -1;
 303
 304        while (tp->t_outq.c_cc > 0) {
 305                cc = ndqb(&tp->t_outq, 0);
 306                if (cc == 0)
 307                        break;
 308                cc = min(cc, sizeof buf);
 309                (void) q_to_b(&tp->t_outq, buf, cc);
 310                for (cp = buf; cp < &buf[cc]; cp++)
 311                    kmputc(tp->t_dev, *cp & 0x7f);
 312        }
 313        if (tp->t_outq.c_cc > 0) {
 314                timeout((timeout_fcn_t)kmtimeout, tp, hz);
 315        }
 316        tp->t_state &= ~TS_BUSY;
 317        (*linesw[tp->t_line].l_start)(tp);
 318
 319        return 0;
 320}
 321
 322void cons_cinput(char ch)
 323{
 324        struct tty *tp = &cons;
 325        
 326        (*linesw[tp->t_line].l_rint) (ch, tp);
 327}
 328
 329
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.