Ignore:
File:
1 edited

Legend:

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

    ra71c158 r8e7afdbc  
    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 *) (instance->sram_begin + (offset)))
     89#define SRAM(type, offset)      ((type *) (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 *) (instance->buffer_begin + (offset)))
     99        ((type *) (sgcn_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 
     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 */
     105static 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 */
     111static uintptr_t sgcn_buffer_begin;
     112
     113/* true iff the kernel driver should ignore pressed keys */
     114static 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 */
     120SPINLOCK_INITIALIZE(sgcn_output_lock);
     121
     122/*
     123 * Prevents the input buffer read/write pointers from getting to inconsistent
     124 * state.
     125 */
     126SPINLOCK_INITIALIZE(sgcn_input_lock);
     127
     128
     129/* functions referenced from definitions of I/O operations structures */
    104130static void sgcn_putchar(outdev_t *, const wchar_t, bool);
    105131
    106 static outdev_operations_t sgcndev_ops = {
    107         .write = sgcn_putchar,
    108         .redraw = NULL
     132/** SGCN output device operations */
     133static outdev_operations_t sgcnout_ops = {
     134        .write = sgcn_putchar
    109135};
    110136
    111 static sgcn_instance_t *instance = NULL;
     137static outdev_t sgcnout;        /**< SGCN output device. */
    112138
    113139/**
     
    132158static void init_sram_begin(void)
    133159{
    134         ASSERT(instance)
    135        
    136         ofw_tree_node_t *chosen = ofw_tree_lookup("/chosen");
     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");
    137165        if (!chosen)
    138166                panic("Cannot find '/chosen'.");
    139        
    140         ofw_tree_property_t *iosram_toc =
    141             ofw_tree_getprop(chosen, "iosram-toc");
     167
     168        iosram_toc = ofw_tree_getprop(chosen, "iosram-toc");
    142169        if (!iosram_toc)
    143170                panic("Cannot find property 'iosram-toc'.");
    144171        if (!iosram_toc->value)
    145172                panic("Cannot find SRAM TOC.");
    146        
    147         uintptr_t sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
     173
     174        sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET
    148175            + *((uint32_t *) iosram_toc->value);
    149         instance->sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
     176        sram_begin = hw_map(sram_begin_physical, MAPPED_AREA_SIZE);
    150177       
    151178        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  */
    159 static 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  */
    191 static void ksgcnpoll(void *instance) {
    192         while (true) {
    193                 if (!silent)
    194                         sgcn_poll(instance);
    195                
    196                 thread_usleep(POLL_INTERVAL);
    197         }
    198179}
    199180
     
    209190 * under the sram.buffer.offset sysinfo key.
    210191 */
    211 static void sgcn_init(void)
    212 {
    213         if (instance)
     192static void sgcn_buffer_begin_init(void)
     193{
     194        static bool initialized;
     195       
     196        if (initialized)
    214197                return;
    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);
     198
     199        init_sram_begin();
    221200               
    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;
     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;
    247208        }
     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;
    248217}
    249218
     
    259228        uint32_t size = end - begin;
    260229       
    261         /* We need pointers to volatile variables */
     230        /* we need pointers to volatile variables */
    262231        volatile char *buf_ptr = (volatile char *)
    263232            SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
    264233        volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
    265234        volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
    266        
     235
    267236        /*
    268237         * Write the character and increment the write pointer modulo the
     
    280249         */
    281250        uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
    282         while (*out_rdptr_ptr == new_wrptr);
    283        
     251        while (*out_rdptr_ptr == new_wrptr)
     252                ;
    284253        *buf_ptr = c;
    285254        *out_wrptr_ptr = new_wrptr;
     
    290259 * character is converted to CRLF.
    291260 */
    292 static void sgcn_putchar(outdev_t *dev, const wchar_t ch, bool silent)
     261static void sgcn_putchar(outdev_t *od, const wchar_t ch, bool silent)
    293262{
    294263        if (!silent) {
    295                 spinlock_lock(&instance->output_lock);
     264                spinlock_lock(&sgcn_output_lock);
    296265               
    297266                if (ascii_check(ch)) {
     
    302271                        sgcn_do_putchar(U_SPECIAL);
    303272               
    304                 spinlock_unlock(&instance->output_lock);
     273                spinlock_unlock(&sgcn_output_lock);
    305274        }
    306275}
    307276
    308277/**
     278 * Grabs the input for kernel.
     279 */
     280void sgcn_grab(void)
     281{
     282        kbd_disabled = false;
     283}
     284
     285/**
     286 * Releases the input so that userspace can use it.
     287 */
     288void 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 */
     298static 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 */
     330static void ksgcnpoll(void *instance) {
     331        while (1) {
     332                if (!silent)
     333                        sgcn_poll(instance);
     334                thread_usleep(POLL_INTERVAL);
     335        }
     336}
     337
     338/**
    309339 * A public function which initializes input from the Serengeti console.
    310340 */
    311341sgcn_instance_t *sgcnin_init(void)
    312342{
    313         sgcn_init();
     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       
    314359        return instance;
    315360}
     
    319364        ASSERT(instance);
    320365        ASSERT(srlnin);
    321        
     366
    322367        instance->srlnin = srlnin;
    323368        thread_ready(instance->thread);
    324        
     369
    325370        sysinfo_set_item_val("kbd", NULL, true);
    326371}
     
    329374 * A public function which initializes output to the Serengeti console.
    330375 */
    331 outdev_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;
     376void 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;
    355384}
    356385
Note: See TracChangeset for help on using the changeset viewer.