⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial.c

📁 Linux启动程序grub的源码分析与实现;
💻 C
字号:
/* serial.c - serial device interface *//* *  GRUB  --  GRand Unified Bootloader *  Copyright (C) 2000,2001,2002  Free Software Foundation, Inc. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#ifdef SUPPORT_SERIAL#include <shared.h>#include <serial.h>#include <term.h>#include <terminfo.h>/* An input buffer.  */static char input_buf[8];static int npending = 0;static int serial_x;static int serial_y;static int keep_track = 1;/* Hardware-dependent definitions.  */#ifndef GRUB_UTIL/* The structure for speed vs. divisor.  */struct divisor{  int speed;  unsigned short div;};/* Store the port number of a serial unit.  */static unsigned short serial_hw_port = 0;/* The table which lists common configurations.  */static struct divisor divisor_tab[] =  {    { 2400,   0x0030 },    { 4800,   0x0018 },    { 9600,   0x000C },    { 19200,  0x0006 },    { 38400,  0x0003 },    { 57600,  0x0002 },    { 115200, 0x0001 }  };/* Read a byte from a port.  */static inline unsigned charinb (unsigned short port){  unsigned char value;  asm volatile ("inb	%w1, %0" : "=a" (value) : "Nd" (port));  asm volatile ("outb	%%al, $0x80" : : );    return value;}/* Write a byte to a port.  */static inline voidoutb (unsigned short port, unsigned char value){  asm volatile ("outb	%b0, %w1" : : "a" (value), "Nd" (port));  asm volatile ("outb	%%al, $0x80" : : );}/* Fetch a key.  */intserial_hw_fetch (void){  if (inb (serial_hw_port + UART_LSR) & UART_DATA_READY)    return inb (serial_hw_port + UART_RX);  return -1;}/* Put a chararacter.  */voidserial_hw_put (int c){  int timeout = 100000;  /* Wait until the transmitter holding register is empty.  */  while ((inb (serial_hw_port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0)    {      if (--timeout == 0)	/* There is something wrong. But what can I do?  */	return;    }  outb (serial_hw_port + UART_TX, c);}voidserial_hw_delay (void){  outb (0x80, 0);}/* Return the port number for the UNITth serial device.  */unsigned shortserial_hw_get_port (int unit){  /* The BIOS data area.  */  const unsigned short *addr = (const unsigned short *) 0x0400;    return addr[unit];}/* Initialize a serial device. PORT is the port number for a serial device.   SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600,   19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used   for the device. Likewise, PARITY is the type of the parity and   STOP_BIT_LEN is the length of the stop bit. The possible values for   WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as   macros.  */intserial_hw_init (unsigned short port, unsigned int speed,		int word_len, int parity, int stop_bit_len){  int i;  unsigned short div = 0;  unsigned char status = 0;    /* Turn off the interrupt.  */  outb (port + UART_IER, 0);  /* Set DLAB.  */  outb (port + UART_LCR, UART_DLAB);    /* Set the baud rate.  */  for (i = 0; i < sizeof (divisor_tab) / sizeof (divisor_tab[0]); i++)    if (divisor_tab[i].speed == speed)      {	div = divisor_tab[i].div;	break;      }    if (div == 0)    return 0;    outb (port + UART_DLL, div & 0xFF);  outb (port + UART_DLH, div >> 8);    /* Set the line status.  */  status |= parity | word_len | stop_bit_len;  outb (port + UART_LCR, status);  /* Enable the FIFO.  */  outb (port + UART_FCR, UART_ENABLE_FIFO);  /* Turn on DTR, RTS, and OUT2.  */  outb (port + UART_MCR, UART_ENABLE_MODEM);  /* Store the port number.  */  serial_hw_port = port;    /* Drain the input buffer.  */  while (serial_checkkey () != -1)    (void) serial_getkey ();  /* Get rid of TERM_NEED_INIT from the serial terminal.  */  for (i = 0; term_table[i].name; i++)    if (grub_strcmp (term_table[i].name, "serial") == 0)      {	term_table[i].flags &= ~TERM_NEED_INIT;	break;      }  /* FIXME: should check if the serial terminal was found.  */    return 1;}#endif /* ! GRUB_UTIL *//* Generic definitions.  */static voidserial_translate_key_sequence (void){  const struct  {    char key;    char ascii;  }  three_code_table[] =    {      {'A', 16},      {'B', 14},      {'C', 6},      {'D', 2},      {'F', 5},      {'H', 1},      {'4', 4}    };  const struct  {    short key;    char ascii;  }  four_code_table[] =    {      {('1' | ('~' << 8)), 1},      {('3' | ('~' << 8)), 4},      {('5' | ('~' << 8)), 7},      {('6' | ('~' << 8)), 3},    };    /* The buffer must start with ``ESC [''.  */  if (*((unsigned short *) input_buf) != ('\e' | ('[' << 8)))    return;    if (npending >= 3)    {      int i;      for (i = 0;	   i < sizeof (three_code_table) / sizeof (three_code_table[0]);	   i++)	if (three_code_table[i].key == input_buf[2])	  {	    input_buf[0] = three_code_table[i].ascii;	    npending -= 2;	    grub_memmove (input_buf + 1, input_buf + 3, npending - 1);	    return;	  }    }  if (npending >= 4)    {      int i;      short key = *((short *) (input_buf + 2));      for (i = 0;	   i < sizeof (four_code_table) / sizeof (four_code_table[0]);	   i++)	if (four_code_table[i].key == key)	  {	    input_buf[0] = four_code_table[i].ascii;	    npending -= 3;	    grub_memmove (input_buf + 1, input_buf + 4, npending - 1);	    return;	  }    }}    staticint fill_input_buf (int nowait){  int i;  for (i = 0; i < 10000 && npending < sizeof (input_buf); i++)    {      int c;      c = serial_hw_fetch ();      if (c >= 0)	{	  input_buf[npending++] = c;	  /* Reset the counter to zero, to wait for the same interval.  */	  i = 0;	}            if (nowait)	break;    }  /* Translate some key sequences.  */  serial_translate_key_sequence ();	    return npending;}/* The serial version of getkey.  */intserial_getkey (void){  int c;    while (! fill_input_buf (0))    ;  c = input_buf[0];  npending--;  grub_memmove (input_buf, input_buf + 1, npending);    return c;}/* The serial version of checkkey.  */intserial_checkkey (void){  if (fill_input_buf (1))    return input_buf[0];  return -1;}/* The serial version of grub_putchar.  */voidserial_putchar (int c){  /* Keep track of the cursor.  */  if (keep_track)    {      /* The serial terminal doesn't have VGA fonts.  */      switch (c)	{	case DISP_UL:	  c = ACS_ULCORNER;	  break;	case DISP_UR:	  c = ACS_URCORNER;	  break;	case DISP_LL:	  c = ACS_LLCORNER;	  break;	case DISP_LR:	  c = ACS_LRCORNER;	  break;	case DISP_HORIZ:	  c = ACS_HLINE;	  break;	case DISP_VERT:	  c = ACS_VLINE;	  break;	case DISP_LEFT:	  c = ACS_LARROW;	  break;	case DISP_RIGHT:	  c = ACS_RARROW;	  break;	case DISP_UP:	  c = ACS_UARROW;	  break;	case DISP_DOWN:	  c = ACS_DARROW;	  break;	default:	  break;	}            switch (c)	{	case '\r':	  serial_x = 0;	  break;	  	case '\n':	  serial_y++;	  break;	  	case '\b':	case 127:	  if (serial_x > 0)	    serial_x--;	  break;	  	case '\a':	  break;	  	default:	  if (serial_x >= 79)	    {	      serial_putchar ('\r');	      serial_putchar ('\n');	    }	  serial_x++;	  break;	}    }    serial_hw_put (c);}intserial_getxy (void){  return (serial_x << 8) | serial_y;}voidserial_gotoxy (int x, int y){  keep_track = 0;  ti_cursor_address (x, y);  keep_track = 1;    serial_x = x;  serial_y = y;}voidserial_cls (void){  keep_track = 0;  ti_clear_screen ();  keep_track = 1;    serial_x = serial_y = 0;}voidserial_setcolorstate (color_state state){  keep_track = 0;  if (state == COLOR_STATE_HIGHLIGHT)    ti_enter_standout_mode ();  else    ti_exit_standout_mode ();  keep_track = 1;}#endif /* SUPPORT_SERIAL */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -