Rev 4042 | Rev 4146 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4042 | Rev 4087 | ||
---|---|---|---|
Line 72... | Line 72... | ||
72 | SPINLOCK_INITIALIZE(klog_lock); |
72 | SPINLOCK_INITIALIZE(klog_lock); |
73 | 73 | ||
74 | /** Physical memory area used for klog buffer */ |
74 | /** Physical memory area used for klog buffer */ |
75 | static parea_t klog_parea; |
75 | static parea_t klog_parea; |
76 | 76 | ||
77 | /* |
- | |
78 | * For now, we use 0 as INR. |
- | |
79 | * However, it is therefore desirable to have architecture specific |
- | |
80 | * definition of KLOG_VIRT_INR in the future. |
- | |
81 | */ |
- | |
82 | #define KLOG_VIRT_INR 0 |
- | |
83 | - | ||
84 | static irq_t klog_irq; |
- | |
85 | - | ||
86 | static chardev_operations_t null_stdout_ops = { |
- | |
87 | .suspend = NULL, |
- | |
88 | .resume = NULL, |
- | |
89 | .write = NULL, |
- | |
90 | .read = NULL |
- | |
91 | }; |
- | |
92 | - | ||
93 | chardev_t null_stdout = { |
- | |
94 | .name = "null", |
- | |
95 | .op = &null_stdout_ops |
- | |
96 | }; |
- | |
97 | - | ||
98 | /** Allways refuse IRQ ownership. |
- | |
99 | * |
- | |
100 | * This is not a real IRQ, so we always decline. |
- | |
101 | * |
- | |
102 | * @return Always returns IRQ_DECLINE. |
- | |
103 | */ |
- | |
104 | static irq_ownership_t klog_claim(irq_t *irq) |
- | |
105 | { |
- | |
106 | return IRQ_DECLINE; |
- | |
107 | } |
- | |
108 | - | ||
109 | static void stdin_suspend(chardev_t *d) |
- | |
110 | { |
- | |
111 | } |
- | |
112 | - | ||
113 | static void stdin_resume(chardev_t *d) |
- | |
114 | { |
- | |
115 | } |
- | |
116 | - | ||
117 | static chardev_operations_t stdin_ops = { |
- | |
118 | .suspend = stdin_suspend, |
- | |
119 | .resume = stdin_resume, |
- | |
120 | }; |
- | |
121 | - | ||
122 | /** Standard input character device */ |
77 | /** Standard input and output character devices */ |
123 | static chardev_t _stdin; |
- | |
124 | chardev_t *stdin = NULL; |
78 | indev_t *stdin = NULL; |
125 | chardev_t *stdout = &null_stdout; |
79 | outdev_t *stdout = NULL; |
126 | - | ||
127 | void console_init(void) |
- | |
128 | { |
- | |
129 | chardev_initialize("stdin", &_stdin, &stdin_ops); |
- | |
130 | stdin = &_stdin; |
- | |
131 | } |
- | |
132 | 80 | ||
133 | /** Initialize kernel logging facility |
81 | /** Initialize kernel logging facility |
134 | * |
82 | * |
135 | * The shared area contains kernel cyclic buffer. Userspace application may |
83 | * The shared area contains kernel cyclic buffer. Userspace application may |
136 | * be notified on new data with indication of position and size |
84 | * be notified on new data with indication of position and size |
137 | * of the data within the circular buffer. |
85 | * of the data within the circular buffer. |
- | 86 | * |
|
138 | */ |
87 | */ |
139 | void klog_init(void) |
88 | void klog_init(void) |
140 | { |
89 | { |
141 | void *faddr = (void *) KA2PA(klog); |
90 | void *faddr = (void *) KA2PA(klog); |
142 | 91 | ||
143 | ASSERT((uintptr_t) faddr % FRAME_SIZE == 0); |
92 | ASSERT((uintptr_t) faddr % FRAME_SIZE == 0); |
144 | ASSERT(KLOG_SIZE % FRAME_SIZE == 0); |
93 | ASSERT(KLOG_SIZE % FRAME_SIZE == 0); |
145 | - | ||
146 | devno_t devno = device_assign_devno(); |
- | |
147 | 94 | ||
148 | klog_parea.pbase = (uintptr_t) faddr; |
95 | klog_parea.pbase = (uintptr_t) faddr; |
149 | klog_parea.frames = SIZE2FRAMES(KLOG_SIZE); |
96 | klog_parea.frames = SIZE2FRAMES(KLOG_SIZE); |
150 | ddi_parea_register(&klog_parea); |
97 | ddi_parea_register(&klog_parea); |
151 | 98 | ||
152 | sysinfo_set_item_val("klog.faddr", NULL, (unative_t) faddr); |
99 | sysinfo_set_item_val("klog.faddr", NULL, (unative_t) faddr); |
153 | sysinfo_set_item_val("klog.pages", NULL, SIZE2FRAMES(KLOG_SIZE)); |
100 | sysinfo_set_item_val("klog.pages", NULL, SIZE2FRAMES(KLOG_SIZE)); |
154 | sysinfo_set_item_val("klog.devno", NULL, devno); |
- | |
155 | sysinfo_set_item_val("klog.inr", NULL, KLOG_VIRT_INR); |
- | |
156 | 101 | ||
157 | irq_initialize(&klog_irq); |
102 | //irq_initialize(&klog_irq); |
158 | klog_irq.devno = devno; |
103 | //klog_irq.devno = devno; |
159 | klog_irq.inr = KLOG_VIRT_INR; |
104 | //klog_irq.inr = KLOG_VIRT_INR; |
160 | klog_irq.claim = klog_claim; |
105 | //klog_irq.claim = klog_claim; |
161 | irq_register(&klog_irq); |
106 | //irq_register(&klog_irq); |
162 | 107 | ||
163 | spinlock_lock(&klog_lock); |
108 | spinlock_lock(&klog_lock); |
164 | klog_inited = true; |
109 | klog_inited = true; |
165 | spinlock_unlock(&klog_lock); |
110 | spinlock_unlock(&klog_lock); |
166 | } |
111 | } |
Line 175... | Line 120... | ||
175 | { |
120 | { |
176 | silent = true; |
121 | silent = true; |
177 | arch_release_console(); |
122 | arch_release_console(); |
178 | } |
123 | } |
179 | 124 | ||
180 | /** Get character from character device. Do not echo character. |
125 | bool check_poll(indev_t *indev) |
181 | * |
126 | { |
- | 127 | if (indev == NULL) |
|
- | 128 | return false; |
|
- | 129 | ||
- | 130 | if (indev->op == NULL) |
|
- | 131 | return false; |
|
- | 132 | ||
182 | * @param chardev Character device. |
133 | return (indev->op->poll != NULL); |
- | 134 | } |
|
- | 135 | ||
- | 136 | /** Get character from input character device. Do not echo character. |
|
183 | * |
137 | * |
- | 138 | * @param indev Input character device. |
|
184 | * @return Character read. |
139 | * @return Character read. |
- | 140 | * |
|
185 | */ |
141 | */ |
186 | uint8_t _getc(chardev_t *chardev) |
142 | uint8_t _getc(indev_t *indev) |
187 | { |
143 | { |
188 | uint8_t ch; |
- | |
189 | ipl_t ipl; |
- | |
190 | - | ||
191 | if (atomic_get(&haltstate)) { |
144 | if (atomic_get(&haltstate)) { |
192 | /* If we are here, we are hopefully on the processor, that |
145 | /* If we are here, we are hopefully on the processor that |
193 | * issued the 'halt' command, so proceed to read the character |
146 | * issued the 'halt' command, so proceed to read the character |
194 | * directly from input |
147 | * directly from input |
195 | */ |
148 | */ |
196 | if (chardev->op->read) |
149 | if (check_poll(indev)) |
197 | return chardev->op->read(chardev); |
150 | return indev->op->poll(indev); |
- | 151 | ||
198 | /* no other way of interacting with user, halt */ |
152 | /* No other way of interacting with user */ |
- | 153 | interrupts_disable(); |
|
- | 154 | ||
199 | if (CPU) |
155 | if (CPU) |
200 | printf("cpu%u: ", CPU->id); |
156 | printf("cpu%u: ", CPU->id); |
201 | else |
157 | else |
202 | printf("cpu: "); |
158 | printf("cpu: "); |
203 | printf("halted (no kconsole)\n"); |
159 | printf("halted (no polling input)\n"); |
204 | cpu_halt(); |
160 | cpu_halt(); |
205 | } |
161 | } |
206 | 162 | ||
207 | waitq_sleep(&chardev->wq); |
163 | waitq_sleep(&indev->wq); |
208 | ipl = interrupts_disable(); |
164 | ipl_t ipl = interrupts_disable(); |
209 | spinlock_lock(&chardev->lock); |
165 | spinlock_lock(&indev->lock); |
210 | ch = chardev->buffer[(chardev->index - chardev->counter) % CHARDEV_BUFLEN]; |
166 | uint8_t ch = indev->buffer[(indev->index - indev->counter) % INDEV_BUFLEN]; |
211 | chardev->counter--; |
167 | indev->counter--; |
212 | spinlock_unlock(&chardev->lock); |
168 | spinlock_unlock(&indev->lock); |
213 | interrupts_restore(ipl); |
169 | interrupts_restore(ipl); |
214 | - | ||
215 | chardev->op->resume(chardev); |
- | |
216 | 170 | ||
217 | return ch; |
171 | return ch; |
218 | } |
172 | } |
219 | 173 | ||
220 | /** Get string from character device. |
174 | /** Get string from input character device. |
221 | * |
175 | * |
222 | * Read characters from character device until first occurrence |
176 | * Read characters from input character device until first occurrence |
223 | * of newline character. |
177 | * of newline character. |
224 | * |
178 | * |
225 | * @param chardev Character device. |
179 | * @param indev Input character device. |
226 | * @param buf Buffer where to store string terminated by '\0'. |
180 | * @param buf Buffer where to store string terminated by '\0'. |
227 | * @param buflen Size of the buffer. |
181 | * @param buflen Size of the buffer. |
228 | * |
182 | * |
229 | * @return Number of characters read. |
183 | * @return Number of characters read. |
- | 184 | * |
|
230 | */ |
185 | */ |
231 | count_t gets(chardev_t *chardev, char *buf, size_t buflen) |
186 | count_t gets(indev_t *indev, char *buf, size_t buflen) |
232 | { |
187 | { |
233 | index_t index = 0; |
188 | index_t index = 0; |
234 | char ch; |
- | |
235 | 189 | ||
236 | while (index < buflen) { |
190 | while (index < buflen) { |
237 | ch = _getc(chardev); |
191 | char ch = _getc(indev); |
238 | if (ch == '\b') { |
192 | if (ch == '\b') { |
239 | if (index > 0) { |
193 | if (index > 0) { |
240 | index--; |
194 | index--; |
241 | /* Space backspace, space */ |
195 | /* Space backspace, space */ |
242 | putchar('\b'); |
196 | putchar('\b'); |
Line 251... | Line 205... | ||
251 | buf[index] = '\0'; |
205 | buf[index] = '\0'; |
252 | return (count_t) index; |
206 | return (count_t) index; |
253 | } |
207 | } |
254 | buf[index++] = ch; |
208 | buf[index++] = ch; |
255 | } |
209 | } |
- | 210 | ||
256 | return (count_t) index; |
211 | return (count_t) index; |
257 | } |
212 | } |
258 | 213 | ||
259 | /** Get character from device & echo it to screen */ |
214 | /** Get character from input device & echo it to screen */ |
260 | uint8_t getc(chardev_t *chardev) |
215 | uint8_t getc(indev_t *indev) |
261 | { |
216 | { |
262 | uint8_t ch; |
- | |
263 | - | ||
264 | ch = _getc(chardev); |
217 | uint8_t ch = _getc(indev); |
265 | putchar(ch); |
218 | putchar(ch); |
266 | return ch; |
219 | return ch; |
267 | } |
220 | } |
268 | 221 | ||
269 | void klog_update(void) |
222 | void klog_update(void) |
270 | { |
223 | { |
271 | spinlock_lock(&klog_lock); |
224 | spinlock_lock(&klog_lock); |
272 | 225 | ||
273 | if ((klog_inited) && (klog_irq.notif_cfg.notify) && (klog_uspace > 0)) { |
226 | // if ((klog_inited) && (klog_irq.notif_cfg.notify) && (klog_uspace > 0)) { |
274 | ipc_irq_send_msg_3(&klog_irq, klog_start, klog_len, klog_uspace); |
227 | // ipc_irq_send_msg_3(&klog_irq, klog_start, klog_len, klog_uspace); |
275 | klog_uspace = 0; |
228 | // klog_uspace = 0; |
276 | } |
229 | // } |
277 | 230 | ||
278 | spinlock_unlock(&klog_lock); |
231 | spinlock_unlock(&klog_lock); |
279 | } |
232 | } |
280 | 233 | ||
281 | void putchar(char c) |
234 | void putchar(char c) |
282 | { |
235 | { |
283 | spinlock_lock(&klog_lock); |
236 | spinlock_lock(&klog_lock); |
284 | 237 | ||
285 | if ((klog_stored > 0) && (stdout->op->write)) { |
238 | if ((klog_stored > 0) && (stdout) && (stdout->op->write)) { |
286 | /* Print charaters stored in kernel log */ |
239 | /* Print charaters stored in kernel log */ |
287 | index_t i; |
240 | index_t i; |
288 | for (i = klog_len - klog_stored; i < klog_len; i++) |
241 | for (i = klog_len - klog_stored; i < klog_len; i++) |
289 | stdout->op->write(stdout, klog[(klog_start + i) % KLOG_SIZE], silent); |
242 | stdout->op->write(stdout, klog[(klog_start + i) % KLOG_SIZE], silent); |
290 | klog_stored = 0; |
243 | klog_stored = 0; |
Line 295... | Line 248... | ||
295 | if (klog_len < KLOG_SIZE) |
248 | if (klog_len < KLOG_SIZE) |
296 | klog_len++; |
249 | klog_len++; |
297 | else |
250 | else |
298 | klog_start = (klog_start + 1) % KLOG_SIZE; |
251 | klog_start = (klog_start + 1) % KLOG_SIZE; |
299 | 252 | ||
300 | if (stdout->op->write) |
253 | if ((stdout) && (stdout->op->write)) |
301 | stdout->op->write(stdout, c, silent); |
254 | stdout->op->write(stdout, c, silent); |
302 | else { |
255 | else { |
303 | /* The character is just in the kernel log */ |
256 | /* The character is just in the kernel log */ |
304 | if (klog_stored < klog_len) |
257 | if (klog_stored < klog_len) |
305 | klog_stored++; |
258 | klog_stored++; |