Annotation of XNU/osfmk/ppc/serial_console.c, revision 1.1.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.