]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/console/ppc/serial_console.c
xnu-792.18.15.tar.gz
[apple/xnu.git] / osfmk / console / ppc / serial_console.c
index bcfbb62c6165c3967e14ee97fb0b58b0c2e38846..6ea518c61cd7cf08848ea18be53b064a646d8a3c 100644 (file)
@@ -1,23 +1,29 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 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@
  */
 /*
  * @OSF_COPYRIGHT@
 #include <machine/machparam.h>         /* spl definitions */
 #include <types.h>
 #include <console/video_console.h>
+#include <console/serial_protos.h>
+#include <kern/kalloc.h>
+#include <kern/thread.h>
 #include <ppc/misc_protos.h>
 #include <ppc/serial_io.h>
 #include <kern/cpu_number.h>
 #include <ppc/Firmware.h>
 #include <ppc/proc_reg.h>
+#include <ppc/cpu_internal.h>
+#include <ppc/exception.h>
 #include <pexpert/pexpert.h>
 
 /*
  */
 
 const int console_unit = 0;
-const int console_chan_default = CONSOLE_PORT;
+const uint32_t console_chan_default = CONSOLE_PORT;
 #define console_chan (console_chan_default) /* ^ cpu_number()) */
 
-#define OPS(putc, getc, nosplputc, nosplgetc) putc, getc
-
-const struct console_ops {
-       int     (*putc)(int, int, int);
-       int     (*getc)(int, int, boolean_t, boolean_t);
-} cons_ops[] = {
-#define SCC_CONS_OPS 0
-       {OPS(scc_putc, scc_getc, no_spl_scputc, no_spl_scgetc)},
-#define VC_CONS_OPS 1
-       {OPS(vcputc, vcgetc, no_spl_vcputc, no_spl_vcgetc)},
-};
-#define NCONSOPS (sizeof cons_ops / sizeof cons_ops[0])
-
-#if SERIAL_CONSOLE_DEFAULT
-#define CONS_OPS SCC_CONS_OPS
-#define CONS_NAME "com"
-#else
-#define CONS_OPS VC_CONS_OPS
-#define CONS_NAME "vc"
-#endif
 
 #define MP_SAFE_CONSOLE 1      /* Set this to 1 to allow more than 1 processor to print at once */
 #if MP_SAFE_CONSOLE
@@ -85,47 +76,83 @@ struct ppcbfr {                                                                                                     /* Controls multiple processor output */
        unsigned int    echo;                                                                           /* Control character echoing */
        char                    buffer[256];                                                            /* Fairly big buffer */ 
 };
-typedef struct ppcbfr ppcbfr;
-ppcbfr cbfr[NCPUS];                                                                                            /* Get one of these for each processor */
+typedef struct ppcbfr ppcbfr_t;
+
+ppcbfr_t cbfr_boot_cpu;                                                                                        /* Get one for boot cpu */
 volatile unsigned int cbfpend;                                                                 /* A buffer is pending output */
 volatile unsigned int sconowner=-1;                                                            /* Mark who's actually writing */
 
 #endif
 
+#define OPS(putc, getc, nosplputc, nosplgetc) putc, getc
+
+console_ops_t cons_ops[] = {
+       {OPS(scc_putc, scc_getc, no_spl_scputc, no_spl_scgetc)},
+       {OPS(vcputc, vcgetc, no_spl_vcputc, no_spl_vcgetc)},
+};
+
+uint32_t nconsops = (sizeof cons_ops / sizeof cons_ops[0]);
+
+uint32_t cons_ops_index = VC_CONS_OPS;
 
-unsigned int cons_ops_index = CONS_OPS;
 unsigned int killprint = 0;
 unsigned int debcnputc = 0;
 extern unsigned int    mappingdeb0;
-extern int debugger_holdoff[NCPUS];
 extern int debugger_cpu;
 
