]>
git.saurik.com Git - apple/xnu.git/blob - bsd/dev/i386/km.c
   2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  28 /*      Copyright (c) 1992 NeXT Computer, Inc.  All rights reserved. 
  30  * km.m - kernel keyboard/monitor module, procedural interface. 
  35 #include <sys/param.h> 
  38 #include <machine/cons.h> 
  40 #include <sys/systm.h> 
  42 #include <sys/fcntl.h>          /* for kmopen */ 
  43 #include <sys/errno.h> 
  44 #include <sys/proc.h>           /* for kmopen */ 
  45 #include <sys/msgbuf.h> 
  47 #include <dev/kmreg_com.h> 
  48 #include <pexpert/pexpert.h> 
  49 #include <pexpert/i386/boot.h> 
  53 extern void cnputcusr(char); 
  54 extern void cnputsusr(char *, int); 
  55 extern int  cngetc(void); 
  58 void    cons_cinput(char ch
); 
  61  * 'Global' variables, shared only by this file and conf.c. 
  63 struct tty 
*km_tty
[1] = { 0 }; 
  66  * this works early on, after initialize_screen() but before autoconf (and thus 
  67  * before we have a kmDevice). 
  69 int disableConsoleOutput
; 
  72  * 'Global' variables, shared only by this file and kmDevice.m. 
  76 static int kmoutput(struct tty 
*tp
); 
  77 static void kmstart(struct tty 
*tp
); 
  79 extern void KeyboardOpen(void); 
  84         km_tty
[0] = ttymalloc(); 
  85         km_tty
[0]->t_dev 
= makedev(12, 0); 
  90  * cdevsw interface to km driver. 
  93 kmopen(dev_t dev
, int flag
, __unused 
int devtype
, proc_t pp
) 
 109         tp
