您的位置:首页 > 移动开发 > IOS开发

字符设备-seria.c tty_io.c seria.c rs_io.s tty_iocnl.c tty.h termios.h keyboard.s源码分析

2015-06-12 15:50 645 查看
1 /*

2 * linux/kernel/serial.c

3 *

4 * (C) 1991 Linus Torvalds

5 */

6

7 /*

8 * serial.c

9 *

10 * This module implements the rs232 io functions

11 * void rs_write(struct tty_struct * queue);

12 * void rs_init(void);

13 * and all interrupts pertaining to serial IO.

14 */

16 #include <linux/tty.h>

17 #include <linux/sched.h>

18 #include <asm/system.h>

19 #include <asm/io.h>

21 #define WAKEUP_CHARS (TTY_BUF_SIZE/4)

23 extern void rs1_interrupt(void);

24 extern void rs2_interrupt(void);

26 static void init(int port)

27 {

28 outb_p(0x80,port+3); /* set DLAB of line control reg */

29 outb_p(0x30,port); /* LS of divisor (48 -> 2400 bps */

30 outb_p(0x00,port+1); /* MS of divisor */

31 outb_p(0x03,port+3); /* reset DLAB */

32 outb_p(0x0b,port+4); /* set DTR,RTS, OUT_2 */

33 outb_p(0x0d,port+1); /* enable all intrs but writes */

34 (void)inb(port); /* read data port to reset things (?) */

35 }

37 void rs_init(void)

38 {

39 set_intr_gate(0x24,rs1_interrupt);

40 set_intr_gate(0x23,rs2_interrupt);

41 init(tty_table[1].read_q.data);

42 init(tty_table[2].read_q.data);

43 outb(inb_p(0x21)&0xE7,0x21);

44 }

45

46 /*

47 * This routine gets called when tty_write has put something into

48 * the write_queue. It must check wheter the queue is empty, and

49 * set the interrupt register accordingly

50 *

51 * void _rs_write(struct tty_struct * tty);

52 */

53 void rs_write(struct tty_struct * tty)

54 {

55 cli();

56 if (!EMPTY(tty->write_q))

57 outb(inb_p(tty->write_q.data+1)|0x02,tty->write_q.data+1);

58 sti();

59 }

ttyio.c



1 /*

2 * linux/kernel/tty_io.c

3 *

4 * (C) 1991 Linus Torvalds

5 */

6

7 /*

8 * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles

9 * or rs-channels. It also implements echoing, cooked mode etc.

10 *

11 * Kill-line thanks to John T Kohl.

12 */

13 #include <ctype.h>

14 #include <errno.h>

15 #include <signal.h>

16

17 #define ALRMMASK (1<<(SIGALRM-1))

18 #define KILLMASK (1<<(SIGKILL-1))

19 #define INTMASK (1<<(SIGINT-1))

20 #define QUITMASK (1<<(SIGQUIT-1))

21 #define TSTPMASK (1<<(SIGTSTP-1))

22

23 #include <linux/sched.h>

24 #include <linux/tty.h>

25 #include <asm/segment.h>

26 #include <asm/system.h>

27

28 #define _L_FLAG(tty,f) ((tty)->termios.c_lflag & f)

29 #define _I_FLAG(tty,f) ((tty)->termios.c_iflag & f)

30 #define _O_FLAG(tty,f) ((tty)->termios.c_oflag & f)

31

32 #define L_CANON(tty) _L_FLAG((tty),ICANON)

33 #define L_ISIG(tty) _L_FLAG((tty),ISIG) 34 #define L_ECHO(tty) _L_FLAG((tty),ECHO)

35 #define L_ECHOE(tty) _L_FLAG((tty),ECHOE)

36 #define L_ECHOK(tty) _L_FLAG((tty),ECHOK)

37 #define L_ECHOCTL(tty) _L_FLAG((tty),ECHOCTL)

38 #define L_ECHOKE(tty) _L_FLAG((tty),ECHOKE)

39

40 #define I_UCLC(tty) _I_FLAG((tty),IUCLC)

41 #define I_NLCR(tty) _I_FLAG((tty),INLCR)

42 #define I_CRNL(tty) _I_FLAG((tty),ICRNL)

43 #define I_NOCR(tty) _I_FLAG((tty),IGNCR)

44

45 #define O_POST(tty) _O_FLAG((tty),OPOST)

46 #define O_NLCR(tty) _O_FLAG((tty),ONLCR)

47 #define O_CRNL(tty) _O_FLAG((tty),OCRNL)

48 #define O_NLRET(tty) _O_FLAG((tty),ONLRET)

49 #define O_LCUC(tty) _O_FLAG((tty),OLCUC)

50

51 struct tty_struct tty_table[] = {

52 {

53 {ICRNL, /* change incoming CR to NL */

54 OPOST|ONLCR, /* change outgoing NL to CRNL */

55 0,

56 ISIG | ICANON | ECHO | ECHOCTL | ECHOKE,

57 0, /* console termio */

58 INIT_C_CC},

59 0, /* initial pgrp */

60 0, /* initial stopped */

61 con_write,

62 {0,0,0,0,""}, /* console read-queue */

63 {0,0,0,0,""}, /* console write-queue */

64 {0,0,0,0,""} /* console secondary queue */

65 },{

66 {0, /* no translation */

67 0, /* no translation */

68 B2400 | CS8,

69 0,

70 0,

71 INIT_C_CC},

72 0,

73 0,

74 rs_write,

75 {0x3f8,0,0,0,""}, /* rs 1 */

76 {0x3f8,0,0,0,""},

77 {0,0,0,0,""}

78 },{

79 {0, /* no translation */

80 0, /* no translation */

81 B2400 | CS8,

82 0,

83 0,

84 INIT_C_CC},

85 0,

86 0,

87 rs_write,

88 {0x2f8,0,0,0,""}, /* rs 2 */

89 {0x2f8,0,0,0,""},

90 {0,0,0,0,""}

91 }

92 };

93

94 /*

95 * these are the tables used by the machine code handlers.

96 * you can implement pseudo-tty's or something by changing

97 * them. Currently not done.

98 */

99 struct tty_queue * table_list[]={

100 &tty_table[0].read_q, &tty_table[0].write_q,

101 &tty_table[1].read_q, &tty_table[1].write_q,

102 &tty_table[2].read_q, &tty_table[2].write_q

103 };

104

105 void tty_init(void)

106 {

107 rs_init();

108 con_init();

109 }

110

111 void tty_intr(struct tty_struct * tty, int mask)

112 {

113 int i;

114

115 if (tty->pgrp <= 0)

116 return;

117 for (i=0;i<NR_TASKS;i++)

118 if (task[i] && task[i]->pgrp==tty->pgrp)

119 task[i]->signal |= mask;

120 }

