Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/arch/alpha/kernel/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 5 kB image not shown  

Quelle  srmcons.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * linux/arch/alpha/kernel/srmcons.c
 *
 * Callback based driver for SRM Console console device.
 * (TTY driver and console driver)
 */


#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>

#include <asm/console.h>
#include <linux/uaccess.h>

#include "proto.h"


static DEFINE_SPINLOCK(srmcons_callback_lock);
static int srm_is_registered_console = 0;

/* 
 * The TTY driver
 */

#define MAX_SRM_CONSOLE_DEVICES 1 /* only support 1 console device */

struct srmcons_private {
 struct tty_port port;
 struct timer_list timer;
} srmcons_singleton;

typedef union _srmcons_result {
 struct {
  unsigned long c :61;
  unsigned long status :3;
 } bits;
 long as_long;
} srmcons_result;

/* called with callback_lock held */
static int
srmcons_do_receive_chars(struct tty_port *port)
{
 srmcons_result result;
 int count = 0, loops = 0;

 do {
  result.as_long = callback_getc(0);
  if (result.bits.status < 2) {
   tty_insert_flip_char(port, (u8)result.bits.c, 0);
   count++;
  }
 } while((result.bits.status & 1) && (++loops < 10));

 if (count)
  tty_flip_buffer_push(port);

 return count;
}

static void
srmcons_receive_chars(struct timer_list *t)
{
 struct srmcons_private *srmconsp = timer_container_of(srmconsp, t,
             timer);
 struct tty_port *port = &srmconsp->port;
 unsigned long flags;
 int incr = 10;

 local_irq_save(flags);
 if (spin_trylock(&srmcons_callback_lock)) {
  if (!srmcons_do_receive_chars(port))
   incr = 100;
  spin_unlock(&srmcons_callback_lock);
 } 

 spin_lock(&port->lock);
 if (port->tty)
  mod_timer(&srmconsp->timer, jiffies + incr);
 spin_unlock(&port->lock);

 local_irq_restore(flags);
}

/* called with callback_lock held */
static void
srmcons_do_write(struct tty_port *port, const u8 *buf, size_t count)
{
 size_t c;
 srmcons_result result;

 while (count > 0) {
  bool need_cr = false;
  /* 
 * Break it up into reasonable size chunks to allow a chance
 * for input to get in
 */

  for (c = 0; c < min_t(size_t, 128U, count) && !need_cr; c++)
   if (buf[c] == '\n')
    need_cr = true;
  
  while (c > 0) {
   result.as_long = callback_puts(0, buf, c);
   c -= result.bits.c;
   count -= result.bits.c;
   buf += result.bits.c;

   /*
 * Check for pending input iff a tty port was provided
 */

   if (port)
    srmcons_do_receive_chars(port);
  }

  while (need_cr) {
   result.as_long = callback_puts(0, "\r", 1);
   if (result.bits.c > 0)
    need_cr = false;
  }
 }
}

static ssize_t
srmcons_write(struct tty_struct *tty, const u8 *buf, size_t count)
{
 unsigned long flags;

 spin_lock_irqsave(&srmcons_callback_lock, flags);
 srmcons_do_write(tty->port, buf, count);
 spin_unlock_irqrestore(&srmcons_callback_lock, flags);

 return count;
}

static unsigned int
srmcons_write_room(struct tty_struct *tty)
{
 return 512;
}

static int
srmcons_open(struct tty_struct *tty, struct file *filp)
{
 struct srmcons_private *srmconsp = &srmcons_singleton;
 struct tty_port *port = &srmconsp->port;
 unsigned long flags;

 spin_lock_irqsave(&port->lock, flags);

 if (!port->tty) {
  tty->driver_data = srmconsp;
  tty->port = port;
  port->tty = tty; /* XXX proper refcounting */
  mod_timer(&srmconsp->timer, jiffies + 10);
 }

 spin_unlock_irqrestore(&port->lock, flags);

 return 0;
}

static void
srmcons_close(struct tty_struct *tty, struct file *filp)
{
 struct srmcons_private *srmconsp = tty->driver_data;
 struct tty_port *port = &srmconsp->port;
 unsigned long flags;

 spin_lock_irqsave(&port->lock, flags);

 if (tty->count == 1) {
  port->tty = NULL;
  timer_delete(&srmconsp->timer);
 }

 spin_unlock_irqrestore(&port->lock, flags);
}


static struct tty_driver *srmcons_driver;

static const struct tty_operations srmcons_ops = {
 .open  = srmcons_open,
 .close  = srmcons_close,
 .write  = srmcons_write,
 .write_room = srmcons_write_room,
};

static int __init
srmcons_init(void)
{
 struct tty_driver *driver;
 int err;

 timer_setup(&srmcons_singleton.timer, srmcons_receive_chars, 0);

 if (!srm_is_registered_console)
  return -ENODEV;

 driver = tty_alloc_driver(MAX_SRM_CONSOLE_DEVICES, 0);
 if (IS_ERR(driver))
  return PTR_ERR(driver);

 tty_port_init(&srmcons_singleton.port);

 driver->driver_name = "srm";
 driver->name = "srm";
 driver->major = 0; /* dynamic */
 driver->minor_start = 0;
 driver->type = TTY_DRIVER_TYPE_SYSTEM;
 driver->subtype = SYSTEM_TYPE_SYSCONS;
 driver->init_termios = tty_std_termios;
 tty_set_operations(driver, &srmcons_ops);
 tty_port_link_device(&srmcons_singleton.port, driver, 0);
 err = tty_register_driver(driver);
 if (err)
  goto err_free_drv;

 srmcons_driver = driver;

 return 0;
err_free_drv:
 tty_driver_kref_put(driver);
 tty_port_destroy(&srmcons_singleton.port);

 return err;
}
device_initcall(srmcons_init);

/*
 * The console driver
 */

static void
srm_console_write(struct console *co, const char *s, unsigned count)
{
 unsigned long flags;

 spin_lock_irqsave(&srmcons_callback_lock, flags);
 srmcons_do_write(NULL, s, count);
 spin_unlock_irqrestore(&srmcons_callback_lock, flags);
}

static struct tty_driver *
srm_console_device(struct console *co, int *index)
{
 *index = co->index;
 return srmcons_driver;
}

static int
srm_console_setup(struct console *co, char *options)
{
 return 0;
}

static struct console srmcons = {
 .name  = "srm",
 .write  = srm_console_write,
 .device  = srm_console_device,
 .setup  = srm_console_setup,
 .flags  = CON_PRINTBUFFER | CON_BOOT,
 .index  = -1,
};

void __init
register_srm_console(void)
{
 if (!srm_is_registered_console) {
  callback_open_console();
  register_console(&srmcons);
  srm_is_registered_console = 1;
 }
}

void __init
unregister_srm_console(void)
{
 if (srm_is_registered_console) {
  callback_close_console();
  unregister_console(&srmcons);
  srm_is_registered_console = 0;
 }
}

Messung V0.5
C=97 H=88 G=92

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.