Ignore:
Timestamp:
2009-08-21T14:12:45Z (15 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0e6dce8, b50b5af2, e5792d1
Parents:
90c8b8d
Message:

kernel output devices now suport multiple instances (except ski and sgcn, which respect the same interface, but behave as singletons)
if more than one output device gets initialized, the output is cloned to all of them
get rid of arch_grab_console() and arch_release_console() (output devices can implement a generic "redraw" method, input devices respect the "silent" global variable)
related cleanups and modifications

File:
1 edited

Legend:

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

    r90c8b8d ra71c158  
    4949#include <synch/spinlock.h>
    5050
    51 #define POLL_INTERVAL           10000
     51#define POLL_INTERVAL  10000
    5252
    5353/*
     
    5757 * not sure whether this value is valid generally.
    5858 */
    59 #define SBBC_START              0x63000000000
     59#define SBBC_START  0x63000000000
    6060
    6161/* offset of SRAM within the SBBC memory */
    62 #define SBBC_SRAM_OFFSET        0x900000
     62#define SBBC_SRAM_OFFSET  0x900000
    6363
    6464/* size (in bytes) of the physical memory area which will be mapped */
    65 #define MAPPED_AREA_SIZE        (128 * 1024)
     65#define MAPPED_AREA_SIZE  (128 * 1024)
    6666
    6767/* magic string contained at the beginning of SRAM */
    68 #define SRAM_TOC_MAGIC          "TOCSRAM"
     68#define SRAM_TOC_MAGIC  "TOCSRAM"
    6969
    7070/*
     
    7878 * Therefore HelenOS needs to make no such arrangements any more.
    7979 */
    80 #define CONSOLE_KEY             "OBPCONS"
     80#define CONSOLE_KEY  "OBPCONS"
    8181
    8282/* magic string contained at the beginning of the console buffer */
    83 #define SGCN_BUFFER_MAGIC       "CON"
     83#define SGCN_BUFFER_MAGIC  "CON"
    8484
    8585/*
     
    8787 * offset from the SRAM beginning.
    8888 */
    89 #define SRAM(type, offset)      ((type *) (sram_begin + (offset)))
     89#define SRAM(type, offset)  ((type *) (instance->sram_begin + (offset)))
    9090
    9191/* Returns a pointer to the SRAM table of contents. */
    92 #define SRAM_TOC                (SRAM(iosram_toc_t, 0))
     92#define SRAM_TOC  (SRAM(iosram_toc_t, 0))
    9393
    9494/*
     
    9797 */
    9898#define SGCN_BUFFER(type, offset) \
    99         ((type *) (sgcn_buffer_begin + (offset)))
     99        ((type *) (instance->buffer_begin + (offset)))
    100100
    101101/** Returns a pointer to the console buffer header. */
    102 #define SGCN_BUFFER_HEADER      (SGCN_BUFFER(sgcn_buffer_header_t, 0))
    103 
    104 /** starting address of SRAM, will be set by the init_sram_begin function */
    105 static uintptr_t sram_begin;
    106 
    107 /**
    108  * starting address of the SGCN buffer, will be set by the
    109  * init_sgcn_buffer_begin function
    110  */
    111 static uintptr_t sgcn_buffer_begin;
    112 
    113 /* true iff the kernel driver should ignore pressed keys */
    114 static bool kbd_disabled;
    115 
    116 /*
    117  * Ensures that writing to the buffer and consequent update of the write pointer
    118  * are together one atomic operation.
    119  */
    120 SPINLOCK_INITIALIZE(sgcn_output_lock);
    121 
    122 /*
    123  * Prevents the input buffer read/write pointers from getting to inconsistent
    124  * state.
    125  */
    126 SPINLOCK_INITIALIZE(sgcn_input_lock);
    127 
    128 
    129 /* functions referenced from definitions of I/O operations structures */
     102#define SGCN_BUFFER_HEADER  (SGCN_BUFFER(sgcn_buffer_header_t, 0))
     103
    130104static void sgcn_putchar(outdev_t *, const wchar_t, bool);
    131105
    132 /** SGCN output device operations */
    133 static outdev_operations_t sgcnout_ops = {
    134         .write = sgcn_putchar
     106static outdev_operations_t sgcndev_ops = {
     107        .write = sgcn_putchar,
     108        .redraw = NULL
    135109};
    136110
    137 static outdev_t sgcnout;        /**< SGCN output device. */
     111static sgcn_instance_t *instance = NULL;
    138112
    139113/**
     
    158132static void init_sram_begin(void)
    159133{
    160         ofw_tree_node_t *chosen;
    161         ofw_tree_property_t *iosram_toc;
    162         uintptr_t sram_begin_physical;
    163 
    164         chosen = ofw_tree_lookup("/chosen");
     134        ASSERT(instance)
     135       
     136        ofw_tree_node_t *chosen = ofw_tree_lookup("/chosen");
    165137        if (!chosen)
    166138                panic("Cannot find '/chosen'.");
    167 
    168         iosram_toc = ofw_tree_getprop(chosen, "iosram-toc");
     139       
     140        ofw_tree_property_t *iosram_toc =
     141            ofw_tree_getprop(chosen, "iosram-toc");
    169142        if (!iosram_toc)
    170143                panic("Cannot find property 'iosram-toc'.");
    171144        if (!iosram_toc->value)
    172145                panic("Cannot find SRAM TOC.");
    173 
    174         sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
     146       
     147        uintptr_t sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
    175148            + *((uint32_t *) iosram_toc->value);
    176         sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
     149        instance->sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
    177150       
    178151        register_sram(sram_begin_physical);
     152}
     153
     154/**
     155 * Function regularly called by the keyboard polling thread. Finds out whether
     156 * there are some unread characters in the input queue. If so, it picks them up
     157 * and sends them to the upper layers of HelenOS.
     158 */
     159static void sgcn_poll(sgcn_instance_t *instance)
     160{
     161        uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
     162        uint32_t end = SGCN_BUFFER_HEADER->in_end;
     163        uint32_t size = end - begin;
     164       
     165        if (silent)
     166                return;
     167       
     168        spinlock_lock(&instance->input_lock);
     169       
     170        /* we need pointers to volatile variables */
     171        volatile char *buf_ptr = (volatile char *)
     172            SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
     173        volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
     174        volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
     175       
     176        while (*in_rdptr_ptr != *in_wrptr_ptr) {
     177                buf_ptr = (volatile char *)
     178                    SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
     179                char c = *buf_ptr;
     180                *in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
     181               
     182                indev_push_character(instance->srlnin, c);
     183        }
     184       
     185        spinlock_unlock(&instance->input_lock);
     186}
     187
     188/**
     189 * Polling thread function.
     190 */
     191static void ksgcnpoll(void *instance) {
     192        while (true) {
     193                if (!silent)
     194                        sgcn_poll(instance);
     195               
     196                thread_usleep(POLL_INTERVAL);
     197        }
    179198}
    180199
     
    190209 * under the sram.buffer.offset sysinfo key.
    191210 */
    192 static void sgcn_buffer_begin_init(void)
    193 {
    194         static bool initialized;
    195        
    196         if (initialized)
     211static void sgcn_init(void)
     212{
     213        if (instance)
    197214                return;
    198 
    199         init_sram_begin();
    200                
    201         ASSERT(str_cmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
    202        
    203         /* lookup TOC entry with the correct key */
    204         uint32_t i;
    205         for (i = 0; i < MAX_TOC_ENTRIES; i++) {
    206                 if (str_cmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
    207                         break;
    208         }
    209         ASSERT(i < MAX_TOC_ENTRIES);
    210        
    211         sgcn_buffer_begin = sram_begin + SRAM_TOC->keys[i].offset;
    212        
    213         sysinfo_set_item_val("sram.buffer.offset", NULL,
    214             SRAM_TOC->keys[i].offset);
    215        
    216         initialized = true;
     215       
     216        instance = malloc(sizeof(sgcn_instance_t), FRAME_ATOMIC);
     217       
     218        if (instance) {
     219                instance->thread = thread_create(ksgcnpoll, instance, TASK, 0,
     220                    "ksgcnpoll", true);
     221               
     222                if (!instance->thread) {
     223                        free(instance);
     224                        instance = NULL;
     225                        return;
     226                }
     227               
     228                init_sram_begin();
     229               
     230                ASSERT(str_cmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
     231               
     232                /* Lookup TOC entry with the correct key */
     233                uint32_t i;
     234                for (i = 0; i < MAX_TOC_ENTRIES; i++) {
     235                        if (str_cmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
     236                                break;
     237                }
     238                ASSERT(i < MAX_TOC_ENTRIES);
     239               
     240                instance->buffer_begin =
     241                    instance->sram_begin + SRAM_TOC->keys[i].offset;
     242               
     243                sysinfo_set_item_val("sram.buffer.offset", NULL,
     244                    SRAM_TOC->keys[i].offset);
     245               
     246                instance->srlnin = NULL;
     247        }
    217248}
    218249
     
    228259        uint32_t size = end - begin;
    229260       
    230         /* we need pointers to volatile variables */
     261        /* We need pointers to volatile variables */
    231262        volatile char *buf_ptr = (volatile char *)
    232263            SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
    233264        volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
    234265        volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
    235 
     266       
    236267        /*
    237268         * Write the character and increment the write pointer modulo the
     
    249280         */
    250281        uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
    251         while (*out_rdptr_ptr == new_wrptr)
    252                 ;
     282        while (*out_rdptr_ptr == new_wrptr);
     283       
    253284        *buf_ptr = c;
    254285        *out_wrptr_ptr = new_wrptr;
     
    259290 * character is converted to CRLF.
    260291 */
    261 static void sgcn_putchar(outdev_t *od, const wchar_t ch, bool silent)
     292static void sgcn_putchar(outdev_t *dev, const wchar_t ch, bool silent)
    262293{
    263294        if (!silent) {
    264                 spinlock_lock(&sgcn_output_lock);
     295                spinlock_lock(&instance->output_lock);
    265296               
    266297                if (ascii_check(ch)) {
     
    271302                        sgcn_do_putchar(U_SPECIAL);
    272303               
    273                 spinlock_unlock(&sgcn_output_lock);
    274         }
    275 }
    276 
    277 /**
    278  * Grabs the input for kernel.
    279  */
    280 void sgcn_grab(void)
    281 {
    282         kbd_disabled = false;
    283 }
    284 
    285 /**
    286  * Releases the input so that userspace can use it.
    287  */
    288 void sgcn_release(void)
    289 {
    290         kbd_disabled = true;
    291 }
    292 
    293 /**
    294  * Function regularly called by the keyboard polling thread. Finds out whether
    295  * there are some unread characters in the input queue. If so, it picks them up
    296  * and sends them to the upper layers of HelenOS.
    297  */
    298 static void sgcn_poll(sgcn_instance_t *instance)
    299 {
    300         uint32_t begin = SGCN_BUFFER_HEADER->in_begin;
    301         uint32_t end = SGCN_BUFFER_HEADER->in_end;
    302         uint32_t size = end - begin;
    303 
    304         if (kbd_disabled)
    305                 return;
    306 
    307         spinlock_lock(&sgcn_input_lock);
    308        
    309         /* we need pointers to volatile variables */
    310         volatile char *buf_ptr = (volatile char *)
    311             SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
    312         volatile uint32_t *in_wrptr_ptr = &(SGCN_BUFFER_HEADER->in_wrptr);
    313         volatile uint32_t *in_rdptr_ptr = &(SGCN_BUFFER_HEADER->in_rdptr);
    314        
    315         while (*in_rdptr_ptr != *in_wrptr_ptr) {
    316                 buf_ptr = (volatile char *)
    317                     SGCN_BUFFER(char, SGCN_BUFFER_HEADER->in_rdptr);
    318                 char c = *buf_ptr;
    319                 *in_rdptr_ptr = (((*in_rdptr_ptr) - begin + 1) % size) + begin;
    320                        
    321                 indev_push_character(instance->srlnin, c);     
    322         }       
    323 
    324         spinlock_unlock(&sgcn_input_lock);
    325 }
    326 
    327 /**
    328  * Polling thread function.
    329  */
    330 static void ksgcnpoll(void *instance) {
    331         while (1) {
    332                 if (!silent)
    333                         sgcn_poll(instance);
    334                 thread_usleep(POLL_INTERVAL);
     304                spinlock_unlock(&instance->output_lock);
    335305        }
    336306}
     
    341311sgcn_instance_t *sgcnin_init(void)
    342312{
    343         sgcn_buffer_begin_init();
    344        
    345         sgcn_instance_t *instance =
    346             malloc(sizeof(sgcn_instance_t), FRAME_ATOMIC);
    347        
    348         if (instance) {
    349                 instance->srlnin = NULL;
    350                 instance->thread = thread_create(ksgcnpoll, instance, TASK, 0,
    351                     "ksgcnpoll", true);
    352                
    353                 if (!instance->thread) {
    354                         free(instance);
    355                         return NULL;
    356                 }
    357         }
    358        
     313        sgcn_init();
    359314        return instance;
    360315}
     
    364319        ASSERT(instance);
    365320        ASSERT(srlnin);
    366 
     321       
    367322        instance->srlnin = srlnin;
    368323        thread_ready(instance->thread);
    369 
     324       
    370325        sysinfo_set_item_val("kbd", NULL, true);
    371326}
     
    374329 * A public function which initializes output to the Serengeti console.
    375330 */
    376 void sgcnout_init(void)
    377 {
    378         sgcn_buffer_begin_init();
    379 
    380         sysinfo_set_item_val("fb.kind", NULL, 4);
    381 
    382         outdev_initialize("sgcnout", &sgcnout, &sgcnout_ops);
    383         stdout_wire(&sgcnout);
     331outdev_t *sgcnout_init(void)
     332{
     333        sgcn_init();
     334        if (!instance)
     335                return NULL;
     336       
     337        outdev_t *sgcndev = malloc(sizeof(outdev_t), FRAME_ATOMIC);
     338        if (!sgcndev)
     339                return NULL;
     340       
     341        outdev_initialize("sgcndev", sgcndev, &sgcndev_ops);
     342        sgcndev->data = instance;
     343       
     344        if (!fb_exported) {
     345                /*
     346                 * This is the necessary evil until the userspace driver is entirely
     347                 * self-sufficient.
     348                 */
     349                sysinfo_set_item_val("fb.kind", NULL, 4);
     350               
     351                fb_exported = true;
     352        }
     353       
     354        return sgcndev;
    384355}
    385356
Note: See TracChangeset for help on using the changeset viewer.