121

122 static void sleep_if_empty(struct tty_queue * queue)

123 {

124 cli();

125 while (!current->signal && EMPTY(*queue))

126 interruptible_sleep_on(&queue->proc_list);

127 sti();

128 }

130 static void sleep_if_full(struct tty_queue * queue)

131 {

132 if (!FULL(*queue))

133 return;

134 cli();

135 while (!current->signal && LEFT(*queue)<128)

136 interruptible_sleep_on(&queue->proc_list);

137 sti();

138 }

140 void wait_for_keypress(void)

141 {

142 sleep_if_empty(&tty_table[0].secondary);

143 }

145 void copy_to_cooked(struct tty_struct * tty)

146 {

147 signed char c;

148

149 while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) {

150 GETCH(tty->read_q,c);

151 if (c==13)

152 if (I_CRNL(tty))

153 c=10;

154 else if (I_NOCR(tty))

155 continue;

156 else ;

157 else if (c==10 && I_NLCR(tty))

158 c=13;

159 if (I_UCLC(tty))

160 c=tolower(c);

161 if (L_CANON(tty)) {

162 if (c==KILL_CHAR(tty)) {

163 /* deal with killing the input line */

164 while(!(EMPTY(tty->secondary) ||

165 (c=LAST(tty->secondary))==10 ||

166 c==EOF_CHAR(tty))) {

167 if (L_ECHO(tty)) {

168 if (c<32)

169 PUTCH(127,tty->write_q);

170 PUTCH(127,tty->write_q);

171 tty->write(tty);

172 }

173 DEC(tty->secondary.head);

174 }

175 continue;

176 }

177 if (c==ERASE_CHAR(tty)) {

178 if (EMPTY(tty->secondary) ||

179 (c=LAST(tty->secondary))==10 ||

180 c==EOF_CHAR(tty))

181 continue;

182 if (L_ECHO(tty)) {

183 if (c<32)

184 PUTCH(127,tty->write_q);

185 PUTCH(127,tty->write_q);

186 tty->write(tty);

187 }

188 DEC(tty->secondary.head);

189 continue;

190 }

191 if (c==STOP_CHAR(tty)) {

192 tty->stopped=1;

193 continue;

194 }

195 if (c==START_CHAR(tty)) {

196 tty->stopped=0;

197 continue;

198 }

199 }

200 if (L_ISIG(tty)) {

201 if (c==INTR_CHAR(tty)) {

202 tty_intr(tty,INTMASK);

203 continue;

204 }

205 if (c==QUIT_CHAR(tty)) {

206 tty_intr(tty,QUITMASK);

207 continue;

208 }

209 }

210 if (c==10 || c==EOF_CHAR(tty))

211 tty->secondary.data++;

212 if (L_ECHO(tty)) {

213 if (c==10) {

214 PUTCH(10,tty->write_q);

215 PUTCH(13,tty->write_q);

216 } else if (c<32) {

217 if (L_ECHOCTL(tty)) {

218 PUTCH('^',tty->write_q);

219 PUTCH(c+64,tty->write_q);

220 }

221 } else

222 PUTCH(c,tty->write_q);

223 tty->write(tty);

224 }

225 PUTCH(c,tty->secondary);

226 }

227 wake_up(&tty->secondary.proc_list);

228 }

230 int tty_read(unsigned channel, char * buf, int nr)

231 {

232 struct tty_struct * tty;

233 char c, * b=buf;

234 int minimum,time,flag=0;

235 long oldalarm;

236

237 if (channel>2 || nr<0) return -1;

238 tty = &tty_table[channel];

239 oldalarm = current->alarm;

240 time = 10L*tty->termios.c_cc[VTIME];

241 minimum = tty->termios.c_cc[VMIN];

242 if (time && !minimum) {

243 minimum=1;

244 if (flag=(!oldalarm || time+jiffies<oldalarm))

245 current->alarm = time+jiffies;

246 }

247 if (minimum>nr)

248 minimum=nr;

249 while (nr>0) {

250 if (flag && (current->signal & ALRMMASK)) {

251 current->signal &= ~ALRMMASK;

252 break;

253 }

254 if (current->signal)

255 break;

256 if (EMPTY(tty->secondary) || (L_CANON(tty) &&

257 !tty->secondary.data && LEFT(tty->secondary)>20)) {

258 sleep_if_empty(&tty->secondary);

259 continue;

260 }

261 do {

262 GETCH(tty->secondary,c);

263 if (c==EOF_CHAR(tty) || c==10)

264 tty->secondary.data--;

265 if (c==EOF_CHAR(tty) && L_CANON(tty))

266 return (b-buf);

267 else {

268 put_fs_byte(c,b++);

269 if (!--nr)

270 break;

271 }

272 } while (nr>0 && !EMPTY(tty->secondary));

273 if (time && !L_CANON(tty))

274 if (flag=(!oldalarm || time+jiffies<oldalarm))

275 current->alarm = time+jiffies;

276 else

277 current->alarm = oldalarm;

278 if (L_CANON(tty)) {

279 if (b-buf)

280 break;

281 } else if (b-buf >= minimum)

282 break;

283 }

284 current->alarm = oldalarm;

285 if (current->signal && !(b-buf))

286 return -EINTR;

287 return (b-buf);

288 }

290 int tty_write(unsigned channel, char * buf, int nr)

291 {

292 static cr_flag=0;

293 struct tty_struct * tty;

294 char c, *b=buf;

295

296 if (channel>2 || nr<0) return -1;

297 tty = channel + tty_table;

298 while (nr>0) {

299 sleep_if_full(&tty->write_q);

300 if (current->signal)

301 break;

302 while (nr>0 && !FULL(tty->write_q)) {

303 c=get_fs_byte(b);

304 if (O_POST(tty)) {

305 if (c=='\r' && O_CRNL(tty))

306 c='\n';

307 else if (c=='\n' && O_NLRET(tty))

308 c='\r';

309 if (c=='\n' && !cr_flag && O_NLCR(tty)) {

310 cr_flag = 1;

311 PUTCH(13,tty->write_q);

312 continue;

313 }

314 if (O_LCUC(tty))

315 c=toupper(c);

316 }

317 b++; nr--;

318 cr_flag = 0;

319 PUTCH(c,tty->write_q);

320 }

321 tty->write(tty);

322 if (nr>0)

323 schedule();

324 }

325 return (b-buf);

326 }

