00001
00002
00003
00004
00005
00006
00007
00008 #include <const.h>
00009 #include <string.h>
00010
00011 #include <arch/i386.h>
00012 #include <arch/interrupt.h>
00013
00014 #include <kernel/console.h>
00015 #include <kernel/keyboard.h>
00016 #include <kernel/task.h>
00017
00018 #include <kernel/serial.h>
00019
00020
00021
00022
00023
00024
00025
00026
00027 static int rs232_read_head=0;
00028
00029 static int rs232_read_tail=0;
00030
00031
00032 byte rs232_read_buf[RS232_BUF_DIM];
00033
00034
00035 static int rs232_write_head=0;
00036
00037 static int rs232_write_tail=0;
00038
00039
00040 byte rs232_write_buf[RS232_BUF_DIM];
00041
00042
00043 static word curr_port = COM1;
00044
00045
00046
00047 void rs232_handler(word port)
00048 {
00049 byte flag, ch;
00050
00051 while(TRUE)
00052 {
00053
00054 flag = inportb(port+2);
00055
00056 if (flag & 0x01) break;
00057
00058 switch(flag & 0x06)
00059 {
00060
00061 case 0x00:
00062 (void)inportb(port+6);
00063 break;
00064
00065
00066 case 0x02:
00067 if (rs232_write_head != rs232_write_tail)
00068 {
00069 ch = rs232_write_buf[rs232_write_head];
00070 rs232_write_head = (rs232_write_head+1)%RS232_BUF_DIM;
00071 outportb(port, ch);
00072 }
00073
00074 if (rs232_write_head == rs232_write_tail)
00075 outportb(port+1, 0x01);
00076 break;
00077
00078
00079 case 0x04:
00080 while(TRUE)
00081 {
00082
00083 flag = inportb(port+5);
00084 if (!(flag & 0x01)) break;
00085
00086
00087 ch = inportb(port);
00088
00089
00090 if (((rs232_read_tail+1)%RS232_BUF_DIM) != rs232_read_head)
00091 {
00092 rs232_read_buf[rs232_read_tail] = ch;
00093 rs232_read_tail = (rs232_read_tail+1)%RS232_BUF_DIM;
00094 }
00095 }
00096 break;
00097
00098
00099 case 0x06:
00100 (void)inportb(port+5);
00101 break;
00102 }
00103 }
00104 }
00105
00106
00107
00108 void rs232_handler_port1()
00109 {
00110 rs232_handler(PORT1);
00111 }
00112
00113
00114
00115 void rs232_handler_port2()
00116 {
00117 rs232_handler(PORT2);
00118 }
00119
00120
00121
00122 void close_rs232(word port)
00123 {
00124
00125 outportb(port+1, 0);
00126
00127
00128 outportb(port+2, 0);
00129
00130
00131 outportb(port+4, 0);
00132 }
00133
00134
00135
00136
00137
00138 void init_rs232(word port, byte divisor)
00139 {
00140
00141 if ( (port == COM1) || (port == COM3) )
00142 install_irq_handler( RS232_1_IRQ, (void *)rs232_handler_port1 );
00143 else if ( (port == COM2) || (port == COM4) )
00144 install_irq_handler( RS232_2_IRQ, (void *)rs232_handler_port2 );
00145 else
00146 return;
00147
00148
00149 outportb(port+1, 0);
00150
00151
00152 outportb(port+3, 0x80);
00153
00154
00155 outportb(port, divisor);
00156
00157 outportb(port+1, 0x00);
00158
00159
00160 outportb(port+3, 0x03);
00161
00162
00163 outportb(port+2, 0xC7);
00164
00165
00166 outportb(port+4, 0x0B);
00167
00168
00169 outportb(port+1, 0x01);
00170
00171
00172 (void)inportb(port);
00173
00174 (void)inportb(port+5);
00175
00176 (void)inportb(port+6);
00177 }
00178
00179
00180
00181
00182
00183 byte rs232_getchar()
00184 {
00185 byte temp;
00186 dword IF = GET_IF();
00187
00188
00189 while( rs232_read_head==rs232_read_tail )
00190 {
00191 enable();
00192 idle();
00193 }
00194
00195 disable();
00196
00197
00198 temp = rs232_read_buf[rs232_read_head];
00199 rs232_read_head = (rs232_read_head+1)%RS232_BUF_DIM;
00200
00201 SET_IF(IF);
00202
00203 return(temp);
00204 }
00205
00206
00207
00208
00209
00210 void rs232_putchar(byte c)
00211 {
00212 dword IF = GET_IF();
00213
00214
00215 if (((rs232_write_tail+1)%RS232_BUF_DIM) == rs232_write_head) return;
00216
00217 disable();
00218
00219
00220 rs232_write_buf[rs232_write_tail] = c;
00221 rs232_write_tail = (rs232_write_tail+1)%RS232_BUF_DIM;
00222
00223 SET_IF(IF);
00224
00225
00226 outportb(curr_port+1, 0x03);
00227 }
00228
00229
00230
00231
00232
00233
00234
00235 void rs232_task()
00236 {
00237 while(TRUE)
00238 {
00239 kputchar(rs232_getchar());
00240 }
00241 }
00242
00243
00244
00245
00246
00247 void rs232_chat(char *argv)
00248 {
00249 static char *default_bps = "38400";
00250 task_t *child;
00251 word key;
00252
00253 kprintf( "\n\rOpening RS232-1 interface (COM1)... "
00254 "\n\rPress CTRL-X to quit." );
00255
00256 if (strcmp(argv, "2400")==0) init_rs232(COM1, BPS_2400);
00257 else if (strcmp(argv, "4800")==0) init_rs232(COM1, BPS_4800);
00258 else if (strcmp(argv, "9600")==0) init_rs232(COM1, BPS_9600);
00259 else if (strcmp(argv, "19200")==0) init_rs232(COM1, BPS_19200);
00260 else if (strcmp(argv, "38400")==0) init_rs232(COM1, BPS_38400);
00261 else if (strcmp(argv, "56700")==0) init_rs232(COM1, BPS_56700);
00262 else if (strcmp(argv, "115200")==0) init_rs232(COM1, BPS_115200);
00263 else
00264 {
00265
00266 argv = default_bps;
00267 init_rs232(COM1, BPS_38400);
00268 }
00269
00270 kprintf("\n\rBitrate: %s bps", argv);
00271 child = create_process(&rs232_task, &rs232_task, 0, "rs232_task", KERNEL_PRIVILEGE);
00272 set_color(GREEN);
00273 kprintf("\r [ OK ]\n\r");
00274 set_color(DEFAULT_COLOR);
00275
00276 while(TRUE)
00277 {
00278
00279 key = kgetchar();
00280 if (key==CTRL_X) break;
00281 if ((key&0xFF)==13) rs232_putchar(10);
00282
00283
00284 rs232_putchar(key);
00285 }
00286
00287
00288 kputchar((byte)CTRL_X);
00289
00290
00291 kill(child->pid);
00292
00293
00294 close_rs232(curr_port);
00295 kprintf("\n\rBye.\n\r");
00296 }
00297
00298