Changes in kernel/arch/sparc64/src/drivers/niagara.c [b366a6f4:d7533c7] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/sparc64/src/drivers/niagara.c
rb366a6f4 rd7533c7 32 32 /** 33 33 * @file 34 * @brief 34 * @brief Niagara input/output driver based on hypervisor calls. 35 35 */ 36 36 … … 52 52 #include <genarch/srln/srln.h> 53 53 54 /* Polling interval in miliseconds */54 /* polling interval in miliseconds */ 55 55 #define POLL_INTERVAL 10000 56 56 57 /* Device instance */57 /* device instance */ 58 58 static niagara_instance_t *instance = NULL; 59 59 60 static void niagara_putchar(outdev_t *, const wchar_t );61 62 /** Character device operations */60 static void niagara_putchar(outdev_t *, const wchar_t, bool); 61 62 /** character device operations */ 63 63 static outdev_operations_t niagara_ops = { 64 64 .write = niagara_putchar, … … 66 66 }; 67 67 68 /* *68 /* 69 69 * The driver uses hypercalls to print characters to the console. Since the 70 70 * hypercall cannot be performed from the userspace, we do this: 71 * 72 * The kernel "little brother" driver (which will be present no matter what 73 * the DDI architecture is -- as we need the kernel part for the kconsole) 71 * The kernel "little brother" driver (which will be present no matter what the 72 * DDI architecture is - as we need the kernel part for the kconsole) 74 73 * defines a shared buffer. Kernel walks through the buffer (in the same thread 75 74 * which is used for polling the keyboard) and prints any pending characters 76 * to the console (using hypercalls). 77 * 78 * The userspace fb server maps this shared buffer to its address space and 79 * output operation it does is performed using the mapped buffer. The shared 80 * buffer definition follows. 81 */ 82 #define OUTPUT_BUFFER_SIZE ((PAGE_SIZE) - 2 * 8) 83 75 * to the console (using hypercalls). The userspace fb server maps this shared 76 * buffer to its address space and output operation it does is performed using 77 * the mapped buffer. The shared buffer definition follows. 78 */ 79 #define OUTPUT_BUFFER_SIZE ((PAGE_SIZE) - 2 * 8) 84 80 static volatile struct { 85 81 uint64_t read_ptr; 86 82 uint64_t write_ptr; 87 83 char data[OUTPUT_BUFFER_SIZE]; 88 } __attribute__ ((packed)) __attribute__ ((aligned(PAGE_SIZE))) output_buffer; 89 90 static parea_t outbuf_parea; 84 } 85 __attribute__ ((packed)) 86 __attribute__ ((aligned(PAGE_SIZE))) 87 output_buffer; 91 88 92 89 /** 93 90 * Analogous to the output_buffer, see the previous definition. 94 91 */ 95 #define INPUT_BUFFER_SIZE ((PAGE_SIZE) - 2 * 8) 96 92 #define INPUT_BUFFER_SIZE ((PAGE_SIZE) - 2 * 8) 97 93 static volatile struct { 98 94 uint64_t write_ptr; 99 95 uint64_t read_ptr; 100 96 char data[INPUT_BUFFER_SIZE]; 101 } __attribute__ ((packed)) __attribute__ ((aligned(PAGE_SIZE))) input_buffer; 102 103 static parea_t inbuf_parea; 104 105 /** Write a single character to the standard output. */ 97 } 98 __attribute__ ((packed)) 99 __attribute__ ((aligned(PAGE_SIZE))) 100 input_buffer; 101 102 103 /** Writes a single character to the standard output. */ 106 104 static inline void do_putchar(const char c) { 107 /* Repeat until the buffer is non-full */ 108 while (__hypercall_fast1(CONS_PUTCHAR, c) == HV_EWOULDBLOCK); 109 } 110 111 /** Write a single character to the standard output. */ 112 static void niagara_putchar(outdev_t *dev, const wchar_t ch) 113 { 114 if ((!outbuf_parea.mapped) || (console_override)) { 115 do_putchar(ch); 116 if (ch == '\n') 117 do_putchar('\r'); 118 } 119 } 120 121 /** Poll keyboard and print pending characters. 122 * 123 * Ask the hypervisor whether there is any unread character. If so, 124 * pick it up and send it to the indev layer. 125 * 126 * Check whether the userspace output driver has pushed any 127 * characters to the output buffer and eventually print them. 128 * 129 */ 130 static void niagara_poll(void) 131 { 132 /* 133 * Print any pending characters from the 134 * shared buffer to the console. 135 */ 136 105 /* repeat until the buffer is non-full */ 106 while (__hypercall_fast1(CONS_PUTCHAR, c) == HV_EWOULDBLOCK) 107 ; 108 } 109 110 /** Writes a single character to the standard output. */ 111 static void niagara_putchar(outdev_t *dev, const wchar_t ch, bool silent) 112 { 113 if (silent) 114 return; 115 116 do_putchar(ch); 117 if (ch == '\n') 118 do_putchar('\r'); 119 } 120 121 /** 122 * Function regularly called by the keyboard polling thread. Asks the 123 * hypervisor whether there is any unread character. If so, it picks it up 124 * and sends it to the upper layers of HelenOS. 125 * 126 * Apart from that, it also checks whether the userspace output driver has 127 * pushed any characters to the output buffer. If so, it prints them. 128 */ 129 static void niagara_poll(niagara_instance_t *instance) 130 { 131 /* print any pending characters from the shared buffer to the console */ 137 132 while (output_buffer.read_ptr != output_buffer.write_ptr) { 138 133 do_putchar(output_buffer.data[output_buffer.read_ptr]); 139 134 output_buffer.read_ptr = 140 ((output_buffer.read_ptr) + 1) % OUTPUT_BUFFER_SIZE; 141 } 142 143 /* 144 * Read character from keyboard. 145 */ 146 135 ((output_buffer.read_ptr) + 1) % OUTPUT_BUFFER_SIZE; 136 } 137 147 138 uint64_t c; 139 140 /* read character from keyboard, send it to upper layers of HelenOS */ 148 141 if (__hypercall_fast_ret1(0, 0, 0, 0, 0, CONS_GETCHAR, &c) == HV_EOK) { 149 if ((!inbuf_parea.mapped) || (console_override)) { 150 /* 151 * Kernel console is active, send 152 * the character to kernel. 153 */ 142 if (!silent) { 143 /* kconsole active, send the character to kernel */ 154 144 indev_push_character(instance->srlnin, c); 155 145 } else { 156 /* 157 * Kernel console is inactive, send 158 * the character to uspace driver. 159 */ 146 /* kconsole inactive, send the character to uspace driver */ 160 147 input_buffer.data[input_buffer.write_ptr] = (char) c; 161 148 input_buffer.write_ptr = 162 149 ((input_buffer.write_ptr) + 1) % INPUT_BUFFER_SIZE; 163 150 } 164 151 } 165 152 } 166 153 167 /** Polling thread function.168 * 169 */ 170 static void kniagarapoll(void * arg) {154 /** 155 * Polling thread function. 156 */ 157 static void kniagarapoll(void *instance) { 171 158 while (true) { 172 niagara_poll( );159 niagara_poll(instance); 173 160 thread_usleep(POLL_INTERVAL); 174 161 } 175 162 } 176 163 177 /** Initialize the input/output subsystem 178 * 164 /** 165 * Initializes the input/output subsystem so that the Niagara standard 166 * input/output is used. 179 167 */ 180 168 static void niagara_init(void) … … 184 172 185 173 instance = malloc(sizeof(niagara_instance_t), FRAME_ATOMIC); 186 instance->thread = thread_create(kniagarapoll, NULL, TASK, 0,187 "kniagarapoll", true);188 174 189 if (!instance->thread) { 190 free(instance); 191 instance = NULL; 192 return; 193 } 194 175 if (instance) { 176 instance->thread = thread_create(kniagarapoll, instance, TASK, 0, 177 "kniagarapoll", true); 178 179 if (!instance->thread) { 180 free(instance); 181 instance = NULL; 182 return; 183 } 184 } 185 195 186 instance->srlnin = NULL; 196 187 197 188 output_buffer.read_ptr = 0; 198 189 output_buffer.write_ptr = 0; 199 190 input_buffer.write_ptr = 0; 200 191 input_buffer.read_ptr = 0; 201 192 202 193 /* 203 194 * Set sysinfos and pareas so that the userspace counterpart of the 204 195 * niagara fb and kbd driver can communicate with kernel using shared 205 196 * buffers. 206 */207 197 */ 198 208 199 sysinfo_set_item_val("fb.kind", NULL, 5); 209 200 210 201 sysinfo_set_item_val("niagara.outbuf.address", NULL, 211 202 KA2PA(&output_buffer)); 212 203 sysinfo_set_item_val("niagara.outbuf.size", NULL, 213 204 PAGE_SIZE); 214 205 sysinfo_set_item_val("niagara.outbuf.datasize", NULL, 215 216 206 OUTPUT_BUFFER_SIZE); 207 217 208 sysinfo_set_item_val("niagara.inbuf.address", NULL, 218 209 KA2PA(&input_buffer)); 219 210 sysinfo_set_item_val("niagara.inbuf.size", NULL, 220 211 PAGE_SIZE); 221 212 sysinfo_set_item_val("niagara.inbuf.datasize", NULL, 222 INPUT_BUFFER_SIZE); 223 213 INPUT_BUFFER_SIZE); 214 215 static parea_t outbuf_parea; 224 216 outbuf_parea.pbase = (uintptr_t) (KA2PA(&output_buffer)); 225 217 outbuf_parea.frames = 1; 226 218 outbuf_parea.unpriv = false; 227 outbuf_parea.mapped = false;228 219 ddi_parea_register(&outbuf_parea); 229 220 221 static parea_t inbuf_parea; 230 222 inbuf_parea.pbase = (uintptr_t) (KA2PA(&input_buffer)); 231 223 inbuf_parea.frames = 1; 232 224 inbuf_parea.unpriv = false; 233 inbuf_parea.mapped = false;234 225 ddi_parea_register(&inbuf_parea); 235 226 236 227 outdev_t *niagara_dev = malloc(sizeof(outdev_t), FRAME_ATOMIC); 237 228 outdev_initialize("niagara_dev", niagara_dev, &niagara_ops); … … 239 230 } 240 231 241 /** Initialize input from the Niagara console.242 * 232 /** 233 * A public function which initializes input from the Niagara console. 243 234 */ 244 235 niagara_instance_t *niagarain_init(void) 245 236 { 246 237 niagara_init(); 247 238 248 239 if (instance) { 249 240 srln_instance_t *srln_instance = srln_init(); … … 251 242 indev_t *sink = stdin_wire(); 252 243 indev_t *srln = srln_wire(srln_instance, sink); 253 244 245 // wire std. input to niagara 254 246 instance->srlnin = srln; 255 247 thread_ready(instance->thread); 256 248 } 257 249 } 258 259 250 return instance; 260 251 }
Note:
See TracChangeset
for help on using the changeset viewer.