328 /*

329 * Jeh, sometimes I really like the 386.

330 * This routine is called from an interrupt,

331 * and there should be absolutely no problem

332 * with sleeping even in an interrupt (I hope).

333 * Of course, if somebody proves me wrong, I'll

334 * hate intel for all time :-). We'll have to

335 * be careful and see to reinstating the interrupt

336 * chips before calling this, though.

337 *

338 * I don't think we sleep here under normal circumstances

339 * anyway, which is good, as the task sleeping might be

340 * totally innocent.

341 */

342 void do_tty_interrupt(int tty)

343 {

344 copy_to_cooked(tty_table+tty);

345 }

346

347 void chr_dev_init(void)

348 {

349 }

tty_iocnlt.c

1 /*

2 * linux/kernel/chr_drv/tty_ioctl.c

3 *

4 * (C) 1991 Linus Torvalds

5 */

6

7 #include <errno.h>

8 #include <termios.h>

9

10 #include <linux/sched.h>

11 #include <linux/kernel.h>

12 #include <linux/tty.h>

13

14 #include <asm/io.h>

15 #include <asm/segment.h>

16 #include <asm/system.h>

17

18 static unsigned short quotient[] = {

19 0, 2304, 1536, 1047, 857,

20 768, 576, 384, 192, 96,

21 64, 48, 24, 12, 6, 3

22 };

23

24 static void change_speed(struct tty_struct * tty)

25 {

26 unsigned short port,quot;

27

28 if (!(port = tty->read_q.data))

29 return;

30 quot = quotient[tty->termios.c_cflag & CBAUD];

31 cli();

32 outb_p(0x80,port+3); /* set DLAB */

33 outb_p(quot & 0xff,port); /* LS of divisor */

34 outb_p(quot >> 8,port+1); /* MS of divisor */

35 outb(0x03,port+3); /* reset DLAB */

36 sti();

37 }

38

39 static void flush(struct tty_queue * queue)

40 {

41 cli();

42 queue->head = queue->tail;

43 sti();

44 }

45

46 static void wait_until_sent(struct tty_struct * tty)

47 {

48 /* do nothing - not implemented */

49 }

50

51 static void send_break(struct tty_struct * tty)

52 {

53 /* do nothing - not implemented */

54 }

55

56 static int get_termios(struct tty_struct * tty, struct termios * termios)

57 {

58 int i;

59

60 verify_area(termios, sizeof (*termios));

61 for (i=0 ; i< (sizeof (*termios)) ; i++)

62 put_fs_byte( ((char *)&tty->termios)[i] , i+(char *)termios );

63 return 0;

64 }

66 static int set_termios(struct tty_struct * tty, struct termios * termios)

67 {

68 int i;

69

70 for (i=0 ; i< (sizeof (*termios)) ; i++)

71 ((char *)&tty->termios)[i]=get_fs_byte(i+(char *)termios);

72 change_speed(tty);

73 return 0;

74 }

75

76 static int get_termio(struct tty_struct * tty, struct termio * termio)

77 {

78 int i;

79 struct termio tmp_termio;

80

81 verify_area(termio, sizeof (*termio));

82 tmp_termio.c_iflag = tty->termios.c_iflag;

83 tmp_termio.c_oflag = tty->termios.c_oflag;

84 tmp_termio.c_cflag = tty->termios.c_cflag;

85 tmp_termio.c_lflag = tty->termios.c_lflag;

86 tmp_termio.c_line = tty->termios.c_line;

87 for(i=0 ; i < NCC ; i++)

88 tmp_termio.c_cc[i] = tty->termios.c_cc[i];

89 for (i=0 ; i< (sizeof (*termio)) ; i++)

90 put_fs_byte( ((char *)&tmp_termio)[i] , i+(char *)termio );

91 return 0;

92 }

94 /*

95 * This only works as the 386 is low-byt-first

96 */

97 static int set_termio(struct tty_struct * tty, struct termio * termio)

98 {

99 int i;

100 struct termio tmp_termio;

101

102 for (i=0 ; i< (sizeof (*termio)) ; i++)

103 ((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio);

104 *(unsigned short *)&tty->termios.c_iflag = tmp_termio.c_iflag;

105 *(unsigned short *)&tty->termios.c_oflag = tmp_termio.c_oflag;

106 *(unsigned short *)&tty->termios.c_cflag = tmp_termio.c_cflag;

107 *(unsigned short *)&tty->termios.c_lflag = tmp_termio.c_lflag;

108 tty->termios.c_line = tmp_termio.c_line;

109 for(i=0 ; i < NCC ; i++)

110 tty->termios.c_cc[i] = tmp_termio.c_cc[i];

111 change_speed(tty);

112 return 0;

113 }

114

115 int tty_ioctl(int dev, int cmd, int arg)

116 {

117 struct tty_struct * tty;

118 if (MAJOR(dev) == 5) {

119 dev=current->tty;

120 if (dev<0)

121 panic("tty_ioctl: dev<0");

122 } else

123 dev=MINOR(dev);

124 tty = dev + tty_table;

125 switch (cmd) {

126 case TCGETS:

127 return get_termios(tty,(struct termios *) arg);

128 case TCSETSF:

129 flush(&tty->read_q); /* fallthrough */

130 case TCSETSW:

131 wait_until_sent(tty); /* fallthrough */

132 case TCSETS:

133 return set_termios(tty,(struct termios *) arg);

134 case TCGETA:

135 return get_termio(tty,(struct termio *) arg);

136 case TCSETAF:

137 flush(&tty->read_q); /* fallthrough */

138 case TCSETAW:

139 wait_until_sent(tty); /* fallthrough */

140 case TCSETA:

141 return set_termio(tty,(struct termio *) arg);

142 case TCSBRK:

143 if (!arg) {

144 wait_until_sent(tty);

145 send_break(tty);

146 }

147 return 0;

148 case TCXONC:

149 return -EINVAL; /* not implemented */

150 case TCFLSH:

151 if (arg==0)

152 flush(&tty->read_q);

153 else if (arg==1)

154 flush(&tty->write_q);

155 else if (arg==2) {

156 flush(&tty->read_q);

157 flush(&tty->write_q);

158 } else

159 return -EINVAL;

160 return 0;

161 case TIOCEXCL:

162 return -EINVAL; /* not implemented */

163 case TIOCNXCL:

164 return -EINVAL; /* not implemented */

165 case TIOCSCTTY:

166 return -EINVAL; /* set controlling term NI */

167 case TIOCGPGRP:

168 verify_area((void *) arg,4);

169 put_fs_long(tty->pgrp,(unsigned long *) arg);

170 return 0;

171 case TIOCSPGRP:

172 tty->pgrp=get_fs_long((unsigned long *) arg);

173 return 0;

174 case TIOCOUTQ:

175 verify_area((void *) arg,4);

176 put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);

177 return 0;

178 case TIOCINQ:

179 verify_area((void *) arg,4);

180 put_fs_long(CHARS(tty->secondary),

181 (unsigned long *) arg);

182 return 0;

183 case TIOCSTI:

184 return -EINVAL; /* not implemented */

185 case TIOCGWINSZ:

186 return -EINVAL; /* not implemented */

187 case TIOCSWINSZ:

188 return -EINVAL; /* not implemented */

189 case TIOCMGET:

190 return -EINVAL; /* not implemented */

191 case TIOCMBIS:

192 return -EINVAL; /* not implemented */

193 case TIOCMBIC:

194 return -EINVAL; /* not implemented */

195 case TIOCMSET:

196 return -EINVAL; /* not implemented */

197 case TIOCGSOFTCAR:

198 return -EINVAL; /* not implemented */

199 case TIOCSSOFTCAR:

200 return -EINVAL; /* not implemented */

201 default:

202 return -EINVAL;

203 }

204 }

