Annotation of XNU/osfmk/ppc/serial_console.c, revision 1.1

1.1     ! root        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: /*
        !            23:  * @OSF_COPYRIGHT@
        !            24:  */
        !            25: /*
        !            26:  * @APPLE_FREE_COPYRIGHT@
        !            27:  */
        !            28: 
        !            29: #include <mach_kdb.h>
        !            30: #include <platforms.h>
        !            31: #include <serial_console_default.h>
        !            32: 
        !            33: #include <kern/spl.h>
        !            34: #include <machine/machparam.h>         /* spl definitions */
        !            35: #include <types.h>
        !            36: #include <ppc/POWERMAC/video_console_entries.h>
        !            37: #include <ppc/misc_protos.h>
        !            38: #include <ppc/POWERMAC/serial_io.h>
        !            39: #include <ppc/POWERMAC/mp/mp.h>
        !            40: #include <kern/cpu_number.h>
        !            41: #include <ppc/Firmware.h>
        !            42: #include <ppc/proc_reg.h>
        !            43: #include <pexpert/pexpert.h>
        !            44: 
        !            45: /*
        !            46:  * A machine MUST have a console.  In our case
        !            47:  * things are a little complicated by the graphic
        !            48:  * display: people expect it to be their "console",
        !            49:  * but we'd like to be able to live without it.
        !            50:  * This is not to be confused with the "rconsole" thing:
        !            51:  * that just duplicates the console I/O to
        !            52:  * another place (for debugging/logging purposes).
        !            53:  */
        !            54: 
        !            55: const int console_unit = 0;
        !            56: const int console_chan_default = CONSOLE_PORT;
        !            57: #define console_chan (console_chan_default) /* ^ cpu_number()) */
        !            58: 
        !            59: #define OPS(putc, getc, nosplputc, nosplgetc) putc, getc
        !            60: 
        !            61: const struct console_ops {
        !            62:        int     (*putc)(int, int, int);
        !            63:        int     (*getc)(int, int, boolean_t, boolean_t);
        !            64: } cons_ops[] = {
        !            65: #define SCC_CONS_OPS 0
        !            66:        {OPS(scc_putc, scc_getc, no_spl_scputc, no_spl_scgetc)},
        !            67: #define VC_CONS_OPS 1
        !            68:        {OPS(vcputc, vcgetc, no_spl_vcputc, no_spl_vcgetc)},
        !            69: };
        !            70: #define NCONSOPS (sizeof cons_ops / sizeof cons_ops[0])
        !            71: 
        !            72: #if SERIAL_CONSOLE_DEFAULT
        !            73: #define CONS_OPS SCC_CONS_OPS
        !            74: #define CONS_NAME "com"
        !            75: #else
        !            76: #define CONS_OPS VC_CONS_OPS
        !            77: #define CONS_NAME "vc"
        !            78: #endif
        !            79: 
        !            80: #define MP_SAFE_CONSOLE 1      /* Set this to 1 to allow more than 1 processor to print at once */
        !            81: #if MP_SAFE_CONSOLE
        !            82: 
        !            83: struct ppcbfr {                                                                                                        /* Controls multiple processor output */
        !            84:        unsigned int    pos;                                                                            /* Current position in buffer */
        !            85:        unsigned int    noprompt;                                                                       /* Set if we skip the prompt */
        !            86:        unsigned int    echo;                                                                           /* Control character echoing */
        !            87:        char                    buffer[256];                                                            /* Fairly big buffer */ 
        !            88: };
        !            89: typedef struct ppcbfr ppcbfr;
        !            90: ppcbfr cbfr[NCPUS];                                                                                            /* Get one of these for each processor */
        !            91: volatile unsigned int cbfpend;                                                                 /* A buffer is pending output */
        !            92: volatile unsigned int sconowner=-1;                                                            /* Mark who's actually writing */
        !            93: 
        !            94: #endif
        !            95: 
        !            96: 
        !            97: unsigned int cons_ops_index = CONS_OPS;
        !            98: unsigned int killprint = 0;
        !            99: unsigned int debcnputc = 0;
        !           100: extern unsigned int    mappingdeb0;
        !           101: extern int debugger_holdoff[NCPUS];
        !           102: 
        !           103: static void _cnputc(char c)
        !           104: {
        !           105:        cons_ops[cons_ops_index].putc(console_unit, console_chan, c);
        !           106: }
        !           107: 
        !           108: void cnputcusr(char c) {                                                                               /* Echo input character directly */
        !           109: 
        !           110:        unsigned int cpu;
        !           111:        
        !           112:        if (cpu_data[master_cpu].active_thread) cpu = cpu_number();     /* If we're started up, use the current CPU */
        !           113:        else cpu = master_cpu;                                                                          /* Otherwise use the master_cpu */
        !           114:        
        !           115:        hw_atomic_add(&debugger_holdoff[cpu], 1);                                       /* Don't allow debugger entry just now (this is a HACK) */
        !           116:        
        !           117:        _cnputc( c);                                                                                            /* Echo the character */
        !           118:        if(c=='\n') _cnputc( '\r');                                                                     /* Add a return if we had a new line */
        !           119:        
        !           120:        hw_atomic_sub(&debugger_holdoff[cpu], 1);                                       /* Don't allow debugger entry just now (this is a HACK) */
        !           121:        return;
        !           122: }
        !           123: 
        !           124: void
        !           125: cnputc(char c)
        !           126: {
        !           127: 
        !           128:        unsigned int oldpend, i, cpu, ourbit, sccpu;
        !           129:        spl_t           s;
        !           130:                
        !           131: #if MP_SAFE_CONSOLE
        !           132: 
        !           133: /*
        !           134:  *             Handle multiple CPU console output.
        !           135:  *             Note: this thing has gotten god-awful complicated.  We need a better way.
        !           136:  */
        !           137:        
        !           138: 
        !           139:        if(killprint) {         
        !           140:                return;                                                                                                 /* If printing is disabled, bail... */
        !           141:        }       
        !           142:        
        !           143:        if (cpu_data[master_cpu].active_thread) cpu = cpu_number();     /* If we're started up, use the current CPU */
        !           144:        else cpu = master_cpu;                                                                          /* Otherwise use the master_cpu */
        !           145: 
        !           146:        hw_atomic_add(&debugger_holdoff[cpu], 1);                                       /* Don't allow debugger entry just now (this is a HACK) */
        !           147: 
        !           148:        ourbit = 1 << cpu;                                                                                      /* Make a mask for just us */
        !           149:        if(debugger_cpu != -1) {                                                                        /* Are we in the debugger with empty buffers? */
        !           150:        
        !           151:                while(sconowner != cpu) {                                                               /* Anyone but us? */
        !           152:                        hw_compare_and_store(-1, cpu, (unsigned int *)&sconowner);      /* Try to mark it for us if idle */
        !           153:                }
        !           154:        
        !           155:                _cnputc( c);                                                                                    /* Yeah, just write it */
        !           156:                if(c=='\n')                                                                                             /* Did we just write a new line? */
        !           157:                        _cnputc( '\r');                                                                         /* Yeah, just add a return */
        !           158:                        
        !           159:                sconowner=-1;                                                                                   /* Mark it idle */      
        !           160:                hw_atomic_sub(&debugger_holdoff[cpu], 1);                               /* Don't allow debugger entry just now (this is a HACK) */
        !           161:                
        !           162:                return;                                                                                                 /* Leave... */
        !           163:        }
        !           164: 
        !           165:        s=splhigh();                                                                                            /* Don't bother me */
        !           166:        
        !           167:        while(ourbit&cbfpend);                                                                          /* We aren't "double buffered," so we'll just wait until the buffers are written */
        !           168:        isync();                                                                                                        /* Just in case we had to wait */
        !           169:        
        !           170:        if(c) {                                                                                                         /* If the character is not null */
        !           171:                cbfr[cpu].buffer[cbfr[cpu].pos]=c;                                              /* Fill in the buffer for our CPU */
        !           172:                cbfr[cpu].pos++;                                                                                /* Up the count */
        !           173:                if(cbfr[cpu].pos > 253) {                                                               /* Is the buffer full? */
        !           174:                        cbfr[cpu].buffer[254]='\n';                                                     /* Yeah, set the second to last as a LF */
        !           175:                        cbfr[cpu].buffer[255]='\r';                                                     /* And the last to a CR */
        !           176:                        cbfr[cpu].pos=256;                                                                      /* Push the buffer to the end */
        !           177:                        c='\r';                                                                                         /* Set character to a CR */
        !           178:                }
        !           179:        }
        !           180:        
        !           181:        if(c == '\n') {                                                                                         /* Are we finishing a line? */
        !           182:                cbfr[cpu].buffer[cbfr[cpu].pos]='\r';                                   /* And the last to a CR */
        !           183:                cbfr[cpu].pos++;                                                                                /* Up the count */
        !           184:                c='\r';                                                                                                 /* Set character to a CR */
        !           185:        }
        !           186: 
        !           187: #if 1
        !           188:        if(cbfr[cpu].echo == 1) {                                                                       /* Did we hit an escape last time? */
        !           189:                if(c == 'K') {                                                                                  /* Is it a partial clear? */
        !           190:                        cbfr[cpu].echo = 2;                                                                     /* Yes, enter echo mode */
        !           191:                }
        !           192:                else cbfr[cpu].echo = 0;                                                                /* Otherwise reset escape */
        !           193:        }
        !           194:        else if(cbfr[cpu].echo == 0) {                                                          /* Not in escape sequence, see if we should enter */
        !           195:                cbfr[cpu].echo = 1;                                                                             /* Set that we are in escape sequence */
        !           196:        }
        !           197: #endif
        !           198: 
        !           199:        if((c == 0x00) || (c == '\r') || (cbfr[cpu].echo == 2)) {       /* Try to push out all buffers if we see CR or null */
        !           200:                                
        !           201:                while(1) {                                                                                              /* Loop until we see who's doing this */
        !           202:                        oldpend=cbfpend;                                                                        /* Get the currentest pending buffer flags */
        !           203:                        if(hw_compare_and_store(oldpend, oldpend|ourbit, (unsigned int *)&cbfpend))     /* Swap ours on if no change */
        !           204:                                break;                                                                                  /* Bail the loop if it worked */
        !           205:                }
        !           206:                
        !           207:                if(!hw_compare_and_store(-1, cpu, (unsigned int *)&sconowner)) {        /* See if someone else has this, and take it if not */
        !           208:                        debugger_holdoff[cpu] = 0;                                                      /* Allow debugger entry (this is a HACK) */
        !           209:                        splx(s);                                                                                        /* Let's take some 'rupts now */
        !           210:                        return;                                                                                         /* We leave here, 'cause another processor is already writing the buffers */
        !           211:                }
        !           212:                                
        !           213:                while(1) {                                                                                              /* Loop to dump out all of the finished buffers */
        !           214:                        oldpend=cbfpend;                                                                        /* Get the most current finished buffers */
        !           215:                        for(sccpu=0; sccpu<NCPUS; sccpu++) {                            /* Cycle through all CPUs buffers */
        !           216:                                
        !           217:                                if(oldpend&(1<<sccpu)) {                                                /* Does this guy have a buffer to do? */
        !           218: 
        !           219: #if 0
        !           220:                                        if(!cbfr[sccpu].noprompt) {                                     /* Don't prompt if there was not CR before */
        !           221:                                                _cnputc( '{');  /* Mark CPU number */
        !           222:                                                _cnputc( '0'+sccpu);    /* Mark CPU number */
        !           223:                                                _cnputc( '.');  /* (TEST/DEBUG) */
        !           224:                                                _cnputc( '0'+cpu);      /* (TEST/DEBUG) */
        !           225:                                                _cnputc( '}');  /* Mark CPU number */
        !           226:                                                _cnputc( ' ');  /* Mark CPU number */
        !           227:                                        }
        !           228: #endif
        !           229:                                        
        !           230:                                        for(i=0; i<cbfr[sccpu].pos; i++) {                      /* Do the whole buffer */
        !           231:                                                _cnputc( cbfr[sccpu].buffer[i]); /* Write it */
        !           232:                                        }
        !           233:                                        
        !           234:                                        if(cbfr[sccpu].buffer[cbfr[sccpu].pos-1]!='\r') {       /* Was the last character a return? */
        !           235:                                                cbfr[sccpu].noprompt = 1;                               /* Remember not to prompt */
        !           236:                                        }
        !           237:                                        else {                                                                          /* Last was a return */
        !           238:                                                cbfr[sccpu].noprompt = 0;                               /* Otherwise remember to prompt */
        !           239:                                                cbfr[sccpu].echo = 0;                                   /* And clear echo */
        !           240:                                        }
        !           241:                                                
        !           242:                                        cbfr[sccpu].pos=0;                                                      /* Reset the buffer pointer */
        !           243:                
        !           244:                                        while(!hw_compare_and_store(cbfpend, cbfpend&~(1<<sccpu), (unsigned int *)&cbfpend));   /* Swap it off */
        !           245:                                }
        !           246:                        }
        !           247:                        sconowner=-1;                                                                           /* Set the writer to idle */
        !           248:                        sync();                                                                                         /* Insure that everything's done */
        !           249:                        if(hw_compare_and_store(0, 0, (unsigned int *)&cbfpend)) break; /* If there are no new buffers, we are done... */
        !           250:                        if(!hw_compare_and_store(-1, cpu, (unsigned int *)&sconowner)) break;   /* If this isn't idle anymore, we're done */
        !           251:        
        !           252:                }
        !           253:        }
        !           254:        hw_atomic_sub(&debugger_holdoff[cpu], 1);                                       /* Don't allow debugger entry just now (this is a HACK) */
        !           255:        splx(s);                                                                                                        /* Let's take some 'rupts now */
        !           256: 
        !           257: #else  /* MP_SAFE_CONSOLE */
        !           258:        _cnputc( c);
        !           259:        if (c == '\n')
        !           260:                _cnputc('\r');
        !           261: #endif  /* MP_SAFE_CONSOLE */
        !           262: 
        !           263: }
        !           264: 
        !           265: int
        !           266: cngetc()
        !           267: {
        !           268:        return cons_ops[cons_ops_index].getc(console_unit, console_chan,
        !           269:                                             TRUE, FALSE);
        !           270: }
        !           271: 
        !           272: int
        !           273: cnmaygetc()
        !           274: {
        !           275:        return cons_ops[cons_ops_index].getc(console_unit, console_chan,
        !           276:                                             FALSE, FALSE);
        !           277: }
        !           278: 
        !           279: boolean_t console_is_serial()
        !           280: {
        !           281:        return cons_ops_index == SCC_CONS_OPS;
        !           282: }
        !           283: 
        !           284: int
        !           285: switch_to_video_console()
        !           286: {
        !           287:        int old_cons_ops = cons_ops_index;
        !           288:        cons_ops_index = VC_CONS_OPS;
        !           289:        return old_cons_ops;
        !           290: }
        !           291: 
        !           292: int
        !           293: switch_to_serial_console()
        !           294: {
        !           295:        int old_cons_ops = cons_ops_index;
        !           296:        cons_ops_index = SCC_CONS_OPS;
        !           297:        return old_cons_ops;
        !           298: }
        !           299: 
        !           300: /* The switch_to_{video,serial,kgdb}_console functions return a cookie that
        !           301:    can be used to restore the console to whatever it was before, in the
        !           302:    same way that splwhatever() and splx() work.  */
        !           303: void
        !           304: switch_to_old_console(int old_console)
        !           305: {
        !           306:        static boolean_t squawked;
        !           307:        unsigned int ops = old_console;
        !           308: 
        !           309:        if (ops >= NCONSOPS && !squawked) {
        !           310:                squawked = TRUE;
        !           311:                printf("switch_to_old_console: unknown ops %d\n", ops);
        !           312:        } else
        !           313:                cons_ops_index = ops;
        !           314: }
        !           315: 
        !           316: 
        !           317: int
        !           318: vcgetc(int l, int u, boolean_t wait, boolean_t raw)
        !           319: {
        !           320:        char c;
        !           321: 
        !           322:        if( 0 == (*PE_poll_input)( 0, &c))
        !           323:                return( c);
        !           324:        else
        !           325:                return( 0);
        !           326: }

unix.superglobalmegacorp.com

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