The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/osfmk/ppc/console_feed.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*
   26  * @OSF_FREE_COPYRIGHT@
   27  * 
   28  */
   29 
   30 /* Intercept mach console output and supply it to a user application */
   31 
   32 #include <mach_kdb.h>
   33 
   34 #include <types.h>
   35 #include <device/buf.h>
   36 #include <device/conf.h>
   37 #include <device/errno.h>
   38 #include <device/misc_protos.h>
   39 #include <device/ds_routines.h>
   40 #include <device/cirbuf.h>
   41 #include <ppc/console_feed_entries.h>
   42 #include <ppc/serial_io.h>
   43 
   44 #if     MACH_KDB
   45 #include <ppc/db_machdep.h>
   46 #endif  /* MACH_KDB */
   47 
   48 static struct cirbuf cons_feed_cb;
   49 static int cons_feed_count = 0;
   50 io_req_t   cons_feed_queued = 0;
   51 
   52 /* console feed lock should be taken at splhigh */
   53 decl_simple_lock_data(,cons_feed_lock)
   54 
   55 boolean_t cons_feed_read_done(io_req_t ior);
   56 
   57 io_return_t
   58 console_feed_open(
   59         dev_t           dev,
   60         dev_mode_t      flag,
   61         io_req_t        ior)
   62 {
   63         spl_t   s;
   64 
   65         simple_lock_init(&cons_feed_lock, ETAP_IO_TTY);
   66 #if     MACH_KDB
   67         if (console_is_serial()) {
   68                 return D_DEVICE_DOWN;
   69         }
   70 #endif  /* MACH_KDB */
   71         cb_alloc(&cons_feed_cb, CONSOLE_FEED_BUFSIZE);
   72         s = splhigh();
   73         simple_lock(&cons_feed_lock);
   74         cons_feed_count++;
   75         simple_unlock(&cons_feed_lock);
   76         splx(s);
   77         return D_SUCCESS;
   78 }
   79 
   80 void
   81 console_feed_close(
   82         dev_t           dev)
   83 {
   84         spl_t   s;
   85 
   86         s = splhigh();
   87         simple_lock(&cons_feed_lock);
   88         cons_feed_count--;
   89         simple_unlock(&cons_feed_lock);
   90         splx(s);
   91 
   92         console_feed_cancel_and_flush();
   93         cb_free(&cons_feed_cb);
   94 
   95         return;
   96 }
   97 
   98 /* A routine that can be called from a panic or other problem
   99  * situation. It switches off the console feed and dumps any
  100  * remaining buffered information to the original console
  101  * (usually the screen). It doesn't free up the buffer, since
  102  * it tries to be as minimal as possible 
  103  */
  104 
  105 void console_feed_cancel_and_flush(void)
  106 {
  107         int     c;
  108         spl_t   s;
  109         
  110 #if     NCONSFEED > 0
  111 #if     MACH_KDB
  112         if (console_is_serial()) {
  113                 return;
  114         }
  115 #endif  /* MACH_KDB */
  116 
  117         s = splhigh();
  118         simple_lock(&cons_feed_lock);
  119         if (cons_feed_count == 0) {
  120                 simple_unlock(&cons_feed_lock);
  121                 splx(s);
  122                 return;
  123         }
  124         cons_feed_count = 0;
  125         simple_unlock(&cons_feed_lock);
  126         splx(s);
  127 
  128         do {
  129                 c = getc(&cons_feed_cb);
  130                 if (c == -1)
  131                         break;
  132                 cnputc(c);
  133         } while (1);
  134 #endif /* NCONSFEED > 0 */
  135 }
  136 
  137 io_return_t
  138 console_feed_read(
  139         dev_t           dev,
  140         io_req_t        ior)
  141 {
  142         spl_t           s;
  143         kern_return_t   rc;
  144         int             count;
  145 
  146         rc = device_read_alloc(ior, (vm_size_t) ior->io_count);
  147         if (rc != KERN_SUCCESS)
  148                 return rc;
  149 
  150         s = splhigh();
  151         simple_lock(&cons_feed_lock);
  152 
  153         ior->io_residual = ior->io_count;
  154 
  155         count = q_to_b(&cons_feed_cb, (char *) ior->io_data, ior->io_count);
  156         if (count == 0) {
  157                 if (ior->io_mode & D_NOWAIT) {
  158                         rc = D_WOULD_BLOCK;
  159                 }
  160                 if (cons_feed_queued == NULL) {
  161                         ior->io_done = cons_feed_read_done;
  162                         cons_feed_queued = ior;
  163                         rc = D_IO_QUEUED;
  164                 } else {
  165                         /* Can't queue multiple read requests yet */
  166                         rc = D_INVALID_OPERATION;
  167                 }
  168                 simple_unlock(&cons_feed_lock);
  169                 splx(s);
  170                 return rc;
  171         }
  172 
  173         simple_unlock(&cons_feed_lock);
  174         splx(s);
  175 
  176         ior->io_residual -= count;
  177 
  178         iodone(ior);
  179 
  180         if (ior->io_op & IO_SYNC) {
  181                 iowait(ior);
  182         }
  183 
  184         return D_SUCCESS;
  185 }
  186 
  187 /* Called when data is ready and there's a queued-up read waiting */
  188 boolean_t cons_feed_read_done(io_req_t ior)
  189 {
  190         spl_t   s;
  191         int     count;
  192 
  193         s = splhigh();
  194         simple_lock(&cons_feed_lock);
  195 
  196         count = q_to_b(&cons_feed_cb, (char *) ior->io_data, ior->io_count);
  197         if (count == 0) {
  198                 if (cons_feed_queued == NULL) {
  199                         ior->io_done = cons_feed_read_done;
  200                         cons_feed_queued = ior;
  201                 }
  202                 simple_unlock(&cons_feed_lock);
  203                 splx(s);
  204                 return FALSE;
  205         }
  206 
  207         simple_unlock(&cons_feed_lock);
  208         splx(s);
  209 
  210         ior->io_residual -= count;
  211         ds_read_done(ior);
  212 
  213         return TRUE;
  214 }
  215 
  216 /* This routine is called from putc() - it should return TRUE if
  217  * the character should be passed on to a physical console, FALSE
  218  * if the feed has intercepted the character. It may be called from
  219  * under interrupt (even splhigh)
  220  */
  221 
  222 boolean_t console_feed_putc(char c)
  223 {
  224         spl_t           s;
  225         io_req_t        ior;
  226         boolean_t       retval;
  227 
  228 #if     MACH_KDB
  229         if (db_active) {
  230                 return TRUE;
  231         }
  232 #endif  /* MACH_KDB */
  233 
  234         retval=TRUE;    /* TRUE : character should be displayed now */
  235         if (!cons_feed_count) {
  236                 return TRUE;
  237         }
  238         s = splhigh();
  239         simple_lock(&cons_feed_lock);
  240         if (!cons_feed_count) {
  241                 simple_unlock(&cons_feed_lock);
  242                 splx(s);
  243                 return TRUE;
  244         }
  245         /* queue up the data if we can */
  246         if (!putc(c, &cons_feed_cb)) {
  247                 /* able to stock the character */
  248                 retval = FALSE;
  249         }
  250         if (cons_feed_queued != NULL) {
  251                 /* Queued up request - service it */
  252                 ior = cons_feed_queued;
  253                 cons_feed_queued = NULL;
  254                 simple_unlock(&cons_feed_lock);
  255                 splx(s);
  256                 iodone(ior);
  257                 retval=FALSE;
  258         } else {
  259                 simple_unlock(&cons_feed_lock);
  260                 splx(s);
  261         }
  262         return retval;
  263 }

Cache object: ce68eb5aa5c68da9a1133eaf6917fafc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.