Changes in kernel/arch/sparc64/src/drivers/sgcn.c [a71c158:8e7afdbc] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/sparc64/src/drivers/sgcn.c
ra71c158 r8e7afdbc 49 49 #include <synch/spinlock.h> 50 50 51 #define POLL_INTERVAL 51 #define POLL_INTERVAL 10000 52 52 53 53 /* … … 57 57 * not sure whether this value is valid generally. 58 58 */ 59 #define SBBC_START 59 #define SBBC_START 0x63000000000 60 60 61 61 /* offset of SRAM within the SBBC memory */ 62 #define SBBC_SRAM_OFFSET 62 #define SBBC_SRAM_OFFSET 0x900000 63 63 64 64 /* size (in bytes) of the physical memory area which will be mapped */ 65 #define MAPPED_AREA_SIZE 65 #define MAPPED_AREA_SIZE (128 * 1024) 66 66 67 67 /* magic string contained at the beginning of SRAM */ 68 #define SRAM_TOC_MAGIC 68 #define SRAM_TOC_MAGIC "TOCSRAM" 69 69 70 70 /* … … 78 78 * Therefore HelenOS needs to make no such arrangements any more. 79 79 */ 80 #define CONSOLE_KEY 80 #define CONSOLE_KEY "OBPCONS" 81 81 82 82 /* magic string contained at the beginning of the console buffer */ 83 #define SGCN_BUFFER_MAGIC 83 #define SGCN_BUFFER_MAGIC "CON" 84 84 85 85 /* … … 87 87 * offset from the SRAM beginning. 88 88 */ 89 #define SRAM(type, offset) ((type *) (instance->sram_begin + (offset)))89 #define SRAM(type, offset) ((type *) (sram_begin + (offset))) 90 90 91 91 /* Returns a pointer to the SRAM table of contents. */ 92 #define SRAM_TOC 92 #define SRAM_TOC (SRAM(iosram_toc_t, 0)) 93 93 94 94 /* … … 97 97 */ 98 98 #define SGCN_BUFFER(type, offset) \ 99 ((type *) ( instance->buffer_begin + (offset)))99 ((type *) (sgcn_buffer_begin + (offset))) 100 100 101 101 /** 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 */ 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 */ 104 130 static void sgcn_putchar(outdev_t *, const wchar_t, bool); 105 131 106 static outdev_operations_t sgcndev_ops = { 107 .write = sgcn_putchar, 108 . redraw = NULL132 /** SGCN output device operations */ 133 static outdev_operations_t sgcnout_ops = { 134 .write = sgcn_putchar 109 135 }; 110 136 111 static sgcn_instance_t *instance = NULL;137 static outdev_t sgcnout; /**< SGCN output device. */ 112 138 113 139 /** … … 132 158 static void init_sram_begin(void) 133 159 { 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"); 137 165 if (!chosen) 138 166 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"); 142 169 if (!iosram_toc) 143 170 panic("Cannot find property 'iosram-toc'."); 144 171 if (!iosram_toc->value) 145 172 panic("Cannot find SRAM TOC."); 146 147 uintptr_tsram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET173 174 sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET 148 175 + *((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); 150 177 151 178 register_sram(sram_begin_physical); 152 }153 154 /**155 * Function regularly called by the keyboard polling thread. Finds out whether156 * there are some unread characters in the input queue. If so, it picks them up157 * 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 }198 179 } 199 180 … … 209 190 * under the sram.buffer.offset sysinfo key. 210 191 */ 211 static void sgcn_init(void) 212 { 213 if (instance) 192 static void sgcn_buffer_begin_init(void) 193 { 194 static bool initialized; 195 196 if (initialized) 214 197 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(); 221 200 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; 247 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; 248 217 } 249 218 … … 259 228 uint32_t size = end - begin; 260 229 261 /* We need pointers to volatile variables */230 /* we need pointers to volatile variables */ 262 231 volatile char *buf_ptr = (volatile char *) 263 232 SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr); 264 233 volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr); 265 234 volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr); 266 235 267 236 /* 268 237 * Write the character and increment the write pointer modulo the … … 280 249 */ 281 250 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 ; 284 253 *buf_ptr = c; 285 254 *out_wrptr_ptr = new_wrptr; … … 290 259 * character is converted to CRLF. 291 260 */ 292 static void sgcn_putchar(outdev_t * dev, const wchar_t ch, bool silent)261 static void sgcn_putchar(outdev_t *od, const wchar_t ch, bool silent) 293 262 { 294 263 if (!silent) { 295 spinlock_lock(& instance->output_lock);264 spinlock_lock(&sgcn_output_lock); 296 265 297 266 if (ascii_check(ch)) { … … 302 271 sgcn_do_putchar(U_SPECIAL); 303 272 304 spinlock_unlock(& instance->output_lock);273 spinlock_unlock(&sgcn_output_lock); 305 274 } 306 275 } 307 276 308 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); 335 } 336 } 337 338 /** 309 339 * A public function which initializes input from the Serengeti console. 310 340 */ 311 341 sgcn_instance_t *sgcnin_init(void) 312 342 { 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 314 359 return instance; 315 360 } … … 319 364 ASSERT(instance); 320 365 ASSERT(srlnin); 321 366 322 367 instance->srlnin = srlnin; 323 368 thread_ready(instance->thread); 324 369 325 370 sysinfo_set_item_val("kbd", NULL, true); 326 371 } … … 329 374 * A public function which initializes output to the Serengeti console. 330 375 */ 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; 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; 355 384 } 356 385
Note:
See TracChangeset
for help on using the changeset viewer.