Main Page | Directories | File List | Globals

syscons.c

Go to the documentation of this file.
00001 /*
00002  * kernel_drivers/adi_char/syscons.c
00003  *
00004  * Copyright (c) 2003-2004 Lukasz Dembinski <dembol@nasa.com.pl>
00005  * All Rights Reserved
00006  * 
00007  * Date:        2004/01
00008  * Author:      Lukasz Dembinski
00009  * Info:        syscons.c core file
00010  * Contact:     mailto: <dembol@nasa.com.pl>
00011  *
00012  */
00013 
00014 #include <agnix/agnix.h>
00015 #include <agnix/adi/adi.h>
00016 #include <agnix/memory.h>
00017 #include <agnix/terminal.h>
00018 #include <agnix/display.h>
00019 #include <agnix/panic.h>
00020 #include <agnix/wait.h>
00021 #include <agnix/sprintf.h>
00022 #include <agnix/console.h>
00023 
00024 #define SCREEN_SCROLL_LINES             10
00025 
00026 extern struct display_s text_display;
00027 extern int kbd_screen_scroll;
00028 
00029 int term_cur;
00030 int term_init = 0;
00031 struct terminal_s term_sys[MAX_TERMINALS];
00032 struct terminal_driver_s term_sys_driver;
00033 
00034 int syscons_count_offset(struct terminal_s *term, char *buf, int screen_scroll)
00035 {
00036     int lines  = 0;
00037     int head   = term->term_buf.head;
00038     int size_x = term->term_var->term_size_x;
00039     int size_y = term->term_var->term_size_y;
00040     int term_data_len = term->term_buf.data_len;
00041     int i;
00042     int j;
00043 
00044     i = head;
00045     j = 0;
00046 
00047     do {
00048         if (i - 1 < 0)
00049             i = term_data_len;
00050         else
00051             i = (i - 1) % term_data_len;
00052 
00053         if ((buf[i] == '\n') || (j == size_x - 1)) {
00054             j = 0;
00055             lines++;
00056         }
00057         else
00058             j++;
00059         
00060     } while(lines < size_y + screen_scroll * SCREEN_SCROLL_LINES);
00061     
00062     return (i + 1) % term_data_len;
00063 }
00064 
00065 int syscons_refresh(struct terminal_s *term, int screen_scroll)
00066 {
00067     struct display_s *disp = term->term_driver->display;
00068     char *term_data = term->term_buf.data;
00069     int term_data_len = term->term_buf.data_len;
00070     int size_x = term->term_var->term_size_x;
00071     int size_y = term->term_var->term_size_y;
00072     int i;
00073     int x, y;
00074     
00075     i = syscons_count_offset(term, term_data, screen_scroll);
00076 
00077     for (y = 0; y < size_y; y++) {
00078         for (x = 0; x < size_x; x++) {
00079             if ((term_data[i] != '\n') && (term_data[i] != 0)) {
00080                 disp->ops->putc(disp, term_data[i], x, y, 7);
00081                 i = (i + 1) % term_data_len;
00082             }
00083             else
00084                 disp->ops->putc(disp, ' ', x, y, 7);
00085         }
00086         
00087         if (term_data[i] == '\n')
00088             i = (i + 1) % term_data_len;
00089     }
00090     
00091     return 0;
00092 }
00093 
00094 int syscons_init(struct terminal_s *term)
00095 {
00096     return 0;
00097 }
00098 
00099 int syscons_open(char *filename, int mode)
00100 {
00101     int i;
00102 
00103     for (i = 0; i < MAX_TERMINALS; i++) {
00104         if (term_sys[i].term_pgrp == 0)
00105             break;
00106     }
00107     
00108     if (i == MAX_TERMINALS)
00109         return -1;
00110 
00111     term_sys[i].term_pgrp = current_task->t_pid;
00112     current_task->term    = &term_sys[i];
00113     
00114     return 0;
00115 }
00116 
00117 int syscons_write_char(struct terminal_s *term, char character)
00118 {
00119     int head            = term->term_buf.head;
00120     char *term_data     = term->term_buf.data;
00121     int term_data_len   = term->term_buf.data_len;
00122     int input_head      = term->term_buf.input_head;
00123     char *term_input_data       = term->term_buf.input;
00124     int term_input_data_len     = term->term_buf.input_data_len;
00125 
00126     if (term->term_buf.data == NULL) {
00127         term->term_buf.data = (char *)get_free_pages(1);
00128         if (term->term_buf.data == NULL)
00129             return -1;
00130             
00131         head          = term->term_buf.head = term->term_buf.tail = 0;
00132         term_data_len = term->term_buf.data_len = (2 << PAGE_SHIFT) - 1;
00133         term_data     = term->term_buf.data;
00134     }
00135 
00136     term_data[head]     = character;
00137     head                = (head + 1) % term_data_len;
00138     term->term_buf.head = head;
00139     term_data[head] = 0;
00140     
00141     if (term->term_buf.input == NULL) {
00142         term->term_buf.input = (char *)get_free_pages(1);
00143         if (term->term_buf.input == NULL)
00144             return -1;
00145             
00146         input_head          = term->term_buf.input_head = term->term_buf.input_tail = 0;
00147         term_input_data_len = term->term_buf.input_data_len = (2 << PAGE_SHIFT) - 1;
00148         term_input_data     = term->term_buf.input;
00149     }
00150 
00151     term_input_data[input_head] = character;
00152     input_head                  = (input_head + 1) % term_input_data_len;
00153     term->term_buf.input_head   = input_head;
00154 
00155     if (term->term_active) {
00156         if (term->term_driver && term->term_driver->ops->refresh) {
00157             kbd_screen_scroll = 0;
00158             term->term_driver->ops->refresh(term, 0);
00159         }
00160     }
00161 
00162     if (character == '\n')
00163         wait_list_wake_up(&term->wait_list);
00164 
00165     
00166     return 0;
00167 }
00168 
00169 int syscons_write(struct terminal_s *term, char *buf, int count)
00170 {
00171     int head            = term->term_buf.head;
00172     char *term_data     = term->term_buf.data;
00173     int term_data_len   = term->term_buf.data_len;
00174     int i               = 0;
00175 
00176     if (buf[0] == 0)
00177         return 0;
00178 
00179     for (i = 0; i < count; i++) {
00180         if (term->term_buf.data == NULL) {
00181             term->term_buf.data = (char *)get_free_pages(1);
00182             if (term->term_buf.data == NULL)
00183                 return -1;
00184 
00185             head          = term->term_buf.head = term->term_buf.tail = 0;
00186             term_data_len = term->term_buf.data_len = (2 << PAGE_SHIFT) - 1;
00187             term_data     = term->term_buf.data;
00188         }
00189         
00190         term_data[head] = buf[i];
00191         head = (head + 1) % term_data_len;
00192     }   
00193 
00194     term->term_buf.head = head;
00195     term_data[head]     = 0;
00196 
00197     if (term->term_active) {
00198         if (term->term_driver && term->term_driver->ops->refresh) {
00199             kbd_screen_scroll = 0;
00200             term->term_driver->ops->refresh(term, 0);
00201         }
00202     }
00203 
00204     return i;
00205 }
00206 
00207 int syscons_read(struct terminal_s *term, char *buf, int count)
00208 {
00209     int input_head;
00210     int input_tail;
00211     char *input_data;
00212     int term_input_len;
00213     int i, j, len;
00214     
00215     if (term->term_pgrp != current_task->t_pid)
00216         return -1;
00217     
00218     while (term->term_buf.input == NULL) {
00219         wait_list_sleep_on(current_task, &term->wait_list);
00220         wait_list_remove(current_task, &term->wait_list);
00221     }
00222 
00223     do {
00224     
00225         input_tail     = term->term_buf.input_tail;
00226         input_head     = term->term_buf.input_head;
00227         input_data     = term->term_buf.input;
00228         term_input_len = term->term_buf.input_data_len;
00229         for (i = input_tail; i != input_head; i = (i + 1) % term_input_len) {
00230             if (input_data[i] == '\n')
00231                 break;
00232         }
00233 
00234         if (i == input_head) {
00235             wait_list_sleep_on(current_task, &term->wait_list);
00236             wait_list_remove(current_task, &term->wait_list);
00237             continue;
00238         }
00239 
00240     } while (i == input_head);
00241     
00242     j = 0;
00243     len = 0;
00244     for (i = input_tail; ((i != input_head) && (count)); 
00245          i = (i + 1) % term_input_len, len++, j++, count--) {
00246          
00247         buf[j] = input_data[i];
00248         
00249         if (input_data[i] == '\n')
00250             break;
00251     }
00252 
00253     buf[j + 1] = 0;
00254     term->term_buf.input_tail = (i + 1) % term_input_len;
00255     
00256     return len;
00257 }
00258 
00259 int syscons_read_current(char *buf, int count)
00260 {
00261     return syscons_read(&term_sys[term_cur], buf, count);
00262 }
00263 
00264 struct terminal_driver_ops_s term_sys_driver_ops = { 
00265     .refresh            = syscons_refresh
00266 };
00267 
00268 struct terminal_var_s term_sys_var = { 
00269     .term_size_x        = 80,
00270     .term_size_y        = 25 
00271 };
00272 
00273 struct terminal_ops_s term_sys_ops = { 
00274     .init               = syscons_init,
00275     .read               = syscons_read,
00276     .write              = syscons_write,
00277     .write_char         = syscons_write_char
00278 };
00279 
00280 struct terminal_driver_s term_sys_driver = {
00281     .ops                = &term_sys_driver_ops,
00282     .display            = &text_display
00283 };
00284 
00285 int __init adi_sysconsole_init(void)
00286 {
00287     int i;
00288 
00289     for (i = 0; i < MAX_TERMINALS; i++) {
00290         memset(&term_sys[i], 0, sizeof(struct terminal_s));
00291 
00292         INIT_LIST_HEAD(&(term_sys[i].term_list));
00293         INIT_LIST_HEAD(&(term_sys[i].term_sys_list));
00294         wait_list_init(&(term_sys[i].wait_list));
00295 
00296         term_sys[i].term_nr        = i;
00297         term_sys[i].term_var       = &term_sys_var;
00298         term_sys[i].ops            = &term_sys_ops;
00299         term_sys[i].term_active    = 0;
00300         
00301         if (register_terminal(&term_sys[i]) < 0)
00302             kernel_panic("register_terminal() error\n");       
00303 
00304         register_terminal_driver(&term_sys[i], &term_sys_driver);
00305     }
00306 
00307     term_sys[0].term_active = 1;
00308     term_cur                = 0;
00309     term_init               = 1;
00310     
00311     return 0;
00312 }
Dokumentacje wygenerowano programem Doxygen 1.4.2 dla projektu Agnix