->t_oproc 
= kmstart
; 
 113         if (!(tp
->t_state 
& TS_ISOPEN
)) { 
 114                 tp
->t_iflag 
= TTYDEF_IFLAG
; 
 115                 tp
->t_oflag 
= TTYDEF_OFLAG
; 
 116                 tp
->t_cflag 
= (CREAD 
| CS8 
| CLOCAL
); 
 117                 tp
->t_lflag 
= TTYDEF_LFLAG
; 
 118                 tp
->t_ispeed 
= tp
->t_ospeed 
= TTYDEF_SPEED
; 
 119                 termioschars(&tp
->t_termios
); 
 121         } else if ((tp
->t_state 
& TS_XCLUDE
) && proc_suser(pp
)) { 
 126         tp
->t_state 
|= TS_CARR_ON
; /* lie and say carrier exists and is on. */ 
 128         ret 
= ((*linesw
[tp
->t_line
].l_open
)(dev
, tp
)); 
 133                  * Magic numbers.  These are CHARWIDTH and CHARHEIGHT 
 134                  * from pexpert/i386/video_console.c 
 139                 tty_unlock(tp
);         /* XXX race window */ 
 141                 if (flag 
& O_POPUP
) { 
 142                         PE_initialize_console(0, kPETextScreen
); 
 145                 bzero(&video
, sizeof(video
)); 
 146                 PE_current_console(&video
); 
 150                 if (video
.v_display 
== FB_TEXT_MODE 
&& video
.v_width 
!= 0 && video
.v_height 
!= 0) { 
 151                         wp
->ws_col 
= video
.v_width 
/ wp
->ws_xpixel
; 
 152                         wp
->ws_row 
= video
.v_height 
/ wp
->ws_ypixel
; 
 166 kmclose(dev_t dev
, int flag
, __unused 
int mode
, __unused proc_t p
) 
 169         struct tty 
*tp 
= km_tty
[minor(dev
)]; 
 172         ret 
= (*linesw
[tp
->t_line
].l_close
)(tp
, flag
); 
 180 kmread(dev_t dev
, struct uio 
*uio
, int ioflag
) 
 183         struct tty 
*tp 
= km_tty
[minor(dev
)]; 
 186         ret 
= (*linesw
[tp
->t_line
].l_read
)(tp
, uio
, ioflag
); 
 193 kmwrite(dev_t dev
, struct uio 
*uio
, int ioflag
) 
 196         struct tty 
*tp 
= km_tty
[minor(dev
)]; 
 199         ret 
= (*linesw
[tp
->t_line
].l_write
)(tp
, uio
, ioflag
); 
 206 kmioctl(dev_t dev
, u_long cmd
, caddr_t data
, int flag
, proc_t p
) 
 209         struct tty 
*tp 
= km_tty
[minor(dev
)]; 
 216                 wp 
= (struct winsize 
*)data
; 
 221                 /* Prevent changing of console size -- 
 222                  * this ensures that login doesn't revert to the 
 223                  * termcap-defined size 
 228         /* Bodge in the CLOCAL flag as the km device is always local */ 
 233                 struct termios32 
*t 
= (struct termios32 
*)data
; 
 234                 t
->c_cflag 
|= CLOCAL
; 
 242                 struct user_termios 
*t 
= (struct user_termios 
*)data
; 
 243                 t
->c_cflag 
|= CLOCAL
; 
 248                 error 
= (*linesw
[tp
->t_line
].l_ioctl
)(tp
, cmd
, data
, flag
, p
); 
 249                 if (ENOTTY 
!= error
) { 
 252                 error 
= ttioctl_locked(tp
, cmd
, data
, flag
, p
); 
 264  * Output a character to the serial console driver via cnputcusr(), 
 265  * which is exported by that driver. 
 267  * Locks:       Assumes tp in the calling tty driver code is locked on 
 268  *              entry, remains locked on exit 
 270  * Notes:       Called from kmoutput(); giving the locking output 
 271  *              assumptions here, this routine should be static (and 
 272  *              inlined, given there is only one call site). 
 275 kmputc(__unused dev_t dev
, char c
) 
 277         if (!disableConsoleOutput 
&& initialized
) { 
 290  * Callouts from linesw. 
 293 #define KM_LOWAT_DELAY  ((ns_time_t)1000) 
 296  * t_oproc for this driver; called from within the line discipline 
 298  * Locks:       Assumes tp is locked on entry, remains locked on exit 
 301 kmstart(struct tty 
*tp
) 
 303         if (tp
->t_state 
& (TS_TIMEOUT 
| TS_BUSY 
| TS_TTSTOP
)) { 
 306         if (tp
->t_outq
.c_cc 
== 0) { 
 309         tp
->t_state 
|= TS_BUSY
; 
 314         (*linesw
[tp
->t_line
].l_start
)(tp
); 
 319  * One-shot output retry timeout from kmoutput(); re-calls kmoutput() at 
 320  * intervals until the output queue for the tty is empty, at which point 
 321  * the timeout is not rescheduled by kmoutput() 
 323  * This function must take the tty_lock() around the kmoutput() call; it 
 324  * ignores the return value. 
 329         struct tty      
*tp 
= (struct tty 
*)arg
; 
 339  * Locks:       Assumes tp is locked on entry, remains locked on exit 
 341  * Notes:       Called from kmstart() and kmtimeout(); kmtimeout() is a 
 342  *              timer initiated by this routine to deal with pending 
 343  *              output not yet flushed (output is flushed at a maximum 
 344  *              of sizeof(buf) charatcers at a time before dropping into 
 348 kmoutput(struct tty 
*tp
) 
 350         unsigned char   buf
[80];        /* buffer; limits output per call */ 
 355         /* While there is data available to be output... */ 
 356         while (tp
->t_outq
.c_cc 
> 0) { 
 357                 cc 
= ndqb(&tp
->t_outq
, 0); 
 362                  * attempt to output as many characters as are available, 
 363                  * up to the available transfer buffer size. 
 365                 cc 
= min(cc
, sizeof(buf
)); 
 366                 /* copy the output queue contents to the buffer */ 
 367                 (void) q_to_b(&tp
->t_outq
, buf
, cc
); 
 368                 for (cp 
= buf
; cp 
< &buf
[cc
]; cp
++) { 
 369                         /* output the buffer one charatcer at a time */ 
 374                         cnputsusr((char *)buf
, cc
); 
 376                         kmputc(tp
->t_dev
, *buf
); 
 380          * XXX This is likely not necessary, as the tty output queue is not 
 381          * XXX writeable while we hold the tty_lock(). 
 383         if (tp
->t_outq
.c_cc 
> 0) { 
 384                 timeout(kmtimeout
, tp
, hz
); 
 386         tp
->t_state 
&= ~TS_BUSY
; 
 387         /* Start the output processing for the line discipline */ 
 388         (*linesw
[tp
->t_line
].l_start
)(tp
); 
 397  * Driver character input from the polled mode serial console driver calls 
 398  * this routine to input a character from the serial driver into the tty 
 399  * line discipline specific input processing receiv interrupt routine, 
 402  * Locks:       Assumes that the tty_lock() is NOT held on the tp, so a 
 403  *              serial driver should NOT call this function as a result 
 404  *              of being called from a function which already holds the 
 405  *              lock; ECHOE will be handled at the line discipline, if 
 406  *              output echo processing is going to occur. 
 411         struct tty 
*tp 
= km_tty
[0];     /* XXX */ 
 414         (*linesw
[tp
->t_line
].l_rint
)(ch
, tp
);