Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/sparc64/src/drivers/niagara.c

    rb366a6f4 rd7533c7  
    3232/**
    3333 * @file
    34  * @brief Niagara input/output driver based on hypervisor calls.
     34 * @brief       Niagara input/output driver based on hypervisor calls.
    3535 */
    3636
     
    5252#include <genarch/srln/srln.h>
    5353
    54 /* Polling interval in miliseconds */
     54/* polling interval in miliseconds */
    5555#define POLL_INTERVAL  10000
    5656
    57 /* Device instance */
     57/* device instance */
    5858static niagara_instance_t *instance = NULL;
    5959
    60 static void niagara_putchar(outdev_t *, const wchar_t);
    61 
    62 /** Character device operations */
     60static void niagara_putchar(outdev_t *, const wchar_t, bool);
     61
     62/** character device operations */
    6363static outdev_operations_t niagara_ops = {
    6464        .write = niagara_putchar,
     
    6666};
    6767
    68 /**
     68/*
    6969 * The driver uses hypercalls to print characters to the console. Since the
    7070 * hypercall cannot be performed from the userspace, we do this:
    71  *
    72  * The kernel "little brother" driver (which will be present no matter what
    73  * the DDI architecture is -- as we need the kernel part for the kconsole)
     71 * The kernel "little brother" driver (which will be present no matter what the
     72 * DDI architecture is - as we need the kernel part for the kconsole)
    7473 * defines a shared buffer. Kernel walks through the buffer (in the same thread
    7574 * which is used for polling the keyboard) and prints any pending characters
    76  * to the console (using hypercalls).
    77  *
    78  * The userspace fb server maps this shared buffer to its address space and
    79  * output operation it does is performed using the mapped buffer. The shared
    80  * buffer definition follows.
    81  */
    82 #define OUTPUT_BUFFER_SIZE  ((PAGE_SIZE) - 2 * 8)
    83 
     75 * to the console (using hypercalls). The userspace fb server maps this shared
     76 * buffer to its address space and output operation it does is performed using
     77 * the mapped buffer. The shared buffer definition follows.
     78 */
     79#define OUTPUT_BUFFER_SIZE      ((PAGE_SIZE) - 2 * 8)
    8480static volatile struct {
    8581        uint64_t read_ptr;
    8682        uint64_t write_ptr;
    8783        char data[OUTPUT_BUFFER_SIZE];
    88 } __attribute__ ((packed)) __attribute__ ((aligned(PAGE_SIZE))) output_buffer;
    89 
    90 static parea_t outbuf_parea;
     84}
     85        __attribute__ ((packed))
     86        __attribute__ ((aligned(PAGE_SIZE)))
     87        output_buffer;
    9188
    9289/**
    9390 * Analogous to the output_buffer, see the previous definition.
    9491 */
    95 #define INPUT_BUFFER_SIZE  ((PAGE_SIZE) - 2 * 8)
    96 
     92#define INPUT_BUFFER_SIZE       ((PAGE_SIZE) - 2 * 8)
    9793static volatile struct {
    9894        uint64_t write_ptr;
    9995        uint64_t read_ptr;
    10096        char data[INPUT_BUFFER_SIZE];
    101 } __attribute__ ((packed)) __attribute__ ((aligned(PAGE_SIZE))) input_buffer;
    102 
    103 static parea_t inbuf_parea;
    104 
    105 /** Write a single character to the standard output. */
     97}
     98        __attribute__ ((packed))
     99        __attribute__ ((aligned(PAGE_SIZE)))
     100        input_buffer;
     101
     102
     103/** Writes a single character to the standard output. */
    106104static inline void do_putchar(const char c) {
    107         /* Repeat until the buffer is non-full */
    108         while (__hypercall_fast1(CONS_PUTCHAR, c) == HV_EWOULDBLOCK);
    109 }
    110 
    111 /** Write a single character to the standard output. */
    112 static void niagara_putchar(outdev_t *dev, const wchar_t ch)
    113 {
    114         if ((!outbuf_parea.mapped) || (console_override)) {
    115                 do_putchar(ch);
    116                 if (ch == '\n')
    117                         do_putchar('\r');
    118         }
    119 }
    120 
    121 /** Poll keyboard and print pending characters.
    122  *
    123  * Ask the hypervisor whether there is any unread character. If so,
    124  * pick it up and send it to the indev layer.
    125  *
    126  * Check whether the userspace output driver has pushed any
    127  * characters to the output buffer and eventually print them.
    128  *
    129  */
    130 static void niagara_poll(void)
    131 {
    132         /*
    133          * Print any pending characters from the
    134          * shared buffer to the console.
    135          */
    136        
     105        /* repeat until the buffer is non-full */
     106        while (__hypercall_fast1(CONS_PUTCHAR, c) == HV_EWOULDBLOCK)
     107                ;
     108}
     109
     110/** Writes a single character to the standard output. */
     111static void niagara_putchar(outdev_t *dev, const wchar_t ch, bool silent)
     112{
     113        if (silent)
     114            return;
     115
     116        do_putchar(ch);
     117        if (ch == '\n')
     118                do_putchar('\r');
     119}
     120
     121/**
     122 * Function regularly called by the keyboard polling thread. Asks the
     123 * hypervisor whether there is any unread character. If so, it picks it up
     124 * and sends it to the upper layers of HelenOS.
     125 *
     126 * Apart from that, it also checks whether the userspace output driver has
     127 * pushed any characters to the output buffer. If so, it prints them.
     128 */
     129static void niagara_poll(niagara_instance_t *instance)
     130{
     131        /* print any pending characters from the shared buffer to the console */
    137132        while (output_buffer.read_ptr != output_buffer.write_ptr) {
    138133                do_putchar(output_buffer.data[output_buffer.read_ptr]);
    139134                output_buffer.read_ptr =
    140                     ((output_buffer.read_ptr) + 1) % OUTPUT_BUFFER_SIZE;
    141         }
    142        
    143         /*
    144          * Read character from keyboard.
    145          */
    146        
     135                        ((output_buffer.read_ptr) + 1) % OUTPUT_BUFFER_SIZE;
     136        }
     137
    147138        uint64_t c;
     139
     140        /* read character from keyboard, send it to upper layers of HelenOS */
    148141        if (__hypercall_fast_ret1(0, 0, 0, 0, 0, CONS_GETCHAR, &c) == HV_EOK) {
    149                 if ((!inbuf_parea.mapped) || (console_override)) {
    150                         /*
    151                          * Kernel console is active, send
    152                          * the character to kernel.
    153                          */
     142                if (!silent) {
     143                        /* kconsole active, send the character to kernel */
    154144                        indev_push_character(instance->srlnin, c);
    155145                } else {
    156                         /*
    157                          * Kernel console is inactive, send
    158                          * the character to uspace driver.
    159                          */
     146                        /* kconsole inactive, send the character to uspace driver */
    160147                        input_buffer.data[input_buffer.write_ptr] = (char) c;
    161148                        input_buffer.write_ptr =
    162                             ((input_buffer.write_ptr) + 1) % INPUT_BUFFER_SIZE;
     149                                ((input_buffer.write_ptr) + 1) % INPUT_BUFFER_SIZE;
    163150                }
    164151        }
    165152}
    166153
    167 /** Polling thread function.
    168  *
    169  */
    170 static void kniagarapoll(void *arg) {
     154/**
     155 * Polling thread function.
     156 */
     157static void kniagarapoll(void *instance) {
    171158        while (true) {
    172                 niagara_poll();
     159                niagara_poll(instance);
    173160                thread_usleep(POLL_INTERVAL);
    174161        }
    175162}
    176163
    177 /** Initialize the input/output subsystem
    178  *
     164/**
     165 * Initializes the input/output subsystem so that the Niagara standard
     166 * input/output is used.
    179167 */
    180168static void niagara_init(void)
     
    184172       
    185173        instance = malloc(sizeof(niagara_instance_t), FRAME_ATOMIC);
    186         instance->thread = thread_create(kniagarapoll, NULL, TASK, 0,
    187             "kniagarapoll", true);
    188174       
    189         if (!instance->thread) {
    190                 free(instance);
    191                 instance = NULL;
    192                 return;
    193         }
    194        
     175        if (instance) {
     176                instance->thread = thread_create(kniagarapoll, instance, TASK, 0,
     177                        "kniagarapoll", true);
     178               
     179                if (!instance->thread) {
     180                        free(instance);
     181                        instance = NULL;
     182                        return;
     183                }
     184        }
     185
    195186        instance->srlnin = NULL;
    196        
     187
    197188        output_buffer.read_ptr = 0;
    198189        output_buffer.write_ptr = 0;
    199190        input_buffer.write_ptr = 0;
    200191        input_buffer.read_ptr = 0;
    201        
     192
    202193        /*
    203194         * Set sysinfos and pareas so that the userspace counterpart of the
    204195         * niagara fb and kbd driver can communicate with kernel using shared
    205196         * buffers.
    206          */
    207        
     197         */
     198
    208199        sysinfo_set_item_val("fb.kind", NULL, 5);
    209        
     200
    210201        sysinfo_set_item_val("niagara.outbuf.address", NULL,
    211             KA2PA(&output_buffer));
     202                KA2PA(&output_buffer));
    212203        sysinfo_set_item_val("niagara.outbuf.size", NULL,
    213             PAGE_SIZE);
     204                PAGE_SIZE);
    214205        sysinfo_set_item_val("niagara.outbuf.datasize", NULL,
    215             OUTPUT_BUFFER_SIZE);
    216        
     206                OUTPUT_BUFFER_SIZE);
     207
    217208        sysinfo_set_item_val("niagara.inbuf.address", NULL,
    218             KA2PA(&input_buffer));
     209                KA2PA(&input_buffer));
    219210        sysinfo_set_item_val("niagara.inbuf.size", NULL,
    220             PAGE_SIZE);
     211                PAGE_SIZE);
    221212        sysinfo_set_item_val("niagara.inbuf.datasize", NULL,
    222            INPUT_BUFFER_SIZE);
    223        
     213                INPUT_BUFFER_SIZE);
     214
     215        static parea_t outbuf_parea;
    224216        outbuf_parea.pbase = (uintptr_t) (KA2PA(&output_buffer));
    225217        outbuf_parea.frames = 1;
    226218        outbuf_parea.unpriv = false;
    227         outbuf_parea.mapped = false;
    228219        ddi_parea_register(&outbuf_parea);
    229        
     220
     221        static parea_t inbuf_parea;
    230222        inbuf_parea.pbase = (uintptr_t) (KA2PA(&input_buffer));
    231223        inbuf_parea.frames = 1;
    232224        inbuf_parea.unpriv = false;
    233         inbuf_parea.mapped = false;
    234225        ddi_parea_register(&inbuf_parea);
    235        
     226
    236227        outdev_t *niagara_dev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
    237228        outdev_initialize("niagara_dev", niagara_dev, &niagara_ops);
     
    239230}
    240231
    241 /** Initialize input from the Niagara console.
    242  *
     232/**
     233 * A public function which initializes input from the Niagara console.
    243234 */
    244235niagara_instance_t *niagarain_init(void)
    245236{
    246237        niagara_init();
    247        
     238
    248239        if (instance) {
    249240                srln_instance_t *srln_instance = srln_init();
     
    251242                        indev_t *sink = stdin_wire();
    252243                        indev_t *srln = srln_wire(srln_instance, sink);
    253                        
     244
     245                        // wire std. input to niagara
    254246                        instance->srlnin = srln;
    255247                        thread_ready(instance->thread);
    256248                }
    257249        }
    258        
    259250        return instance;
    260251}
Note: See TracChangeset for help on using the changeset viewer.