rs_io.s



1 /*

2 * linux/kernel/rs_io.s

3 *

4 * (C) 1991 Linus Torvalds

5 */

6

7 /*

8 * rs_io.s

9 *

10 * This module implements the rs232 io interrupts.

11 */

12

13 .text

14 .globl _rs1_interrupt,_rs2_interrupt

15

16 size = 1024 /* must be power of two !

17 and must match the value

18 in tty_io.c!!! */

19

20 /* these are the offsets into the read/write buffer structures */

21 rs_addr = 0

22 head = 4

23 tail = 8

24 proc_list = 12

25 buf = 16

26

27 startup = 256 /* chars left in write queue when we restart it */

28

29 /*

30 * These are the actual interrupt routines. They look where

31 * the interrupt is coming from, and take appropriate action.

32 */

33 .align 2

34 _rs1_interrupt:

35 pushl $_table_list+8

36 jmp rs_int

37 .align 2

38 _rs2_interrupt:

39 pushl $_table_list+16

40 rs_int:

41 pushl %edx

42 pushl %ecx

43 pushl %ebx

44 pushl %eax

45 push %es

46 push %ds /* as this is an interrupt, we cannot */

47 pushl $0x10 /* know that bs is ok. Load it */

48 pop %ds

49 pushl $0x10

50 pop %es

51 movl 24(%esp),%edx

52 movl (%edx),%edx

53 movl rs_addr(%edx),%edx

54 addl $2,%edx /* interrupt ident. reg */

55 rep_int:

56 xorl %eax,%eax

57 inb %dx,%al

58 testb $1,%al

59 jne end

60 cmpb $6,%al /* this shouldn't happen, but ... */

61 ja end

62 movl 24(%esp),%ecx

63 pushl %edx

64 subl $2,%edx

65 call jmp_table(,%eax,2) /* NOTE! not *4, bit0 is 0 already */

66 popl %edx

67 jmp rep_int

68 end: movb $0x20,%al

69 outb %al,$0x20 /* EOI */

70 pop %ds

71 pop %es

72 popl %eax

73 popl %ebx

74 popl %ecx

75 popl %edx

76 addl $4,%esp # jump over _table_list entry

77 iret

78

79 jmp_table:

80 .long modem_status,write_char,read_char,line_status

81

82 .align 2

83 modem_status:

84 addl $6,%edx /* clear intr by reading modem status reg */

85 inb %dx,%al

86 ret

87

88 .align 2

89 line_status:

90 addl $5,%edx /* clear intr by reading line status reg. */

91 inb %dx,%al

92 ret

93

94 .align 2

95 read_char:

96 inb %dx,%al

97 movl %ecx,%edx

98 subl $_table_list,%edx

99 shrl $3,%edx

100 movl (%ecx),%ecx # read-queue

101 movl head(%ecx),%ebx

102 movb %al,buf(%ecx,%ebx)

103 incl %ebx

104 andl $size-1,%ebx

105 cmpl tail(%ecx),%ebx

106 je 1f

107 movl %ebx,head(%ecx)

108 1: pushl %edx

109 call _do_tty_interrupt

110 addl $4,%esp

111 ret

112

113 .align 2

114 write_char:

115 movl 4(%ecx),%ecx # write-queue

116 movl head(%ecx),%ebx

117 subl tail(%ecx),%ebx

118 andl $size-1,%ebx # nr chars in queue

119 je write_buffer_empty

120 cmpl $startup,%ebx

121 ja 1f

122 movl proc_list(%ecx),%ebx # wake up sleeping process

123 testl %ebx,%ebx # is there any?

124 je 1f

125 movl $0,(%ebx)

126 1: movl tail(%ecx),%ebx

127 movb buf(%ecx,%ebx),%al

128 outb %al,%dx

129 incl %ebx

130 andl $size-1,%ebx

131 movl %ebx,tail(%ecx)

132 cmpl head(%ecx),%ebx

133 je write_buffer_empty

134 ret

135 .align 2

136 write_buffer_empty:

137 movl proc_list(%ecx),%ebx # wake up sleeping process

138 testl %ebx,%ebx # is there any?

139 je 1f

140 movl $0,(%ebx)

141 1: incl %edx

142 inb %dx,%al

143 jmp 1f

144 1: jmp 1f

145 1: andb $0xd,%al /* disable transmit interrupt */

146 outb %al,%dx

147 ret

include/linux/tty.h

1 /*

2 * 'tty.h' defines some structures used by tty_io.c and some defines.

3 *

4 * NOTE! Don't touch this without checking that nothing in rs_io.s or

5 * con_io.s breaks. Some constants are hardwired into the system (mainly

6 * offsets into 'tty_queue'

7 */

8

9 #ifndef _TTY_H

10 #define _TTY_H

11

12 #include <termios.h>

13

14 #define TTY_BUF_SIZE 1024

15

16 struct tty_queue {

17 unsigned long data; //缓冲区数据统计值

18 unsigned long head; //缓冲区队首

19 unsigned long tail; //缓冲区队尾

20 struct task_struct * proc_list; //等待缓冲区的进程

21 char buf[TTY_BUF_SIZE]; //缓冲区

22 };

23

24 #define INC(a) ((a) = ((a)+1) & (TTY_BUF_SIZE-1))

25 #define DEC(a) ((a) = ((a)-1) & (TTY_BUF_SIZE-1))

26 #define EMPTY(a) ((a).head == (a).tail)

27 #define LEFT(a) (((a).tail-(a).head-1)&(TTY_BUF_SIZE-1))

28 #define LAST(a) ((a).buf[(TTY_BUF_SIZE-1)&((a).head-1)])

29 #define FULL(a) (!LEFT(a))

30 #define CHARS(a) (((a).head-(a).tail)&(TTY_BUF_SIZE-1))

31 #define GETCH(queue,c) \

32 (void)({c=(queue).buf[(queue).tail];INC((queue).tail);})

33 #define PUTCH(c,queue) \

34 (void)({(queue).buf[(queue).head]=(c);INC((queue).head);})

35

36 #define INTR_CHAR(tty) ((tty)->termios.c_cc[VINTR])

37 #define QUIT_CHAR(tty) ((tty)->termios.c_cc[VQUIT])

38 #define ERASE_CHAR(tty) ((tty)->termios.c_cc[VERASE])

39 #define KILL_CHAR(tty) ((tty)->termios.c_cc[VKILL])

40 #define EOF_CHAR(tty) ((tty)->termios.c_cc[VEOF])

41 #define START_CHAR(tty) ((tty)->termios.c_cc[VSTART])

42 #define STOP_CHAR(tty) ((tty)->termios.c_cc[VSTOP])

43 #define SUSPEND_CHAR(tty) ((tty)->termios.c_cc[VSUSP])

44

45 struct tty_struct {

46 struct termios termios; //终端io属性和控制字符数据结构

47 int pgrp; //所属进程组

48 int stopped; //停止标志

49 void (*write)(struct tty_struct * tty); //tty函数指针

50 struct tty_queue read_q; //读队列

51 struct tty_queue write_q; //写队列

52 struct tty_queue secondary; //辅助队列

53 };

54

55 extern struct tty_struct tty_table[];

56

57 /* intr=^C quit=^| erase=del kill=^U

58 eof=^D vtime=\0 vmin=\1 sxtc=\0

59 start=^Q stop=^S susp=^Z eol=\0

60 reprint=^R discard=^U werase=^W lnext=^V

61 eol2=\0

62 */

63 #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"

64

65 void rs_init(void);

66 void con_init(void);

67 void tty_init(void);

68

69 int tty_read(unsigned c, char * buf, int n);

70 int tty_write(unsigned c, char * buf, int n);

71

72 void rs_write(struct tty_struct * tty);

73 void con_write(struct tty_struct * tty);

74

75 void copy_to_cooked(struct tty_struct * tty);

76

77 #endif

termios.h



36 struct winsize {

37 unsigned short ws_row;

38 unsigned short ws_col;

39 unsigned short ws_xpixel;

40 unsigned short ws_ypixel;

41 };

43 #define NCC 8

44 struct termio {

45 unsigned short c_iflag; /* input mode flags */

46 unsigned short c_oflag; /* output mode flags */

47 unsigned short c_cflag; /* control mode flags */

48 unsigned short c_lflag; /* local mode flags */

49 unsigned char c_line; /* line discipline */

50 unsigned char c_cc[NCC]; /* control characters */

51 };

52

53 #define NCCS 17

54 struct termios {

55 unsigned long c_iflag; /* input mode flags */

56 unsigned long c_oflag; /* output mode flags */

57 unsigned long c_cflag; /* control mode flags */

58 unsigned long c_lflag; /* local mode flags */

59 unsigned char c_line; /* line discipline */

60 unsigned char c_cc[NCCS]; /* control characters */

61 };

keyboard.s



1 /*

2 * linux/kernel/keyboard.S

3 *

4 * (C) 1991 Linus Torvalds

5 */

6

7 /*

8 * Thanks to Alfred Leung for US keyboard patches

9 * Wolfgang Thiel for German keyboard patches

10 * Marc Corsini for the French keyboard

11 */

12

13 #include <linux/config.h>

14

15 .text

16 .globl _keyboard_interrupt

17

18 /*

19 * these are for the keyboard read functions

20 */

21 size = 1024 /* must be a power of two ! And MUST be the same

22 as in tty_io.c !!!! */

size是键盘缓冲区队列长度

23 head = 4

24 tail = 8

25 proc_list = 12

26 buf = 16

上面的值是字段在tty_queue中的偏移

28 mode: .byte 0 /* caps, alt, ctrl and shift mode */
一个byte不同的bit代表不同的键按下

29 leds: .byte 2 /* num-lock, caps, scroll-lock mode (nom-lock on) */
同样不同的位代表不同的按键状态

30 e0: .byte 0

扫描码为0xe0或0xe1时,设置该标志。当扫描码为0xe0时,说明后面还有一个字符;当扫描码为0xe1时说明后面还有两个字符

32 /*

33 * con_int is the real interrupt routine that reads the

34 * keyboard scan-code and converts it into the appropriate

35 * ascii character(s).

36 */

37 _keyboard_interrupt:

38 pushl %eax

39 pushl %ebx

40 pushl %ecx

41 pushl %edx

42 push %ds

43 push %es

44 movl $0x10,%eax

45 mov %ax,%ds

46 mov %ax,%es

内核数据段

47 xorl %al,%al /* %eax is scan code */

48 inb $0x60,%al //从键盘控制器相应端口0x60读入扫描码

49 cmpb $0xe0,%al //如果是0xe0说明后面还有一个字符

50 je set_e0

51 cmpb $0xe1,%al //后面还有两个字符

52 je set_e1

53 call key_table(,%eax,4) //

54 movb $0,e0 //复位标记

55 e0_e1: inb $0x61,%al //取键盘控制器端口状态

56 jmp 1f

57 1: jmp 1f

58 1: orb $0x80,%al //al位7置位,禁止键盘工作

59 jmp 1f

60 1: jmp 1f

61 1: outb %al,$0x61 //写入到端口中,禁止键盘工作

62 jmp 1f

63 1: jmp 1f

64 1: andb $0x7F,%al //al位7复位

65 outb %al,$0x61 //允许键盘工作

66 movb $0x20,%al //

67 outb %al,$0x20 //向8259发送结束中断命令

68 pushl $0 //控制台tty号0入栈

69 call _do_tty_interrupt //调用中断处理函数

70 addl $4,%esp //丢弃参数

71 pop %es

72 pop %ds

73 popl %edx

74 popl %ecx

75 popl %ebx

76 popl %eax

77 iret //中断返回

78 set_e0: movb $1,e0 //设置标志

79 jmp e0_e1

80 set_e1: movb $2,e0 //

81 jmp e0_e1

83 /*

84 * This routine fills the buffer with max 8 bytes, taken from

85 * %ebx:%eax. (%ebx is high). The bytes are written in the

86 * order %al,%ah,%eal,%eah,%bl,%bh ... until %eax is zero.

87 */

88 put_queue:

89 pushl %ecx

90 pushl %edx

91 movl _table_list,%edx # read-queue for console