+void *console_per_proc_alloc(boolean_t boot_processor)
+{
+       ppcbfr_t  *cbfr_cpu;
+
+       if (boot_processor)
+               cbfr_cpu = &cbfr_boot_cpu;
+       else {
+               cbfr_cpu = (ppcbfr_t *)kalloc(sizeof(ppcbfr_t));
+               if (cbfr_cpu == (ppcbfr_t *)NULL)
+                       return (void *)NULL;
+       }
+       bzero((char *)cbfr_cpu, sizeof(ppcbfr_t));
+       return (void *)cbfr_cpu;
+}
+
+void console_per_proc_free(void *per_proc_cbfr)
+{
+       if (per_proc_cbfr == (void *)&cbfr_boot_cpu)
+               return;
+       else
+               kfree(per_proc_cbfr, sizeof(ppcbfr_t));
+}
+
+
 static void _cnputc(char c)
 {
        cons_ops[cons_ops_index].putc(console_unit, console_chan, c);
 }
 
 void cnputcusr(char c) {                                                                               /* Echo input character directly */
-
-       unsigned int cpu;
-       
-       cpu = cpu_number();
-       
-       hw_atomic_add(&debugger_holdoff[cpu], 1);                                       /* Don't allow debugger entry just now (this is a HACK) */
+       struct per_proc_info    *procinfo;
+       spl_t                                   s;
        
+       s=splhigh();
+       procinfo = getPerProc();
+
+       hw_atomic_add(&(procinfo->debugger_holdoff), 1);                        /* Don't allow debugger entry just now (this is a HACK) */
+
        _cnputc( c);                                                                                            /* Echo the character */
        if(c=='\n') _cnputc( '\r');                                                                     /* Add a return if we had a new line */
-       
-       hw_atomic_sub(&debugger_holdoff[cpu], 1);                                       /* Don't allow debugger entry just now (this is a HACK) */
+
+       hw_atomic_sub(&(procinfo->debugger_holdoff), 1);                        /* Don't allow debugger entry just now (this is a HACK) */
+       splx(s);
        return;
 }
 
 void
 cnputc(char c)
 {
-
-       unsigned int oldpend, i, cpu, ourbit, sccpu;
-       spl_t           s;
+       unsigned int                            oldpend, i, cpu, ourbit, sccpu;
+       struct per_proc_info            *procinfo;
+       ppcbfr_t                                        *cbfr, *cbfr_cpu;
+       spl_t                                           s;
                
 #if MP_SAFE_CONSOLE
 
@@ -139,9 +166,12 @@ cnputc(char c)
                return;                                                                                                 /* If printing is disabled, bail... */
        }       
        
-       cpu = cpu_number();
+       s=splhigh();                                                                                            /* Don't bother me */
+       procinfo = getPerProc();
+       cpu = procinfo->cpu_number;
+       cbfr = procinfo->pp_cbfr;
 
-       hw_atomic_add(&debugger_holdoff[cpu], 1);                                       /* Don't allow debugger entry just now (this is a HACK) */
+       hw_atomic_add(&(procinfo->debugger_holdoff), 1);                        /* Don't allow debugger entry just now (this is a HACK) */
 
        ourbit = 1 << cpu;                                                                                      /* Make a mask for just us */
        if(debugger_cpu != -1) {                                                                        /* Are we in the debugger with empty buffers? */
@@ -155,46 +185,46 @@ cnputc(char c)
                        _cnputc( '\r');                                                                         /* Yeah, just add a return */
                        
                sconowner=-1;                                                                                   /* Mark it idle */      
-               hw_atomic_sub(&debugger_holdoff[cpu], 1);                               /* Don't allow debugger entry just now (this is a HACK) */
+               hw_atomic_sub(&(procinfo->debugger_holdoff), 1);                        /* Don't allow debugger entry just now (this is a HACK) */
                
+               splx(s);
                return;                                                                                                 /* Leave... */
        }
 
