~ubuntu-branches/debian/stretch/grub2/stretch

« back to all changes in this revision

Viewing changes to term/serial.c

Tags: upstream-1.98+20100705
ImportĀ upstreamĀ versionĀ 1.98+20100705

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
#include <grub/extcmd.h>
28
28
#include <grub/i18n.h>
29
29
 
30
 
#define TEXT_WIDTH      80
31
 
#define TEXT_HEIGHT     24
32
 
 
33
 
static unsigned int xpos, ypos;
34
 
static unsigned int keep_track = 1;
35
30
static unsigned int registered = 0;
36
31
 
37
 
/* An input buffer.  */
38
 
static char input_buf[8];
39
 
static unsigned int npending = 0;
40
 
 
41
 
static struct grub_term_output grub_serial_term_output;
42
 
 
43
32
/* Argument options.  */
44
33
static const struct grub_arg_option options[] =
45
34
{
111
100
  grub_outb (c, serial_settings.port + UART_TX);
112
101
}
113
102
 
114
 
static void
115
 
serial_translate_key_sequence (void)
116
 
{
117
 
  unsigned int i;
118
 
  static struct
119
 
  {
120
 
    char key;
121
 
    char ascii;
122
 
  }
123
 
  three_code_table[] =
124
 
    {
125
 
      {'A', 16},
126
 
      {'B', 14},
127
 
      {'C', 6},
128
 
      {'D', 2},
129
 
      {'F', 5},
130
 
      {'H', 1},
131
 
      {'4', 4}
132
 
    };
133
 
 
134
 
  static struct
135
 
  {
136
 
      short key;
137
 
      char ascii;
138
 
  }
139
 
  four_code_table[] =
140
 
    {
141
 
      {('1' | ('~' << 8)), 1},
142
 
      {('3' | ('~' << 8)), 4},
143
 
      {('5' | ('~' << 8)), 7},
144
 
      {('6' | ('~' << 8)), 3}
145
 
    };
146
 
 
147
 
  if (npending < 3)
148
 
    return;
149
 
 
150
 
  /* The buffer must start with "ESC [".  */
151
 
  if (input_buf[0] != '\e' || input_buf[1] != '[')
152
 
    return;
153
 
 
154
 
  for (i = 0; i < ARRAY_SIZE (three_code_table); i++)
155
 
    if (three_code_table[i].key == input_buf[2])
156
 
      {
157
 
        input_buf[0] = three_code_table[i].ascii;
158
 
        npending -= 2;
159
 
        grub_memmove (input_buf + 1, input_buf + 3, npending - 1);
160
 
        return;
161
 
      }
162
 
 
163
 
  if (npending >= 4)
164
 
    {
165
 
      short key = input_buf[3] | (input_buf[4] << 8);
166
 
 
167
 
      for (i = 0; i < ARRAY_SIZE (four_code_table); i++)
168
 
        if (four_code_table[i].key == key)
169
 
          {
170
 
            input_buf[0] = four_code_table[i].ascii;
171
 
            npending -= 3;
172
 
            grub_memmove (input_buf + 1, input_buf + 4, npending - 1);
173
 
            return;
174
 
          }
175
 
    }
176
 
}
177
 
 
178
 
static int
179
 
fill_input_buf (const int nowait)
180
 
{
181
 
  int i;
182
 
 
183
 
  for (i = 0; i < 10000 && npending < sizeof (input_buf); i++)
184
 
    {
185
 
      int c;
186
 
 
187
 
      c = serial_hw_fetch ();
188
 
      if (c >= 0)
189
 
        {
190
 
          input_buf[npending++] = c;
191
 
 
192
 
          /* Reset the counter to zero, to wait for the same interval.  */
193
 
          i = 0;
194
 
        }
195
 
 
196
 
      if (nowait)
197
 
        break;
198
 
    }
199
 
 
200
 
  /* Translate some key sequences.  */
201
 
  serial_translate_key_sequence ();
202
 
 
203
 
  return npending;
204
 
}
205
 
 
206
103
/* Convert speed to divisor.  */
207
104
static unsigned short
208
105
serial_get_divisor (unsigned int speed)
241
138
  return 0;