92 movl head(%edx),%ecx //队头指针

93 1: movb %al,buf(%edx,%ecx) //al放到头部

94 incl %ecx //增加头指针

95 andl $size-1,%ecx //&

96 cmpl tail(%edx),%ecx # buffer full - discard everything

97 je 3f //缓冲区满的话跳到3

98 shrdl $8,%ebx,%eax //将ebx中的8个比特右移到eax,ebx保持不变

99 je 2f //如果没有数据就跳到2:

100 shrl $8,%ebx //ebx右移8位

101 jmp 1b //跳转到1,也就是这里是循环把数据存入缓冲区

102 2: movl %ecx,head(%edx) //保存头指针

103 movl proc_list(%edx),%ecx //等待队列指针

104 testl %ecx,%ecx //是否有等待该队列的进程

105 je 3f

106 movl $0,(%ecx) //有的话,唤醒

107 3: popl %edx

108 popl %ecx

109 ret

put_queue会在相应键的处理过程中调用来把处理过的扫描码放到队列中



下面是跳转表中各键处理子程序

111 ctrl: movb $0x04,%al

112 jmp 1f

113 alt: movb $0x10,%al

114 1: cmpb $0,e0

115 je 2f

116 addb %al,%al

117 2: orb %al,mode

118 ret

119 unctrl: movb $0x04,%al

120 jmp 1f

121 unalt: movb $0x10,%al

122 1: cmpb $0,e0

123 je 2f

124 addb %al,%al

125 2: notb %al

126 andb %al,mode

127 ret

128

129 lshift:

130 orb $0x01,mode

131 ret

132 unlshift:

133 andb $0xfe,mode

134 ret

135 rshift:

136 orb $0x02,mode

137 ret

138 unrshift:

139 andb $0xfd,mode

140 ret

141

142 caps: testb $0x80,mode

143 jne 1f

144 xorb $4,leds

145 xorb $0x40,mode

146 orb $0x80,mode

147 set_leds:

148 call kb_wait

149 movb $0xed,%al /* set leds command */

150 outb %al,$0x60

151 call kb_wait

152 movb leds,%al

153 outb %al,$0x60

154 ret

155 uncaps: andb $0x7f,mode

156 ret

157 scroll:

158 xorb $1,leds

159 jmp set_leds

160 num: xorb $2,leds

161 jmp set_leds

162

163 /*

164 * curosr-key/numeric keypad cursor keys are handled here.

165 * checking for numeric keypad etc.

166 */

167 cursor:

168 subb $0x47,%al

169 jb 1f

170 cmpb $12,%al

171 ja 1f

172 jne cur2 /* check for ctrl-alt-del */

173 testb $0x0c,mode

174 je cur2

175 testb $0x30,mode

176 jne reboot

177 cur2: cmpb $0x01,e0 /* e0 forces cursor movement */

178 je cur

179 testb $0x02,leds /* not num-lock forces cursor */

180 je cur

181 testb $0x03,mode /* shift forces cursor */

182 jne cur

183 xorl %ebx,%ebx

184 movb num_table(%eax),%al

185 jmp put_queue

186 1: ret

187

188 cur: movb cur_table(%eax),%al

189 cmpb $'9,%al

190 ja ok_cur

191 movb $'~,%ah

192 ok_cur: shll $16,%eax

193 movw $0x5b1b,%ax

194 xorl %ebx,%ebx

195 jmp put_queue

196

197 #if defined(KBD_FR)

198 num_table:

199 .ascii "789 456 1230."

200 #else

201 num_table:

202 .ascii "789 456 1230,"

203 #endif

204 cur_table:

205 .ascii "HA5 DGC YB623"

206

207 /*

208 * this routine handles function keys 处理功能键

209 */

210 func:

211 pushl %eax

212 pushl %ecx

213 pushl %edx

214 call _show_stat

215 popl %edx

216 popl %ecx

217 popl %eax

218 subb $0x3B,%al

219 jb end_func

220 cmpb $9,%al

221 jbe ok_func

222 subb $18,%al

223 cmpb $10,%al

224 jb end_func

225 cmpb $11,%al

226 ja end_func

227 ok_func:

228 cmpl $4,%ecx /* check that there is enough room */

229 jl end_func

230 movl func_table(,%eax,4),%eax

231 xorl %ebx,%ebx

232 jmp put_queue

233 end_func:

234 ret

235

236 /*

237 * function keys send F1:'esc [ [ A' F2:'esc [ [ B' etc.

238 */

239 func_table:

240 .long 0x415b5b1b,0x425b5b1b,0x435b5b1b,0x445b5b1b

241 .long 0x455b5b1b,0x465b5b1b,0x475b5b1b,0x485b5b1b

242 .long 0x495b5b1b,0x4a5b5b1b,0x4b5b5b1b,0x4c5b5b1b

243

以下是扫描码与ASCII字符映射转换
KBD_FINNISH是include/linux/config.h中的键盘类型

244 #if defined(KBD_FINNISH)

245 key_map:

246 .byte 0,27

247 .ascii "1234567890+'"

248 .byte 127,9

249 .ascii "qwertyuiop}"

250 .byte 0,13,0

251 .ascii "asdfghjkl|{"

252 .byte 0,0

253 .ascii "'zxcvbnm,.-"

254 .byte 0,'*,0,32 /* 36-39 */

255 .fill 16,1,0 /* 3A-49 */

256 .byte '-,0,0,0,'+ /* 4A-4E */

257 .byte 0,0,0,0,0,0,0 /* 4F-55 */

258 .byte '<

259 .fill 10,1,0

260

261 shift_map:

262 .byte 0,27

263 .ascii "!\"#$%&/()=?`"

264 .byte 127,9

265 .ascii "QWERTYUIOP]^"

266 .byte 13,0

267 .ascii "ASDFGHJKL\\["

268 .byte 0,0

269 .ascii "*ZXCVBNM;:_"

270 .byte 0,'*,0,32 /* 36-39 */

271 .fill 16,1,0 /* 3A-49 */

272 .byte '-,0,0,0,'+ /* 4A-4E */

273 .byte 0,0,0,0,0,0,0 /* 4F-55 */

274 .byte '>

275 .fill 10,1,0

276

277 alt_map:

278 .byte 0,0

279 .ascii "\0@\0$\0\0{[]}\\\0"

280 .byte 0,0

281 .byte 0,0,0,0,0,0,0,0,0,0,0

282 .byte '~,13,0

283 .byte 0,0,0,0,0,0,0,0,0,0,0

284 .byte 0,0

285 .byte 0,0,0,0,0,0,0,0,0,0,0

286 .byte 0,0,0,0 /* 36-39 */