-       s=splhigh();                                                                                            /* Don't bother me */
        
        while(ourbit&cbfpend);                                                                          /* We aren't "double buffered," so we'll just wait until the buffers are written */
        isync();                                                                                                        /* Just in case we had to wait */
        
        if(c) {                                                                                                         /* If the character is not null */
-               cbfr[cpu].buffer[cbfr[cpu].pos]=c;                                              /* Fill in the buffer for our CPU */
-               cbfr[cpu].pos++;                                                                                /* Up the count */
-               if(cbfr[cpu].pos > 253) {                                                               /* Is the buffer full? */
-                       cbfr[cpu].buffer[254]='\n';                                                     /* Yeah, set the second to last as a LF */
-                       cbfr[cpu].buffer[255]='\r';                                                     /* And the last to a CR */
-                       cbfr[cpu].pos=256;                                                                      /* Push the buffer to the end */
+               cbfr->buffer[cbfr->pos]=c;                                                      /* Fill in the buffer for our CPU */
+               cbfr->pos++;                                                                            /* Up the count */
+               if(cbfr->pos > 253) {                                                           /* Is the buffer full? */
+                       cbfr->buffer[254]='\n';                                                 /* Yeah, set the second to last as a LF */
+                       cbfr->buffer[255]='\r';                                                 /* And the last to a CR */
+                       cbfr->pos=256;                                                                  /* Push the buffer to the end */
                        c='\r';                                                                                         /* Set character to a CR */
                }
        }
        
        if(c == '\n') {                                                                                         /* Are we finishing a line? */
-               cbfr[cpu].buffer[cbfr[cpu].pos]='\r';                                   /* And the last to a CR */
-               cbfr[cpu].pos++;                                                                                /* Up the count */
+               cbfr->buffer[cbfr->pos]='\r';                                                   /* And the last to a CR */
+               cbfr->pos++;                                                                                    /* Up the count */
                c='\r';                                                                                                 /* Set character to a CR */
        }
 
 #if 1
-       if(cbfr[cpu].echo == 1) {                                                                       /* Did we hit an escape last time? */
+       if(cbfr->echo == 1) {                                                                           /* Did we hit an escape last time? */
                if(c == 'K') {                                                                                  /* Is it a partial clear? */
-                       cbfr[cpu].echo = 2;                                                                     /* Yes, enter echo mode */
+                       cbfr->echo = 2;                                                                         /* Yes, enter echo mode */
                }
-               else cbfr[cpu].echo = 0;                                                                /* Otherwise reset escape */
+               else cbfr->echo = 0;                                                                    /* Otherwise reset escape */
        }
-       else if(cbfr[cpu].echo == 0) {                                                          /* Not in escape sequence, see if we should enter */
-               cbfr[cpu].echo = 1;                                                                             /* Set that we are in escape sequence */
+       else if(cbfr->echo == 0) {                                                                      /* Not in escape sequence, see if we should enter */
+               cbfr->echo = 1;                                                                                 /* Set that we are in escape sequence */
        }
 #endif
 
-       if((c == 0x00) || (c == '\r') || (cbfr[cpu].echo == 2)) {       /* Try to push out all buffers if we see CR or null */
+       if((c == 0x00) || (c == '\r') || (cbfr->echo == 2)) {           /* Try to push out all buffers if we see CR or null */
                                
                while(1) {                                                                                              /* Loop until we see who's doing this */
                        oldpend=cbfpend;                                                                        /* Get the currentest pending buffer flags */
@@ -203,19 +233,24 @@ cnputc(char c)
                }
                
                if(!hw_compare_and_store(-1, cpu, (unsigned int *)&sconowner)) {        /* See if someone else has this, and take it if not */
-                       debugger_holdoff[cpu] = 0;                                                      /* Allow debugger entry (this is a HACK) */
+                       procinfo->debugger_holdoff = 0;                                         /* Allow debugger entry (this is a HACK) */
                        splx(s);                                                                                        /* Let's take some 'rupts now */
                        return;                                                                                         /* We leave here, 'cause another processor is already writing the buffers */
                }
                                
                while(1) {                                                                                              /* Loop to dump out all of the finished buffers */
                        oldpend=cbfpend;                                                                        /* Get the most current finished buffers */
-                       for(sccpu=0; sccpu<NCPUS; sccpu++) {                            /* Cycle through all CPUs buffers */
+                       for(sccpu=0; sccpu<real_ncpus; sccpu++) {                               /* Cycle through all CPUs buffers */
+                               if ((PerProcTable[sccpu].ppe_vaddr == 0)
+                                   || (PerProcTable[sccpu].ppe_vaddr->pp_cbfr == 0))
+                                       continue;
+
+                               cbfr_cpu = PerProcTable[sccpu].ppe_vaddr->pp_cbfr;
                                
                                if(oldpend&(1<<sccpu)) {                                                /* Does this guy have a buffer to do? */
 
 #if 0
-                                       if(!cbfr[sccpu].noprompt) {                                     /* Don't prompt if there was not CR before */
+                                       if(!cbfr_cpu->noprompt) {                                       /* Don't prompt if there was not CR before */
                                                _cnputc( '{');  /* Mark CPU number */
                                                _cnputc( '0'+sccpu);    /* Mark CPU number */
                                                _cnputc( '.');  /* (TEST/DEBUG) */
@@ -225,19 +260,19 @@ cnputc(char c)
                                        }
 #endif
                                        
-                                       for(i=0; i<cbfr[sccpu].pos; i++) {                      /* Do the whole buffer */
-                                               _cnputc( cbfr[sccpu].buffer[i]); /* Write it */
+                                       for(i=0; i<cbfr_cpu->pos; i++) {                                /* Do the whole buffer */
+                                               _cnputc(cbfr_cpu->buffer[i]);                           /* Write it */
                                        }
                                        
-                                       if(cbfr[sccpu].buffer[cbfr[sccpu].pos-1]!='\r') {       /* Was the last character a return? */
-                                               cbfr[sccpu].noprompt = 1;                               /* Remember not to prompt */
+                                       if(cbfr_cpu->buffer[cbfr_cpu->pos-1]!='\r') {   /* Was the last character a return? */
+                                               cbfr_cpu->noprompt = 1;                                         /* Remember not to prompt */
                                        }
-                                       else {                                                                          /* Last was a return */
-                                               cbfr[sccpu].noprompt = 0;                               /* Otherwise remember to prompt */
-                                               cbfr[sccpu].echo = 0;                                   /* And clear echo */
+                                       else {                                                                                  /* Last was a return */
+                                               cbfr_cpu->noprompt = 0;                                         /* Otherwise remember to prompt */
+                                               cbfr_cpu->echo = 0;                                                     /* And clear echo */
                                        }
                                                
-                                       cbfr[sccpu].pos=0;                                                      /* Reset the buffer pointer */
+                                       cbfr_cpu->pos=0;                                                                /* Reset the buffer pointer */
                
                                        while(!hw_compare_and_store(cbfpend, cbfpend&~(1<<sccpu), (unsigned int *)&cbfpend));   /* Swap it off */
                                }
@@ -249,7 +284,7 @@ cnputc(char c)
        
                }
        }
-       hw_atomic_sub(&debugger_holdoff[cpu], 1);                                       /* Don't allow debugger entry just now (this is a HACK) */
+       hw_atomic_sub(&(procinfo->debugger_holdoff), 1);                                        /* Don't allow debugger entry just now (this is a HACK) */
        splx(s);                                                                                                        /* Let's take some 'rupts now */
 
 #else  /* MP_SAFE_CONSOLE */
@@ -274,46 +309,12 @@ cnmaygetc()
                                             FALSE, FALSE);
 }
 
-boolean_t console_is_serial()
-{
-       return cons_ops_index == SCC_CONS_OPS;
-}
-
-int
-switch_to_video_console()
-{
-       int old_cons_ops = cons_ops_index;
-       cons_ops_index = VC_CONS_OPS;
-       return old_cons_ops;
-}
-
-int
-switch_to_serial_console()
-{
-       int old_cons_ops = cons_ops_index;
-       cons_ops_index = SCC_CONS_OPS;
-       return old_cons_ops;
-}
-
-/* The switch_to_{video,serial,kgdb}_console functions return a cookie that
-   can be used to restore the console to whatever it was before, in the
-   same way that splwhatever() and splx() work.  */
-void
-switch_to_old_console(int old_console)
-{
-       static boolean_t squawked;
-       unsigned int ops = old_console;
-
-       if (ops >= NCONSOPS && !squawked) {
-               squawked = TRUE;
-               printf("switch_to_old_console: unknown ops %d\n", ops);
-       } else
-               cons_ops_index = ops;
-}
-
 
 int
-vcgetc(int l, int u, boolean_t wait, boolean_t raw)
+vcgetc(__unused int l, 
+       __unused int u, 
+       __unused boolean_t wait, 
+       __unused boolean_t raw)
 {
        char c;