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