287 .fill 16,1,0 /* 3A-49 */

288 .byte 0,0,0,0,0 /* 4A-4E */

289 .byte 0,0,0,0,0,0,0 /* 4F-55 */

290 .byte '|

291 .fill 10,1,0

292

293 #elif defined(KBD_US)

294

295 key_map:

296 .byte 0,27

297 .ascii "1234567890-="

298 .byte 127,9

299 .ascii "qwertyuiop[]"

300 .byte 13,0

301 .ascii "asdfghjkl;'"

302 .byte '`,0

303 .ascii "\\zxcvbnm,./"

304 .byte 0,'*,0,32 /* 36-39 */

305 .fill 16,1,0 /* 3A-49 */

306 .byte '-,0,0,0,'+ /* 4A-4E */

307 .byte 0,0,0,0,0,0,0 /* 4F-55 */

308 .byte '<

309 .fill 10,1,0

310

311

312 shift_map:

313 .byte 0,27

314 .ascii "!@#$%^&*()_+"

315 .byte 127,9

316 .ascii "QWERTYUIOP{}"

317 .byte 13,0

318 .ascii "ASDFGHJKL:\""

319 .byte '~,0

320 .ascii "|ZXCVBNM<>?"

321 .byte 0,'*,0,32 /* 36-39 */

322 .fill 16,1,0 /* 3A-49 */

323 .byte '-,0,0,0,'+ /* 4A-4E */

324 .byte 0,0,0,0,0,0,0 /* 4F-55 */

325 .byte '>

326 .fill 10,1,0

327

328 alt_map:

329 .byte 0,0

330 .ascii "\0@\0$\0\0{[]}\\\0"

331 .byte 0,0

332 .byte 0,0,0,0,0,0,0,0,0,0,0

333 .byte '~,13,0

334 .byte 0,0,0,0,0,0,0,0,0,0,0

335 .byte 0,0

336 .byte 0,0,0,0,0,0,0,0,0,0,0

337 .byte 0,0,0,0 /* 36-39 */

338 .fill 16,1,0 /* 3A-49 */

339 .byte 0,0,0,0,0 /* 4A-4E */

340 .byte 0,0,0,0,0,0,0 /* 4F-55 */

341 .byte '|

342 .fill 10,1,0

343

344 #elif defined(KBD_GR)

345

346 key_map:

347 .byte 0,27

348 .ascii "1234567890\\'"

349 .byte 127,9

350 .ascii "qwertzuiop@+"

351 .byte 13,0

352 .ascii "asdfghjkl[]^"

353 .byte 0,'#

354 .ascii "yxcvbnm,.-"

355 .byte 0,'*,0,32 /* 36-39 */

356 .fill 16,1,0 /* 3A-49 */

357 .byte '-,0,0,0,'+ /* 4A-4E */

358 .byte 0,0,0,0,0,0,0 /* 4F-55 */

359 .byte '<

360 .fill 10,1,0

361

362

363 shift_map:

364 .byte 0,27

365 .ascii "!\"#$%&/()=?`"

366 .byte 127,9

367 .ascii "QWERTZUIOP\\*"

368 .byte 13,0

369 .ascii "ASDFGHJKL{}~"

370 .byte 0,''

371 .ascii "YXCVBNM;:_"

372 .byte 0,'*,0,32 /* 36-39 */

373 .fill 16,1,0 /* 3A-49 */

374 .byte '-,0,0,0,'+ /* 4A-4E */

375 .byte 0,0,0,0,0,0,0 /* 4F-55 */

376 .byte '>

377 .fill 10,1,0

378

379 alt_map:

380 .byte 0,0

381 .ascii "\0@\0$\0\0{[]}\\\0"

382 .byte 0,0

383 .byte '@,0,0,0,0,0,0,0,0,0,0

384 .byte '~,13,0

385 .byte 0,0,0,0,0,0,0,0,0,0,0

386 .byte 0,0

387 .byte 0,0,0,0,0,0,0,0,0,0,0

388 .byte 0,0,0,0 /* 36-39 */

389 .fill 16,1,0 /* 3A-49 */

390 .byte 0,0,0,0,0 /* 4A-4E */

391 .byte 0,0,0,0,0,0,0 /* 4F-55 */

392 .byte '|

393 .fill 10,1,0

394

395

396 #elif defined(KBD_FR)

397

398 key_map:

399 .byte 0,27

400 .ascii "&{\"'(-}_/@)="

401 .byte 127,9

402 .ascii "azertyuiop^$"

403 .byte 13,0

404 .ascii "qsdfghjklm|"

405 .byte '`,0,42 /* coin sup gauche, don't know, [*|mu] */

406 .ascii "wxcvbn,;:!"

407 .byte 0,'*,0,32 /* 36-39 */

408 .fill 16,1,0 /* 3A-49 */

409 .byte '-,0,0,0,'+ /* 4A-4E */

410 .byte 0,0,0,0,0,0,0 /* 4F-55 */

411 .byte '<

412 .fill 10,1,0

413

414 shift_map:

415 .byte 0,27

416 .ascii "1234567890]+"

417 .byte 127,9

418 .ascii "AZERTYUIOP<>"

419 .byte 13,0

420 .ascii "QSDFGHJKLM%"

421 .byte '~,0,'#

422 .ascii "WXCVBN?./\\"

423 .byte 0,'*,0,32 /* 36-39 */

424 .fill 16,1,0 /* 3A-49 */

425 .byte '-,0,0,0,'+ /* 4A-4E */

426 .byte 0,0,0,0,0,0,0 /* 4F-55 */

427 .byte '>

428 .fill 10,1,0

429

430 alt_map:

431 .byte 0,0

432 .ascii "\0~#{[|`\\^@]}"

433 .byte 0,0

434 .byte '@,0,0,0,0,0,0,0,0,0,0

435 .byte '~,13,0

436 .byte 0,0,0,0,0,0,0,0,0,0,0

437 .byte 0,0

438 .byte 0,0,0,0,0,0,0,0,0,0,0

439 .byte 0,0,0,0 /* 36-39 */

440 .fill 16,1,0 /* 3A-49 */

441 .byte 0,0,0,0,0 /* 4A-4E */

442 .byte 0,0,0,0,0,0,0 /* 4F-55 */

443 .byte '|

444 .fill 10,1,0

446 #else

447 #error "KBD-type not defined"

448 #endif

449 /*

450 * do_self handles "normal" keys, ie keys that don't change meaning

451 * and which have just one character returns.

452 */

453 do_self:

454 lea alt_map,%ebx

455 testb $0x20,mode /* alt-gr */

456 jne 1f

457 lea shift_map,%ebx

458 testb $0x03,mode