242
139
}
243
140
 
244
 
/* The serial version of checkkey.  */
245
 
static int
246
 
grub_serial_checkkey (void)
247
 
{
248
 
  if (fill_input_buf (1))
249
 
    return input_buf[0];
250
 
  else
251
 
    return -1;
252
 
}
253
 
 
254
 
/* The serial version of getkey.  */
255
 
static int
256
 
grub_serial_getkey (void)
257
 
{
258
 
  int c;
259
 
 
260
 
  while (! fill_input_buf (0))
261
 
    ;
262
 
 
263
 
  c = input_buf[0];
264
 
  if (c == 0x7f)
265
 
    c = GRUB_TERM_BACKSPACE;
266
 
 
267
 
  grub_memmove (input_buf, input_buf + 1, --npending);
268
 
 
269
 
  return c;
270
 
}
271
 
 
272
141
/* Initialize a serial device. PORT is the port number for a serial device.
273
142
   SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600,
274
143
   19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used
300
169
  /* In Yeeloong serial port has only 3 wires.  */
301
170
#ifndef GRUB_MACHINE_MIPS_YEELOONG
302
171
  /* Enable the FIFO.  */
303
 
  grub_outb (UART_ENABLE_FIFO, serial_settings.port + UART_FCR);
 
172
  grub_outb (UART_ENABLE_FIFO_TRIGGER1, serial_settings.port + UART_FCR);
 
173
 
 
174
  /* Turn on DTR and RTS.  */
 
175
  grub_outb (UART_ENABLE_DTRRTS, serial_settings.port + UART_MCR);
 
176
#else
 
177
  /* Enable the FIFO.  */
 
178
  grub_outb (UART_ENABLE_FIFO_TRIGGER14, serial_settings.port + UART_FCR);
304
179
 
305
180
  /* Turn on DTR, RTS, and OUT2.  */
306
 
  grub_outb (UART_ENABLE_MODEM, serial_settings.port + UART_MCR);
 
181
  grub_outb (UART_ENABLE_DTRRTS | UART_ENABLE_OUT2,
 
182
             serial_settings.port + UART_MCR);
307
183
#endif
308
184
 
309
185
  /* Drain the input buffer.  */
310
 
  while (grub_serial_checkkey () != -1)
311
 
    (void) grub_serial_getkey ();
 
186
  while (serial_hw_fetch () != -1);
312
187
 
313
188
  /*  FIXME: should check if the serial terminal was found.  */
314
189
 
315
190
  return GRUB_ERR_NONE;
316
191
}
317
192
 
318
 
/* The serial version of putchar.  */
319
 
static void
320
 
grub_serial_putchar (grub_uint32_t c)
321
 
