X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/1c79356b52d46aa6b508fb032f5ae709b1f2897b..fe8ab488e9161c46dd9885d58fc52996dc0249ff:/bsd/dev/i386/km.c?ds=sidebyside diff --git a/bsd/dev/i386/km.c b/bsd/dev/i386/km.c index ac1054724..d276b6d95 100644 --- a/bsd/dev/i386/km.c +++ b/bsd/dev/i386/km.c @@ -1,23 +1,29 @@ /* * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. * @@ -29,7 +35,7 @@ #include #include -#include +#include #include #include #include @@ -40,12 +46,20 @@ #include #include #include +#include + +extern int hz; + +extern void cnputcusr(char); +extern int cngetc(void); + +void kminit(void); +void cons_cinput(char ch); /* * 'Global' variables, shared only by this file and conf.c. */ -extern struct tty cons; -struct tty *km_tty[1] = { &cons }; +struct tty *km_tty[1] = { 0 }; /* * this works early on, after initialize_screen() but before autoconf (and thus @@ -59,27 +73,24 @@ int disableConsoleOutput; int initialized = 0; static int kmoutput(struct tty *tp); -static void kmtimeout(struct tty *tp); static void kmstart(struct tty *tp); extern void KeyboardOpen(void); -int kminit() +void +kminit(void) { - cons.t_dev = makedev(12, 0); + km_tty[0] = ttymalloc(); + km_tty[0]->t_dev = makedev(12, 0); initialized = 1; } + /* * cdevsw interface to km driver. */ int -kmopen( - dev_t dev, - int flag, - int devtype, - struct proc *pp) +kmopen(dev_t dev, int flag, __unused int devtype, proc_t pp) { - int rtn; int unit; struct tty *tp; struct winsize *wp; @@ -89,7 +100,10 @@ kmopen( if(unit >= 1) return (ENXIO); - tp = (struct tty *)&cons; + tp = km_tty[unit]; + + tty_lock(tp); + tp->t_oproc = kmstart; tp->t_param = NULL; tp->t_dev = dev; @@ -102,26 +116,35 @@ kmopen( tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; termioschars(&tp->t_termios); ttsetwater(tp); - } else if ((tp->t_state & TS_XCLUDE) && pp->p_ucred->cr_uid != 0) - return EBUSY; + } else if ((tp->t_state & TS_XCLUDE) && proc_suser(pp)) { + ret = EBUSY; + goto out; + } tp->t_state |= TS_CARR_ON; /* lie and say carrier exists and is on. */ + ret = ((*linesw[tp->t_line].l_open)(dev, tp)); { PE_Video video; wp = &tp->t_winsize; - /* Magic numbers. These are CHARWIDTH and CHARHEIGHT + /* + * Magic numbers. These are CHARWIDTH and CHARHEIGHT * from pexpert/i386/video_console.c */ wp->ws_xpixel = 8; wp->ws_ypixel = 16; + tty_unlock(tp); /* XXX race window */ + if (flag & O_POPUP) PE_initialize_console(0, kPETextScreen); bzero(&video, sizeof(video)); PE_current_console(&video); - if( video.v_width != 0 && video.v_height != 0 ) { + + tty_lock(tp); + + if( video.v_display == FB_TEXT_MODE && video.v_width != 0 && video.v_height != 0 ) { wp->ws_col = video.v_width / wp->ws_xpixel; wp->ws_row = video.v_height / wp->ws_ypixel; } else { @@ -129,233 +152,251 @@ kmopen( wp->ws_row = 36; } } + +out: + tty_unlock(tp); + return ret; } int -kmclose( - dev_t dev, - int flag, - int mode, - struct proc *p) +kmclose(dev_t dev, int flag, __unused int mode, __unused proc_t p) { - - struct tty *tp; + int ret; + struct tty *tp = km_tty[minor(dev)]; - tp = &cons; - (*linesw[tp->t_line].l_close)(tp,flag); + tty_lock(tp); + ret = (*linesw[tp->t_line].l_close)(tp,flag); ttyclose(tp); - return (0); + tty_unlock(tp); + + return (ret); } int -kmread( - dev_t dev, - struct uio *uio, - int ioflag) +kmread(dev_t dev, struct uio *uio, int ioflag) { - register struct tty *tp; - - tp = &cons; - return ((*linesw[tp->t_line].l_read)(tp, uio, ioflag)); + int ret; + struct tty *tp = km_tty[minor(dev)]; + + tty_lock(tp); + ret = (*linesw[tp->t_line].l_read)(tp, uio, ioflag); + tty_unlock(tp); + + return (ret); } int -kmwrite( - dev_t dev, - struct uio *uio, - int ioflag) +kmwrite(dev_t dev, struct uio *uio, int ioflag) { - register struct tty *tp; - - tp = &cons; - return ((*linesw[tp->t_line].l_write)(tp, uio, ioflag)); + int ret; + struct tty *tp = km_tty[minor(dev)]; + + tty_lock(tp); + ret = (*linesw[tp->t_line].l_write)(tp, uio, ioflag); + tty_unlock(tp); + + return (ret); } int -kmioctl( - dev_t dev, - int cmd, - caddr_t data, - int flag, - struct proc *p) +kmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, proc_t p) { - int error; - struct tty *tp = &cons; + int error = 0; + struct tty *tp = km_tty[minor(dev)]; struct winsize *wp; + + tty_lock(tp); switch (cmd) { - - - case KMIOCSIZE: wp = (struct winsize *)data; *wp = tp->t_winsize; - return 0; + break; case TIOCSWINSZ: /* Prevent changing of console size -- * this ensures that login doesn't revert to the * termcap-defined size */ - return EINVAL; + error = EINVAL; + break; /* Bodge in the CLOCAL flag as the km device is always local */ - case TIOCSETA: - case TIOCSETAW: - case TIOCSETAF: { - register struct termios *t = (struct termios *)data; - t->c_cflag |= CLOCAL; - /* No Break */ - } - default: - error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); - if (error >= 0) { - return error; - } - error = ttioctl (tp, cmd, data, flag, p); - if (error >= 0) { - return error; + case TIOCSETA_32: + case TIOCSETAW_32: + case TIOCSETAF_32: + { + struct termios32 *t = (struct termios32 *)data; + t->c_cflag |= CLOCAL; + /* No Break */ } - else { - return ENOTTY; + goto fallthrough; + case TIOCSETA_64: + case TIOCSETAW_64: + case TIOCSETAF_64: + { + struct user_termios *t = (struct user_termios *)data; + t->c_cflag |= CLOCAL; + /* No Break */ } +fallthrough: + default: + error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); + if (ENOTTY != error) + break; + error = ttioctl_locked(tp, cmd, data, flag, p); + break; } -} - -int -kmputc( - int c) -{ - if( disableConsoleOutput) - return( 0); + tty_unlock(tp); - if(!initialized) - return( 0); - - if(c == '\n') - cnputc('\r'); - - cnputc(c); - - return 0; + return (error); } +/* + * kmputc + * + * Output a character to the serial console driver via cnputcusr(), + * which is exported by that driver. + * + * Locks: Assumes tp in the calling tty driver code is locked on + * entry, remains locked on exit + * + * Notes: Called from kmoutput(); giving the locking output + * assumptions here, this routine should be static (and + * inlined, given there is only one call site). + */ int -kmgetc( - dev_t dev) +kmputc(__unused dev_t dev, char c) { - int c; - - c= cngetc(); - - if (c == '\r') { - c = '\n'; + if(!disableConsoleOutput && initialized) { + /* OCRNL */ + if(c == '\n') + cnputcusr('\r'); + cnputcusr(c); } - cnputc(c); - return c; -} -int -kmgetc_silent( - dev_t dev) -{ - int c; - - c= cngetc(); - if (c == '\r') { - c = '\n'; - } - return c; + return (0); } + /* * Callouts from linesw. */ #define KM_LOWAT_DELAY ((ns_time_t)1000) +/* + * t_oproc for this driver; called from within the line discipline + * + * Locks: Assumes tp is locked on entry, remains locked on exit + */ static void -kmstart( - struct tty *tp) +kmstart(struct tty *tp) { - extern int hz; if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) goto out; if (tp->t_outq.c_cc == 0) goto out; tp->t_state |= TS_BUSY; - if (tp->t_outq.c_cc > tp->t_lowat) { - /* - * Start immediately. - */ - kmoutput(tp); - } - else { - /* - * Wait a bit... - */ -#if 0 - /* FIXME */ - timeout(kmtimeout, tp, hz); -#else - kmoutput(tp); -#endif - } + kmoutput(tp); + return; + out: - ttwwakeup(tp); + (*linesw[tp->t_line].l_start)(tp); + return; } +/* + * One-shot output retry timeout from kmoutput(); re-calls kmoutput() at + * intervals until the output queue for the tty is empty, at which point + * the timeout is not rescheduled by kmoutput() + * + * This function must take the tty_lock() around the kmoutput() call; it + * ignores the return value. + */ static void -kmtimeout( struct tty *tp) +kmtimeout(void *arg) { - boolean_t funnel_state; - - funnel_state = thread_funnel_set(kernel_flock, TRUE); - kmoutput(tp); - (void) thread_funnel_set(kernel_flock, FALSE); - + struct tty *tp = (struct tty *)arg; + tty_lock(tp); + (void)kmoutput(tp); + tty_unlock(tp); } + +/* + * kmoutput + * + * Locks: Assumes tp is locked on entry, remains locked on exit + * + * Notes: Called from kmstart() and kmtimeout(); kmtimeout() is a + * timer initiated by this routine to deal with pending + * output not yet flushed (output is flushed at a maximum + * of sizeof(buf) charatcers at a time before dropping into + * the timeout code). + */ static int -kmoutput( - struct tty *tp) +kmoutput(struct tty *tp) { - /* - * FIXME - to be grokked...copied from m68k km.c. - */ - char buf[80]; - char *cp; + unsigned char buf[80]; /* buffer; limits output per call */ + unsigned char *cp; int cc = -1; - extern int hz; + /* While there is data available to be output... */ while (tp->t_outq.c_cc > 0) { cc = ndqb(&tp->t_outq, 0); if (cc == 0) break; - cc = min(cc, sizeof buf); + /* + * attempt to output as many characters as are available, + * up to the available transfer buffer size. + */ + cc = min(cc, sizeof(buf)); + /* copy the output queue contents to the buffer */ (void) q_to_b(&tp->t_outq, buf, cc); for (cp = buf; cp < &buf[cc]; cp++) { - kmputc(*cp & 0x7f); + /* output the buffer one charatcer at a time */ + kmputc(tp->t_dev, *cp & 0x7f); } } + /* + * XXX This is likely not necessary, as the tty output queue is not + * XXX writeable while we hold the tty_lock(). + */ if (tp->t_outq.c_cc > 0) { timeout(kmtimeout, tp, hz); } tp->t_state &= ~TS_BUSY; - ttwwakeup(tp); + /* Start the output processing for the line discipline */ + (*linesw[tp->t_line].l_start)(tp); return 0; } + + +/* + * cons_cinput + * + * Driver character input from the polled mode serial console driver calls + * this routine to input a character from the serial driver into the tty + * line discipline specific input processing receiv interrupt routine, + * l_rint(). + * + * Locks: Assumes that the tty_lock() is NOT held on the tp, so a + * serial driver should NOT call this function as a result + * of being called from a function which already holds the + * lock; ECHOE will be handled at the line discipline, if + * output echo processing is going to occur. + */ +void cons_cinput(char ch) { - struct tty *tp = &cons; - boolean_t funnel_state; + struct tty *tp = km_tty[0]; /* XXX */ - + tty_lock(tp); (*linesw[tp->t_line].l_rint) (ch, tp); - + tty_unlock(tp); } -