Ignore:
Timestamp:
2009-08-22T10:48:00Z (15 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
04803bf
Parents:
1ea99cc (diff), a71c158 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

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

    r1ea99cc rb50b5af2  
    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 = &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.