{
322
 
  /* Keep track of the cursor.  */
323
 
  if (keep_track)
324
 
    {
325
 
      /* The serial terminal does not have VGA fonts.  */
326
 
      if (c > 0x7F)
327
 
        {
328
 
          /* Better than nothing.  */
329
 
          switch (c)
330
 
            {
331
 
            case GRUB_TERM_DISP_LEFT:
332
 
              c = '<';
333
 
              break;
334
 
 
335
 
            case GRUB_TERM_DISP_UP:
336
 
              c = '^';
337
 
              break;
338
 
 
339
 
            case GRUB_TERM_DISP_RIGHT:
340
 
              c = '>';
341
 
              break;
342
 
 
343
 
            case GRUB_TERM_DISP_DOWN:
344
 
              c = 'v';
345
 
              break;
346
 
 
347
 
            case GRUB_TERM_DISP_HLINE:
348
 
              c = '-';
349
 
              break;
350
 
 
351
 
            case GRUB_TERM_DISP_VLINE:
352
 
              c = '|';
353
 
              break;
354
 
 
355
 
            case GRUB_TERM_DISP_UL:
356
 
            case GRUB_TERM_DISP_UR:
357
 
            case GRUB_TERM_DISP_LL:
358
 
            case GRUB_TERM_DISP_LR:
359
 
              c = '+';
360
 
              break;
361
 
 
362
 
            default:
363
 
              c = '?';
364
 
              break;
365
 
            }
366
 
        }
367
 
 
368
 
      switch (c)
369
 
        {
370
 
        case '\a':
371
 
          break;
372
 
 
373
 
        case '\b':
374
 
        case 127:
375
 
          if (xpos > 0)
376
 
            xpos--;
377
 
          break;
378
 
 
379
 
        case '\n':
380
 
          if (ypos < TEXT_HEIGHT - 1)
381
 
            ypos++;
382
 
          break;
383
 
 
384
 
        case '\r':
385
 
          xpos = 0;
386
 
          break;
387
 
 
388
 
        default:
389
 
          if (xpos >= TEXT_WIDTH)
390
 
            {
391
 
              grub_putchar ('\r');
392
 
              grub_putchar ('\n');
393
 
            }
394
 
          xpos++;
395
 
          break;
396
 
        }
397
 
    }
398
 
 
399
 
  serial_hw_put (c);
400
 
}
401
 
 
402
 
static grub_ssize_t
403
 
grub_serial_getcharwidth (grub_uint32_t c __attribute__ ((unused)))
404
 
{
405
 
  return 1;
406
 
}
407
 
 
408
193
static grub_uint16_t
409
 
grub_serial_getwh (void)
 
194
grub_serial_getwh (struct grub_term_output *term __attribute__ ((unused)))
410
195
{
 
196
  const grub_uint8_t TEXT_WIDTH = 80;
 
197
  const grub_uint8_t TEXT_HEIGHT = 24;
411
198
  return (TEXT_WIDTH << 8) | TEXT_HEIGHT;
412
199
}
413
200
 
414
 
static grub_uint16_t
415
 
grub_serial_getxy (void)
416
 
{
417
 
  return ((xpos << 8) | ypos);
418
 
}
419
 
 
420
 
static void
421
 
grub_serial_gotoxy (grub_uint8_t x, grub_uint8_t y)
422
 
{
423
 
  if (x > TEXT_WIDTH || y > TEXT_HEIGHT)
424
 
    {
425
 
      grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)", x, y);
426
 
    }
427
 
  else
428
 
    {
429
 
      keep_track = 0;
430
 
      grub_terminfo_gotoxy (x, y, &grub_serial_term_output);
431
 
      keep_track = 1;
432
 
 
433
 
      xpos = x;
434
 
      ypos = y;
435
 
    }
436
 
}
437
 
 
438
 
static void
439
 
grub_serial_cls (void)
440
 
{
441
 
  keep_track = 0;
442
 
  grub_terminfo_cls (&grub_serial_term_output);
443
 
  keep_track = 1;
444
 
 
445
 
  xpos = ypos = 0;
446
 
}
447
 
 
448
 
static void
449
 
grub_serial_setcolorstate (const grub_term_color_state state)
450
 
{
451
 
  keep_track = 0;
452
 
  switch (state)
453
 
    {
454
 
    case GRUB_TERM_COLOR_STANDARD:
455
 
    case GRUB_TERM_COLOR_NORMAL:
456
 
      grub_terminfo_reverse_video_off (&grub_serial_term_output);
457
 
      break;
458
 
    case GRUB_TERM_COLOR_HIGHLIGHT:
459
 
      grub_terminfo_reverse_video_on (&grub_serial_term_output);
460
 
      break;
461
 
    default:
462
 
      break;
463
 
    }
464
 
  keep_track = 1;
465
 
}
466
 
 
467
 
static void
468
 
grub_serial_setcursor (const int on)
469
 
{
470
 
  if (on)
471
 
    grub_terminfo_cursor_on (&grub_serial_term_output);
472
 
  else
473
 
    grub_terminfo_cursor_off (&grub_serial_term_output);
474
 
}
 