459 jne 1f

460 lea key_map,%ebx

461 1: movb (%ebx,%eax),%al

462 orb %al,%al

463 je none

464 testb $0x4c,mode /* ctrl or caps */

465 je 2f

466 cmpb $'a,%al

467 jb 2f

468 cmpb $'},%al

469 ja 2f

470 subb $32,%al

471 2: testb $0x0c,mode /* ctrl */

472 je 3f

473 cmpb $64,%al

474 jb 3f

475 cmpb $64+32,%al

476 jae 3f

477 subb $64,%al

478 3: testb $0x10,mode /* left alt */

479 je 4f

480 orb $0x80,%al

481 4: andl $0xff,%eax

482 xorl %ebx,%ebx

483 call put_queue

484 none: ret

486 /*

487 * minus has a routine of it's own, as a 'E0h' before

488 * the scan code for minus means that the numeric keypad

489 * slash was pushed.

490 */

491 minus: cmpb $1,e0

492 jne do_self

493 movl $'/,%eax

494 xorl %ebx,%ebx

495 jmp put_queue

497 /*

498 * This table decides which routine to call when a scan-code has been

499 * gotten. Most routines just call do_self, or none, depending if

500 * they are make or break.

501 */

502 key_table:

503 .long none,do_self,do_self,do_self /* 00-03 s0 esc 1 2 */

504 .long do_self,do_self,do_self,do_self /* 04-07 3 4 5 6 */

505 .long do_self,do_self,do_self,do_self /* 08-0B 7 8 9 0 */

506 .long do_self,do_self,do_self,do_self /* 0C-0F + ' bs tab */

507 .long do_self,do_self,do_self,do_self /* 10-13 q w e r */

508 .long do_self,do_self,do_self,do_self /* 14-17 t y u i */

509 .long do_self,do_self,do_self,do_self /* 18-1B o p } ^ */

510 .long do_self,ctrl,do_self,do_self /* 1C-1F enter ctrl a s */

511 .long do_self,do_self,do_self,do_self /* 20-23 d f g h */

512 .long do_self,do_self,do_self,do_self /* 24-27 j k l | */

513 .long do_self,do_self,lshift,do_self /* 28-2B { para lshift , */

514 .long do_self,do_self,do_self,do_self /* 2C-2F z x c v */

515 .long do_self,do_self,do_self,do_self /* 30-33 b n m , */

516 .long do_self,minus,rshift,do_self /* 34-37 . - rshift * */

517 .long alt,do_self,caps,func /* 38-3B alt sp caps f1 */

518 .long func,func,func,func /* 3C-3F f2 f3 f4 f5 */

519 .long func,func,func,func /* 40-43 f6 f7 f8 f9 */

520 .long func,num,scroll,cursor /* 44-47 f10 num scr home */

521 .long cursor,cursor,do_self,cursor /* 48-4B up pgup - left */

522 .long cursor,cursor,do_self,cursor /* 4C-4F n5 right + end */

523 .long cursor,cursor,cursor,cursor /* 50-53 dn pgdn ins del */

524 .long none,none,do_self,func /* 54-57 sysreq ? < f11 */

525 .long func,none,none,none /* 58-5B f12 ? ? ? */

526 .long none,none,none,none /* 5C-5F ? ? ? ? */

527 .long none,none,none,none /* 60-63 ? ? ? ? */

528 .long none,none,none,none /* 64-67 ? ? ? ? */

529 .long none,none,none,none /* 68-6B ? ? ? ? */

530 .long none,none,none,none /* 6C-6F ? ? ? ? */

531 .long none,none,none,none /* 70-73 ? ? ? ? */

532 .long none,none,none,none /* 74-77 ? ? ? ? */

533 .long none,none,none,none /* 78-7B ? ? ? ? */

534 .long none,none,none,none /* 7C-7F ? ? ? ? */

535 .long none,none,none,none /* 80-83 ? br br br */

536 .long none,none,none,none /* 84-87 br br br br */

537 .long none,none,none,none /* 88-8B br br br br */

538 .long none,none,none,none /* 8C-8F br br br br */

539 .long none,none,none,none /* 90-93 br br br br */

540 .long none,none,none,none /* 94-97 br br br br */

541 .long none,none,none,none /* 98-9B br br br br */

542 .long none,unctrl,none,none /* 9C-9F br unctrl br br */

543 .long none,none,none,none /* A0-A3 br br br br */

544 .long none,none,none,none /* A4-A7 br br br br */

545 .long none,none,unlshift,none /* A8-AB br br unlshift br */

546 .long none,none,none,none /* AC-AF br br br br */

547 .long none,none,none,none /* B0-B3 br br br br */

548 .long none,none,unrshift,none /* B4-B7 br br unrshift br */

549 .long unalt,none,uncaps,none /* B8-BB unalt br uncaps br */

550 .long none,none,none,none /* BC-BF br br br br */

551 .long none,none,none,none /* C0-C3 br br br br */

552 .long none,none,none,none /* C4-C7 br br br br */

553 .long none,none,none,none /* C8-CB br br br br */

554 .long none,none,none,none /* CC-CF br br br br */

555 .long none,none,none,none /* D0-D3 br br br br */

556 .long none,none,none,none /* D4-D7 br br br br */

557 .long none,none,none,none /* D8-DB br ? ? ? */

558 .long none,none,none,none /* DC-DF ? ? ? ? */

559 .long none,none,none,none /* E0-E3 e0 e1 ? ? */

560 .long none,none,none,none /* E4-E7 ? ? ? ? */

561 .long none,none,none,none /* E8-EB ? ? ? ? */

562 .long none,none,none,none /* EC-EF ? ? ? ? */

563 .long none,none,none,none /* F0-F3 ? ? ? ? */

564 .long none,none,none,none /* F4-F7 ? ? ? ? */

565 .long none,none,none,none /* F8-FB ? ? ? ? */

566 .long none,none,none,none /* FC-FF ? ? ? ? */

我们获取键盘扫描码后根据跳转表进行跳转

568 /*

569 * kb_wait waits for the keyboard controller buffer to empty.

570 * there is no timeout - if the buffer doesn't empty, we hang.

571 */

572 kb_wait:

573 pushl %eax

574 1: inb $0x64,%al

575 testb $0x02,%al

576 jne 1b

577 popl %eax

578 ret

579 /*

580 * This routine reboots the machine by asking the keyboard

581 * controller to pulse the reset-line low.

582 */

583 reboot:

584 call kb_wait

585 movw $0x1234,0x472 /* don't do memory check */

586 movb $0xfc,%al /* pulse reset and A20 low */

587 outb %al,$0x64

588 die: jmp die
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: