OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [bootloaders/] [orpmon/] [cmds/] [atabug.c] - Blame information for rev 354

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 marcus.erl
/*
2
    atabug.c -- ATA debugging
3
    Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
4
 
5
    This file is part of OpenRISC 1000 Reference Platform Monitor (ORPmon)
6
 
7
    This program is free software; you can redistribute it and/or modify
8
    it under the terms of the GNU General Public License as published by
9
    the Free Software Foundation; either version 2 of the License, or
10
    (at your option) any later version
11
 
12
    This program is distributed in the hope that it will be useful,
13
    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
    GNU General Public License for more details.
16
 
17
    You should have received a copy of the GNU General Public License
18
    along with this program; if not, write to the Free Software
19
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
*/
21
 
22
 
23
#include "support.h"
24
#include "common.h"
25
#include "atabug.h"
26
#include "ata.h"
27
 
28
#include <ctype.h>
29
 
30
static int ata_num_commands;
31
static command_struct ata_command[MAX_ATA_COMMANDS];
32
 
33
/* inode struct for ata */
34
static struct inode _inode;
35
static struct inode *inode = &_inode;
36
 
37
/* file struct for ata */
38
static struct file _filp;
39
static struct file *filp = &_filp;
40
 
41
/* buffer for ata-data */
42
static unsigned char buf[512];
43
 
44
 
45
/**********************************************************************/
46
/*                                                                    */
47
/*      A T A B U G                                                   */
48
/*                                                                    */
49
/**********************************************************************/
50
/*
51
        A T A _ I N I T
52
 
53
        initializes the ATA core, and registers it with ORPmon
54
*/
55
void module_ata_init (void)
56
{
57
  ata_num_commands = 0;
58
 
59
  register_command ("atabug", "", "ATA debugger. Type 'atabug help' for help", atabug);
60
 
61
  register_ata_command ("help", "", "Display this help message", atabug_help);
62
  register_ata_command ("exit", "", "Exit atabug and return to ORPmon", atabug_exit);
63
  register_ata_command ("open", "<device> [<mode>]", "Opens the requested device. Device=<0|1>, Mode=<r>eadonly|read<w>rite.", ata_open_cmd);
64
  register_ata_command ("close", "", "Closes the device.", ata_close_cmd);
65
  register_ata_command ("reset", "<mode>", "Reset ata device(s).", ata_reset_cmd);
66
  register_ata_command ("enable", "", "Enables ATA host controller, clears all resets", ata_enable_cmd);
67
  register_ata_command ("dump_dev_regs", "", "Dump the (readable) ata device registers.", ata_dump_device_regs_cmd);
68
  register_ata_command ("dump_host_regs", "", "Dump the ata host registers.", ata_dump_host_regs_cmd);
69
  register_ata_command ("exec_cmd", "<cmd>", "Execute ata command <cmd> (hex)", ata_exec_cmd_cmd);
70
  register_ata_command ("identify_device", "", "Dumps device's IDENTIFY DEVICE block.", ata_identify_device_cmd);
71
  register_ata_command ("program_timing", "<PIO mode>", "Programs the device to the selected PIO mode.", ata_set_piomode_cmd);
72
  register_ata_command ("read_sectors", "<startsector> [<sectorcount>]", "Reads sector", ata_read_sectors_cmd);
73
  register_ata_command ("read_mbr", "<partition>", "Reads the Master Boot Record.", ata_read_mbr_cmd);
74
  register_ata_command ("read_dosboot", "<sector>", "Reads the device's bootsector (FAT).", ata_read_dosboot_cmd);
75
  register_ata_command ("select_device", "<device_no>", "Select ata device. device_no=<0|1>", ata_select_device_cmd);
76
}
77
 
78
 
79
int atabug(int argc, char **argv)
80
{
81
 
82
  /* take care of commandline options                                 */
83
  if (argc == 0)
84
  {
85
    /* start atabug                                                   */
86
    while ( !ata_mon_command() );
87
  }
88
  else
89
    return execute_ata_command(argv[0], argc -1, &argv[1]);
90
 
91
  return 0;
92
}
93
 
94
int atabug_exit(int argc, char **argv)
95
{
96
  ata_close_cmd(argc, argv);
97
  return -2;
98
}
99
 
100
/*
101
 The next code is graceously taken from the "common.c" file
102
 and slightly modified to suit the big list of ATA commands
103
 
104
 Better would be if we could access the routines in 'common.c'
105
 directly, using our own set of commands.
106
*/
107
 
108
/* Process command-line, generate arguments */
109
int ata_mon_command(void)
110
{
111
  char c = '\0';
112
  char str[1000];
113
  char *pstr = str;
114
  char *command_str;
115
  char *argv[20];
116
  int argc = 0;
117
 
118
 
119
  /* Show prompt */
120
  printf ("\natabug> ");
121
 
122
 
123
  /* Get characters from UART */
124
  c = getc();
125
  while (c != '\r' && c != '\f' && c != '\n')
126
  {
127
    if (c == '\b')
128
      pstr--;
129
    else
130
      *pstr++ = c;
131
    putc(c);
132
    c = getc();
133
  }
134
  *pstr = '\0';
135
  printf ("\n");
136
 
137
  /* Skip leading blanks */
138
  pstr = str;
139
  while ( isspace(*pstr) ) pstr++;
140
 
141
  /* Get command from the string */
142
  command_str = pstr;
143
 
144
  while (1) {
145
    /* Go to next argument */
146
    while ( isgraph(*pstr) ) pstr++;
147
    if (*pstr) {
148
      *pstr++ = '\0';
149
      while ( isspace(*pstr) ) pstr++;
150
      argv[argc++] = pstr;
151
    }
152
    else
153
      break;
154
  }
155
 
156
  return execute_ata_command(command_str, argc, argv);
157
}
158
 
159
 
160
int execute_ata_command(char *command_str, int argc, char **argv)
161
{
162
  int i, found = 0;
163
 
164
  for (i = 0; i < ata_num_commands; i++)
165
    if ( !strcmp(command_str, ata_command[i].name) )
166
    {
167
      switch ( ata_command[i].func(argc, argv) )
168
      {
169
        case -1:
170
          printf ("Missing/wrong parameters, usage: %s %s\n", ata_command[i].name, ata_command[i].params);
171
          break;
172
 
173
        case -2:
174
          return -1;
175
      }
176
 
177
      found++;
178
      break;
179
    }
180
 
181
    if (!found)
182
      printf ("Unknown command. Type 'ata help' for help.\n");
183
 
184
  return 0;
185
}
186
 
187
 
188
void register_ata_command (const char *name, const char *params, const char *help, int (*func)(int argc, char *argv[]) )
189
{
190
  if (ata_num_commands < MAX_ATA_COMMANDS)
191
  {
192
    ata_command[ata_num_commands].name = name;
193
    ata_command[ata_num_commands].params = params;
194
    ata_command[ata_num_commands].help = help;
195
    ata_command[ata_num_commands].func = func;
196
    ata_num_commands++;
197
  }
198
  else
199
    printf ("ata-command '%s' ignored; MAX_COMMANDS limit reached\n", name);
200
}
201
 
202
int atabug_help(int argc, char **argv)
203
{
204
  int i;
205
 
206
  for (i = 0; i < ata_num_commands; i++)
207
    printf ("%-15s %-17s -%s\n", ata_command[i].name, ata_command[i].params, ata_command[i].help);
208
 
209
  return 0;
210
}
211
 
212
 
213
 
214
 
215
/**********************************************************************/
216
/*                                                                    */
217
/*      A T A B U G   C O M M A N D S E T                             */
218
/*                                                                    */
219
/**********************************************************************/
220
 
221
/*
222
        A T A _ C L O S E
223
 
224
        closes the ata_device
225
*/
226
int ata_close_cmd(int argc, char **argv)
227
{
228
    inode->i_rdev = (ATA_BASE_ADDR >> 16) | (*argv[0] - '0');
229
 
230
    return ata_release(inode, filp);
231
}
232
 
233
 
234
/*
235
        A T A _ D U M P _ D E V I C E _ R E G S
236
 
237
        Dumps the (readable) ata-registers.
238
        Exception: status register is not read, this could mask an interrupt
239
*/
240
int ata_dump_device_regs_cmd(int argc, char **argv)
241
{
242
    if (argc)
243
      printf("\nWARNING: Ignoring invalid argument(s)\n\n");
244
 
245
 
246
    printf("Alternate status register : 0x%02lX\n", REG32(ATA_BASE_ADDR + ATA_ASR) );
247
    printf("Cylinder high register    : 0x%02lX\n", REG32(ATA_BASE_ADDR + ATA_CHR) );
248
    printf("Cylinder low register     : 0x%02lX\n", REG32(ATA_BASE_ADDR + ATA_CLR) );
249
    printf("Device head register      : 0x%02lX\n", REG32(ATA_BASE_ADDR + ATA_DHR) );
250
    printf("Error register            : 0x%02lX\n", REG32(ATA_BASE_ADDR + ATA_ERR) );
251
    printf("Sector count register     : 0x%02lX\n", REG32(ATA_BASE_ADDR + ATA_SCR) );
252
    printf("Sector number register    : 0x%02lX\n", REG32(ATA_BASE_ADDR + ATA_SNR) );
253
    printf("Status register (see alternate status register)\n" );
254
 
255
    return 0;
256
}
257
 
258
 
259
/*
260
        A T A _ D U M P _ H O S T _ R E G S
261
 
262
        Dumps the ata-host registers
263
*/
264
int ata_dump_host_regs_cmd(int argc, char **argv)
265
{
266
    if (argc)
267
      printf("\nWARNING: Ignoring invalid argument(s)\n\n");
268
 
269
 
270
    printf("Control register                   CTRL : 0x%08lX\n", REG32(ATA_BASE_ADDR + ATA_CTRL) );
271
    printf("Status register                    STAT : 0x%08lX\n", REG32(ATA_BASE_ADDR + ATA_STAT) );
272
    printf("Pio command timing register        PCTR : 0x%08lX\n", REG32(ATA_BASE_ADDR + ATA_PCTR) );
273
    printf("Pio fast timing register (device0) PFTR0: 0x%08lX\n", REG32(ATA_BASE_ADDR + ATA_PFTR0) );
274
    printf("Pio fast timing register (device1) PFTR1: 0x%08lX\n", REG32(ATA_BASE_ADDR + ATA_PFTR1) );
275
    printf("Dma timing register (device0)      DTR0 : 0x%08lX\n", REG32(ATA_BASE_ADDR + ATA_DTR0) );
276
    printf("Dma timing register (device1)      DTR1 : 0x%08lX\n", REG32(ATA_BASE_ADDR + ATA_DTR1) );
277
 
278
    return 0;
279
}
280
 
281
 
282
/*
283
        A T A _ E N A B L E
284
 
285
        clears reset bits
286
*/
287
int ata_enable_cmd(int argc, char **argv)
288
{
289
    if (argc != 0)
290
        printf("Ignoring invalid parameters\n");
291
 
292
    inode->i_rdev = (ATA_BASE_ADDR >> 16);
293
 
294
    // clear hardware reset bit
295
    if ( ata_ioctl(inode, filp, ATA_IOCTL_SET_RST, CLR | ARG_HW_RST) )
296
      return -1;
297
 
298
    // clear software reset bit
299
    if ( ata_ioctl(inode, filp, ATA_IOCTL_SET_RST, CLR | ARG_SW_RST) )
300
      return -1;
301
 
302
    // enable ATA Hostcontroller core
303
    if ( ata_ioctl(inode, filp, ATA_IOCTL_ENABLE_HOST, 0) )
304
      return -1;
305
 
306
    printf("ATA host controller enabled\n");
307
 
308
    return 0;
309
}
310
 
311
 
312
/*
313
        A T A _ E X E C _ C M D
314
 
315
        Executes the command; writes the command number in the command register
316
*/
317
int ata_exec_cmd_cmd(int argc, char **argv)
318
{
319
    if (argc != 1)
320
        return -1;
321
 
322
    inode->i_rdev = (ATA_BASE_ADDR >> 16);
323
 
324
    ata_ioctl(inode, filp, ATA_IOCTL_EXEC_CMD, strtoul(*argv, argv, 16) );
325
    return 0;
326
}
327
 
328
 
329
/*
330
        A T A _ I D E N T I F Y _ D E V I C E
331
 
332
        Reads the identify_device block and dumps it to the screen
333
*/
334
int ata_identify_device_cmd(int argc, char **argv)
335
{
336
    unsigned char checksum;
337
 
338
    if (argc != 0)
339
        printf("Ignoring invalid parameters\n");
340
 
341
 
342
    /* check for busy flag                                            */
343
    if ( ata_dev_busy(ATA_BASE_ADDR) )
344
        printf("Selected ata device busy, ignoring command\n");
345
    else
346
    {
347
        /* execute identify device                                    */
348
        ata_ioctl(inode, filp, ATA_IOCTL_EXEC_CMD, IDENTIFY_DEVICE);
349
 
350
        /* read block from ata-device                                 */
351
        buf[0] = 0;
352
        buf[1] = 1;
353
        ata_ioctl(inode, filp, ATA_IOCTL_READ, (unsigned long) buf);
354
 
355
        /* dump data to the screen                                    */
356
        checksum = atabug_dump_data(buf, 512);
357
 
358
        if (buf[512] == 0xa5)
359
            printf("Checksum = 0x%02X (%s)\n", checksum, checksum ? "error" : "OK");
360
        else
361
            printf("No checksum supported\n");
362
    }
363
    return 0;
364
}
365
 
366
 
367
/*
368
        A T A _ O P E N
369
 
370
        opens the ata_device
371
*/
372
int ata_open_cmd(int argc, char **argv)
373
{
374
    inode->i_rdev = (ATA_BASE_ADDR >> 16) | (*argv[0] - '0');
375
 
376
    filp->f_mode = FMODE_READ;
377
 
378
    if (*argv[1] == 'w')
379
      filp->f_mode |= FMODE_WRITE;
380
 
381
    switch( ata_open(inode, filp) ) {
382
      case EOPENIDEV:
383
        printf( "Error: Invalid device (invalid MINOR %02X)\n", MINOR(inode->i_rdev) );
384
        break;
385
 
386
      case EOPENNODEV:
387
        printf( "Error: Requested device not found\n" );
388
        break;
389
 
390
      case EOPENIHOST:
391
        printf( "Error: Invalid host (invalid MAJOR %02X)\n", MAJOR(inode->i_rdev) );
392
      default:
393
        break;
394
    }
395
 
396
    return 0;
397
}
398
 
399
 
400
/*
401
        A T A _ S E T _ P I O M O D E
402
 
403
        Sets the device to the requested PIO mode
404
*/
405
int ata_set_piomode_cmd(int argc, char **argv)
406
{
407
    return 0;
408
}
409
 
410
 
411
/*
412
        A T A _ R E A D _ S E C T O R S
413
 
414
        Reads 1 sector from the device and dumps it to the screen
415
*/
416
int ata_read_sectors_cmd(int argc, char **argv)
417
{
418
    struct request request;
419
    unsigned long sector_cnt, sector;
420
 
421
    sector = strtoul(argv[0], argv, 10);
422
 
423
    switch (argc) {
424
      case 2:
425
        sector_cnt = strtoul(argv[1], argv, 10);
426
        break;
427
 
428
      case 1:
429
        sector_cnt = 1;
430
        break;
431
 
432
      default:
433
        return -1;
434
    }
435
 
436
    if ( !sector_cnt )
437
    {
438
      printf( "Invalid number of sectors.\n" );
439
      return 0;
440
    }
441
 
442
    /* check for busy flag                                            */
443
    if ( ata_dev_busy(ATA_BASE_ADDR) )
444
        printf("Selected ata device busy, ignoring command\n");
445
    else
446
    {
447
        /* fill the request structure                                 */
448
        request.cmd = READ;
449
        request.sector = sector;
450
        request.nr_sectors = sector_cnt;
451
        request.buffer = buf;
452
 
453
        if ( ata_request(inode, filp, &request) )
454
        {
455
            printf("Error while executing READ_SECTOR(S) command\n");
456
            printf("Status register = 0x%02lX, error register = 0x%02lX\n", ata_astatus(ATA_BASE_ADDR), ata_error(ATA_BASE_ADDR) );
457
        }
458
        else
459
        {
460
            /* dump data to the screen                                    */
461
            atabug_dump_data(buf, 512 * sector_cnt);
462
        }
463
    }
464
    return 0;
465
}
466
 
467
 
468
/*
469
        A T A _ R E A D _ M B R
470
 
471
        Reads master boot record from the device and dumps it's contents to the screen
472
*/
473
int ata_read_mbr_cmd(int argc, char **argv)
474
{
475
    struct request request;
476
    unsigned int partition;
477
 
478
    // get requested partition number
479
    partition = 0;
480
    if (argc)
481
        partition = strtoul(*argv, argv, 10);
482
 
483
    /* check for busy flag                                            */
484
    if ( ata_dev_busy(ATA_BASE_ADDR) )
485
        printf("Selected ata device busy, ignoring command\n");
486
    else
487
    {
488
        /* fill the request structure                                 */
489
        request.cmd = READ;
490
        request.sector = 0;
491
        request.nr_sectors = 1;
492
        request.buffer = buf;
493
 
494
        if ( ata_request(inode, filp, &request) )
495
        {
496
            printf("Error while reading master boot sector.\n");
497
            printf("Status register = 0x%02lX, error register = 0x%02lX\n", ata_astatus(ATA_BASE_ADDR), ata_error(ATA_BASE_ADDR) );
498
        }
499
        else
500
        {
501
          printf( "Skipping bootloader (446bytes)\n" );
502
          printf( "Partition %1d:\n", partition);
503
 
504
          // abuse partitionnumber to get offset in MBR record
505
          partition *= 16;
506
          partition += 446;
507
 
508
          printf( "Bootindicator: 0x%2X (%s)\n", buf[partition], buf[partition] ? "bootable" : "non-bootable");
509
          printf( "Partition start (head: 0x%02X cyl: 0x%03X sect: 0x%02X)\n",
510
              buf[partition +1], (buf[partition +2] & 0xc0) << 2 | buf[partition +3] ,buf[partition +2] & 0x3f );
511
          printf( "Systemindicator: 0x%02X (", buf[partition +4]);
512
 
513
          switch (buf[partition +4])
514
          {
515
              case 0: printf ("Non DOS"); break;
516
              case 1: printf ("DOS FAT12"); break;
517
              case 4: printf ("DOS FAT16"); break;
518
              case 5: printf ("DOS extended"); break;
519
              case 6: printf ("DOS >32MByte"); break;
520
 
521
              default : printf ("unkown");
522
          };
523
          printf (")\n");
524
          printf( "Partition end (head: 0x%02X cyl: 0x%03X sect: 0x%02X)\n",
525
              buf[partition +5], (buf[partition +6] & 0xc0) << 2 | buf[partition +7] ,buf[partition +6] & 0x3f );
526
          printf( "Physical Startsector: 0x%08X\n", buf[partition +11] << 24 |
527
                                                    buf[partition +10] << 16 |
528
                                                    buf[partition +9] << 8   |
529
                                                    buf[partition +8]);
530
          printf( "Sector count: 0x%08X\n", buf[partition +15] << 24 |
531
                                            buf[partition +14] << 16 |
532
                                            buf[partition +13] << 8  |
533
                                            buf[partition +12]);
534
        }
535
    }
536
    return 0;
537
}
538
 
539
 
540
/*
541
        A T A _ R E A D _ D O S B O O T
542
 
543
        Reads boot sector from the device and dumps it's contents to the screen
544
*/
545
int ata_read_dosboot_cmd(int argc, char **argv)
546
{
547
    struct request request;
548
    unsigned int sector;
549
    char txt[8];
550
 
551
    sector = 0;
552
    if (argc)
553
      sector = strtoul(*argv, argv, 0);
554
 
555
    /* check for busy flag                                            */
556
    if ( ata_dev_busy(ATA_BASE_ADDR) )
557
        printf("Selected ata device busy, ignoring command\n");
558
    else
559
    {
560
        /* fill the request structure                                 */
561
        request.cmd = READ;
562
        request.sector = sector;
563
        request.nr_sectors = 1;
564
        request.buffer = buf;
565
 
566
        if ( ata_request(inode, filp, &request) )
567
        {
568
            printf("Error whilereading boot sector 0x%02X.\n", sector);
569
            printf("Status register = 0x%02lX, error register = 0x%02lX\n", ata_astatus(ATA_BASE_ADDR), ata_error(ATA_BASE_ADDR) );
570
        }
571
        else
572
        {
573
          printf( "Reading boot sector 0x%02X\n", sector );
574
          printf( "ID number: 0x%2X%2X%2X\n", buf[0], buf[1], buf[2] );
575
 
576
          printf( "OEM-name and number: " );
577
          memcpy(txt, &buf[3], 8);
578
          txt[8] = '\0';
579
          printf( "%s\n", txt );
580
 
581
          printf( "Bytes per sector: %5d\n", (buf[12]<<8) | buf[11] );
582
          printf( "Sectors per cluster: %3d\n", buf[13] );
583
          printf( "Reserved IM-sectors: %5d\n", (buf[15]<<8) | buf[14] );
584
          printf( "Number of FATs: %3d\n", buf[16] );
585
          printf( "Number of entries in the root-directory: %5d\n", (buf[18]<<8) | buf[17] );
586
          printf( "Number of logical sectors: %5d\n", (buf[20]<<8) | buf[19] );
587
          printf( "Medium descriptor byte: %02X\n", buf[21] );
588
          printf( "Sectors per FAT: %5d\n", (buf[23]<<8) | buf[22] );
589
          printf( "Sectors per track: %5d\n", (buf[25]<<8) | buf[24] );
590
          printf( "Number of heads: %5d\n", (buf[27]<<8) | buf[26] );
591
          printf( "Number of hidden sectors: %5d\n", (buf[29]<<8) | buf[28] );
592
        }
593
    }
594
    return 0;
595
}
596
 
597
 
598
/*
599
        A T A _ R E S E T
600
 
601
        resets the ATA device, using the select method
602
*/
603
int ata_reset_cmd(int argc, char **argv)
604
{
605
    if (argc != 1)
606
        return -1;
607
 
608
    return ata_ioctl(inode, filp, ATA_IOCTL_SET_RST, SET | (**argv - '0') );
609
}
610
 
611
 
612
/*
613
        A T A _ S E L E C T _ D E V I C E
614
 
615
        selects the ATA device; sets the DEV bit in the device/head register
616
*/
617
int ata_select_device_cmd(int argc, char **argv)
618
{
619
    if (argc != 1)
620
      return -1;
621
 
622
    inode->i_rdev = (ATA_BASE_ADDR >> 16) | (*argv[0] - '0');
623
 
624
    ata_ioctl(inode, filp, ATA_IOCTL_SELECT_DEVICE, **argv - '0');
625
 
626
    printf("Ata device %1d selected.\n", REG32(ATA_BASE_ADDR + ATA_DHR) & ATA_DHR_DEV ? 1 : 0);
627
    return 0;
628
}
629
 
630
 
631
 
632
 
633
/**********************************************************************/
634
/*                                                                    */
635
/*      A T A B U G   T O O L S                                       */
636
/*                                                                    */
637
/**********************************************************************/
638
 
639
/*
640
 D U M P _ D A T A
641
 
642
 dumps byte-data in a buffer of type short to the screen
643
 and returns the byte-checksum
644
 
645
 *buffer = pointer to (short)buffer
646
 cnt     = number of bytes to display
647
*/
648
unsigned char atabug_dump_data(unsigned char *buffer, int cnt)
649
{
650
    int i, n, bytes_per_line = 16;
651
    unsigned char  c, checksum;
652
    unsigned char *buf_ptr;
653
 
654
    /* prepare stored data for display & calculate checksum           */
655
    checksum = 0;
656
    buf_ptr = buffer;
657
 
658
    /* display data                                                   */
659
    for (i=0; i < cnt; i += bytes_per_line)
660
    {
661
      printf("%3X ", i);
662
 
663
      /* print hexadecimal notation                                   */
664
      for (n=0; n < bytes_per_line; n++)
665
          printf("%02X ", *buf_ptr++);
666
 
667
      buf_ptr -= bytes_per_line; /* back to the start (of this block) */
668
 
669
      /* print ASCII notation & calculate checksum                    */
670
      for (n=0; n < bytes_per_line; n++)
671
      {
672
        c = *buf_ptr++;
673
        printf("%c", isprint(c) ? c : '.');
674
        checksum += c;
675
      }
676
      printf("\n");
677
    }
678
 
679
    return checksum;
680
}
681
 
682
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.