201
struct grub_terminfo_input_state grub_serial_terminfo_input =
 
202
  {
 
203
    .readkey = serial_hw_fetch
 
204
  };
 
205
 
 
206
struct grub_terminfo_output_state grub_serial_terminfo_output =
 
207
  {
 
208
    .put = serial_hw_put
 
209
  };
475
210
 
476
211
static struct grub_term_input grub_serial_term_input =
477
212
{
478
213
  .name = "serial",
479
 
  .checkkey = grub_serial_checkkey,
480
 
  .getkey = grub_serial_getkey,
 
214
  .init = grub_terminfo_input_init,
 
215
  .checkkey = grub_terminfo_checkkey,
 
216
  .getkey = grub_terminfo_getkey,
 
217
  .data = &grub_serial_terminfo_input
481
218
};
482
219
 
483
220
static struct grub_term_output grub_serial_term_output =
484
221
{
485
222
  .name = "serial",
486
 
  .putchar = grub_serial_putchar,
487
 
  .getcharwidth = grub_serial_getcharwidth,
 
223
  .putchar = grub_terminfo_putchar,
488
224
  .getwh = grub_serial_getwh,
489
 
  .getxy = grub_serial_getxy,
490
 
  .gotoxy = grub_serial_gotoxy,
491
 
  .cls = grub_serial_cls,
492
 
  .setcolorstate = grub_serial_setcolorstate,
493
 
  .setcursor = grub_serial_setcursor,
494
 
  .flags = 0,
 
225
  .getxy = grub_terminfo_getxy,
 
226
  .gotoxy = grub_terminfo_gotoxy,
 
227
  .cls = grub_terminfo_cls,
 
228
  .setcolorstate = grub_terminfo_setcolorstate,
 
229
  .setcursor = grub_terminfo_setcursor,
 
230
  .flags = GRUB_TERM_CODE_TYPE_ASCII,
 
231
  .data = &grub_serial_terminfo_output,
 
232
  .normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR,
 
233
  .highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR,
495
234
};
496
235
 
497
236
 
586
325
        {
587
326
          grub_term_register_input ("serial", &grub_serial_term_input);
588
327
          grub_term_register_output ("serial", &grub_serial_term_output);
 
328
          grub_terminfo_output_register (&grub_serial_term_output, "vt100");
589
329
          registered = 1;
590
330
        }
591
331
    }
602
342
              /* If unable to restore settings, unregister terminal.  */
603
343
              grub_term_unregister_input (&grub_serial_term_input);
604
344
              grub_term_unregister_output (&grub_serial_term_output);
 
345
              grub_terminfo_output_unregister (&grub_serial_term_output);
605
346
              registered = 0;
606
347
            }
607
348
        }
629
370
  serial_settings.word_len  = UART_8BITS_WORD;
630
371
  serial_settings.parity    = UART_NO_PARITY;
631
372
  serial_settings.stop_bits = UART_1_STOP_BIT;
 
373
 
 
374
#ifdef GRUB_MACHINE_MIPS_YEELOONG
 
375
  {
 
376
    grub_err_t hwiniterr;
 
377
    hwiniterr = serial_hw_init ();
 
378
 
 
379
    if (hwiniterr == GRUB_ERR_NONE)
 
380
      {
 
381
        grub_term_register_input_active ("serial", &grub_serial_term_input);
 
382
        grub_term_register_output_active ("serial", &grub_serial_term_output);
 
383
 
 
384
        registered = 1;
 
385
      }
 
386
  }
 
387
#endif
632
388
}
633
389
 
634
390
GRUB_MOD_FINI(serial)
638
394
    {
639
395
      grub_term_unregister_input (&grub_serial_term_input);
640
396
      grub_term_unregister_output (&grub_serial_term_output);
 
397
      grub_terminfo_output_unregister (&grub_serial_term_output);
641
398
    }
642
399
}