Changeset a71c158 in mainline for kernel/arch/sparc64/src/drivers/sgcn.c
- Timestamp:
- 2009-08-21T14:12:45Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0e6dce8, b50b5af2, e5792d1
- Parents:
- 90c8b8d
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/sparc64/src/drivers/sgcn.c
r90c8b8d ra71c158 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 *) (sram_begin + (offset)))89 #define SRAM(type, offset) ((type *) (instance->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 *) ( sgcn_buffer_begin + (offset)))99 ((type *) (instance->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 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 130 104 static void sgcn_putchar(outdev_t *, const wchar_t, bool); 131 105 132 /** SGCN output device operations */ 133 static outdev_operations_t sgcnout_ops = { 134 . write = sgcn_putchar106 static outdev_operations_t sgcndev_ops = { 107 .write = sgcn_putchar, 108 .redraw = NULL 135 109 }; 136 110 137 static outdev_t sgcnout; /**< SGCN output device. */111 static sgcn_instance_t *instance = NULL; 138 112 139 113 /** … … 158 132 static void init_sram_begin(void) 159 133 { 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"); 165 137 if (!chosen) 166 138 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"); 169 142 if (!iosram_toc) 170 143 panic("Cannot find property 'iosram-toc'."); 171 144 if (!iosram_toc->value) 172 145 panic("Cannot find SRAM TOC."); 173 174 sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET146 147 uintptr_t sram_begin_physical = SBBC_START + SBBC_SRAM_OFFSET 175 148 + *((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); 177 150 178 151 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 } 179 198 } 180 199 … … 190 209 * under the sram.buffer.offset sysinfo key. 191 210 */ 192 static void sgcn_buffer_begin_init(void) 193 { 194 static bool initialized; 195 196 if (initialized) 211 static void sgcn_init(void) 212 { 213 if (instance) 197 214 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 } 217 248 } 218 249 … … 228 259 uint32_t size = end - begin; 229 260 230 /* we need pointers to volatile variables */261 /* We need pointers to volatile variables */ 231 262 volatile char *buf_ptr = (volatile char *) 232 263 SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr); 233 264 volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr); 234 265 volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr); 235 266 236 267 /* 237 268 * Write the character and increment the write pointer modulo the … … 249 280 */ 250 281 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 253 284 *buf_ptr = c; 254 285 *out_wrptr_ptr = new_wrptr; … … 259 290 * character is converted to CRLF. 260 291 */ 261 static void sgcn_putchar(outdev_t * od, const wchar_t ch, bool silent)292 static void sgcn_putchar(outdev_t *dev, const wchar_t ch, bool silent) 262 293 { 263 294 if (!silent) { 264 spinlock_lock(& sgcn_output_lock);295 spinlock_lock(&instance->output_lock); 265 296 266 297 if (ascii_check(ch)) { … … 271 302 sgcn_do_putchar(U_SPECIAL); 272 303 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); 335 305 } 336 306 } … … 341 311 sgcn_instance_t *sgcnin_init(void) 342 312 { 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(); 359 314 return instance; 360 315 } … … 364 319 ASSERT(instance); 365 320 ASSERT(srlnin); 366 321 367 322 instance->srlnin = srlnin; 368 323 thread_ready(instance->thread); 369 324 370 325 sysinfo_set_item_val("kbd", NULL, true); 371 326 } … … 374 329 * A public function which initializes output to the Serengeti console. 375 330 */ 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); 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; 384 355 } 385 356
Note:
See TracChangeset
for help on using the changeset viewer.