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  * 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_FREE_COPYRIGHT@
   24  * 
   25  */
   26 
   27 /* Intercept mach console output and supply it to a user application */
   28 
   29 #include <mach_kdb.h>
   30 
   31 #include <types.h>
   32 #include <device/buf.h>
   33 #include <device/conf.h>
   34 #include <device/errno.h>
   35 #include <device/misc_protos.h>
   36 #include <device/ds_routines.h>
   37 #include <device/cirbuf.h>
   38 #include <ppc/console_feed_entries.h>
   39 #include <ppc/serial_io.h>
   40 
   41 #if     MACH_KDB
   42 #include <ppc/db_machdep.h>
   43 #endif  /* MACH_KDB */
   44 
   45 static struct cirbuf cons_feed_cb;
   46 static int cons_feed_count = 0;
   47 io_req_t   cons_feed_queued = 0;
   48 
   49 /* console feed lock should be taken at splhigh */
   50 decl_simple_lock_data(,cons_feed_lock)
   51 
   52 boolean_t cons_feed_read_done(io_req_t ior);
   53 
   54 io_return_t
   55 console_feed_open(
   56         dev_t           dev,
   57         dev_mode_t      flag,
   58         io_req_t        ior)
   59 {
   60         spl_t   s;
   61 
   62         simple_lock_init(&cons_feed_lock, 0);
   63 #if     MACH_KDB
   64         if (console_is_serial()) {
   65                 return D_DEVICE_DOWN;
   66         }
   67 #endif  /* MACH_KDB */
   68         cb_alloc(&cons_feed_cb, CONSOLE_FEED_BUFSIZE);
   69         s = splhigh();
   70         simple_lock(&cons_feed_lock);
   71         cons_feed_count++;
   72         simple_unlock(&cons_feed_lock);
   73         splx(s);
   74         return D_SUCCESS;
   75 }
   76 
   77 void
   78 console_feed_close(
   79         dev_t           dev)
   80 {
   81         spl_t   s;
   82 
   83         s = splhigh();
   84         simple_lock(&cons_feed_lock);
   85         cons_feed_count--;
   86         simple_unlock(&cons_feed_lock);
   87         splx(s);
   88 
   89         console_feed_cancel_and_flush();
   90         cb_free(&cons_feed_cb);
   91 
   92         return;
   93 }
   94 
   95 /* A routine that can be called from a panic or other problem
   96  * situation. It switches off the console feed and dumps any
   97  * remaining buffered information to the original console
   98  * (usually the screen). It doesn't free up the buffer, since
   99  * it tries to be as minimal as possible 
  100  */
  101 
  102 void console_feed_cancel_and_flush(void)
  103 {
  104         int     c;
  105         spl_t   s;
  106         
  107 #if     NCONSFEED > 0
  108 #if     MACH_KDB
  109         if (console_is_serial()) {
  110                 return;
  111         }
  112 #endif  /* MACH_KDB */
  113 
  114         s = splhigh();
  115         simple_lock(&cons_feed_lock);
  116         if (cons_feed_count == 0) {
  117                 simple_unlock(&cons_feed_lock);
  118                 splx(s);
  119                 return;
  120         }
  121         cons_feed_count = 0;
  122         simple_unlock(&cons_feed_lock);
  123         splx(s);
  124 
  125         do {
  126                 c = getc(&cons_feed_cb);
  127                 if (c == -1)
  128                         break;
  129                 cnputc(c);
  130         } while (1);
  131 #endif /* NCONSFEED > 0 */
  132 }
  133 
  134 io_return_t
  135 console_feed_read(
  136         dev_t           dev,
  137         io_req_t        ior)
  138 {
  139         spl_t           s;
  140         kern_return_t   rc;
  141         int             count;
  142 
  143         rc = device_read_alloc(ior, (vm_size_t) ior->io_count);
  144         if (rc != KERN_SUCCESS)
  145                 return rc;
  146 
  147         s = splhigh();
  148         simple_lock(&cons_feed_lock);
  149 
  150         ior->io_residual = ior->io_count;
  151 
  152         count = q_to_b(&cons_feed_cb, (char *) ior->io_data, ior->io_count);
  153         if (count == 0) {
  154                 if (ior->io_mode & D_NOWAIT) {
  155                         rc = D_WOULD_BLOCK;
  156                 }
  157                 if (cons_feed_queued == NULL) {
  158                         ior->io_done = cons_feed_read_done;
  159                         cons_feed_queued = ior;
  160                         rc = D_IO_QUEUED;
  161                 } else {
  162                         /* Can't queue multiple read requests yet */
  163                         rc = D_INVALID_OPERATION;
  164                 }
  165                 simple_unlock(&cons_feed_lock);
  166                 splx(s);
  167                 return rc;
  168         }
  169 
  170         simple_unlock(&cons_feed_lock);
  171         splx(s);
  172 
  173         ior->io_residual -= count;
  174 
  175         iodone(ior);
  176 
  177         if (ior->io_op & IO_SYNC) {
  178                 iowait(ior);
  179         }
  180 
  181         return D_SUCCESS;
  182 }
  183 
  184 /* Called when data is ready and there's a queued-up read waiting */
  185 boolean_t cons_feed_read_done(io_req_t ior)
  186 {
  187         spl_t   s;
  188         int     count;
  189 
  190         s = splhigh();
  191         simple_lock(&cons_feed_lock);
  192 
  193         count = q_to_b(&cons_feed_cb, (char *) ior->io_data, ior->io_count);
  194         if (count == 0) {
  195                 if (cons_feed_queued == NULL) {
  196                         ior->io_done = cons_feed_read_done;
  197                         cons_feed_queued = ior;
  198                 }
  199                 simple_unlock(&cons_feed_lock);
  200                 splx(s);
  201                 return FALSE;
  202         }
  203 
  204         simple_unlock(&cons_feed_lock);
  205         splx(s);
  206 
  207         ior->io_residual -= count;
  208         ds_read_done(ior);
  209 
  210         return TRUE;
  211 }
  212 
  213 /* This routine is called from putc() - it should return TRUE if
  214  * the character should be passed on to a physical console, FALSE
  215  * if the feed has intercepted the character. It may be called from
  216  * under interrupt (even splhigh)
  217  */
  218 
  219 boolean_t console_feed_putc(char c)
  220 {
  221         spl_t           s;
  222         io_req_t        ior;
  223         boolean_t       retval;
  224 
  225 #if     MACH_KDB
  226         if (db_active) {
  227                 return TRUE;
  228         }
  229 #endif  /* MACH_KDB */
  230 
  231         retval=TRUE;    /* TRUE : character should be displayed now */
  232         if (!cons_feed_count) {
  233                 return TRUE;
  234         }
  235         s = splhigh();
  236         simple_lock(&cons_feed_lock);
  237         if (!cons_feed_count) {
  238                 simple_unlock(&cons_feed_lock);
  239                 splx(s);
  240                 return TRUE;
  241         }
  242         /* queue up the data if we can */
  243         if (!putc(c, &cons_feed_cb)) {
  244                 /* able to stock the character */
  245                 retval = FALSE;
  246         }
  247         if (cons_feed_queued != NULL) {
  248                 /* Queued up request - service it */
  249                 ior = cons_feed_queued;
  250                 cons_feed_queued = NULL;
  251                 simple_unlock(&cons_feed_lock);
  252                 splx(s);
  253                 iodone(ior);
  254                 retval=FALSE;
  255         } else {
  256                 simple_unlock(&cons_feed_lock);
  257                 splx(s);
  258         }
  259         return retval;
  260 }

Cache object: 3e719c4efb3602976a8c5905c11044ea


[ 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.