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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [orpmon/] [cmds/] [atabug.c] - Blame information for rev 920

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

Line No. Rev Author Line
1 920 rherveille
/*
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). Mode: 0=hw_reset, 1=sw_reset, 2=device_reset", ata_reset_cmd);
66
  register_ata_command ("enable", "<mode>", "Clear ata reset bits. Mode: 0=hw_reset, 1=sw_reset", 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 <sectorno>(dec)from the selected device (LBA mode)", ata_read_sectors_cmd);
73
  register_ata_command ("read_dosboot", "", "Reads the device's bootsector (FAT).", ata_read_dosboot_cmd);
74
  register_ata_command ("select_device", "<device_no>", "Select ata device. device_no=<0|1>", ata_select_device_cmd);
75
}
76
 
77
 
78
int atabug(int argc, char **argv)
79
{
80
 
81
  /* take care of commandline options                                 */
82
  if (argc == 0)
83
  {
84
    /* start atabug                                                   */
85
    while ( !ata_mon_command() );
86
  }
87
  else
88
    return execute_ata_command(argv[0], argc -1, &argv[1]);
89
 
90
  return 0;
91
}
92
 
93
int atabug_exit(int argc, char **argv)
94
{
95
  ata_close_cmd(argc, argv);
96
  return -2;
97
}
98
 
99
/*
100
 The next code is graceously taken from the "common.c" file
101
 and slightly modified to suit the big list of ATA commands
102
 
103
 Better would be if we could access the routines in 'common.c'
104
 directly, using our own set of commands.
105
*/
106
 
107
/* Process command-line, generate arguments */
108
int ata_mon_command(void)
109
{
110
  char c = '\0';
111
  char str[1000];
112
  char *pstr = str;
113
  char *command_str;
114
  char *argv[20];
115
  int argc = 0;
116
 
117
 
118
  /* Show prompt */
119
  printf ("\natabug> ");
120
 
121
 
122
  /* Get characters from UART */
123
  c = getc();
124
  while (c != '\r' && c != '\f' && c != '\n')
125
  {
126
    if (c == '\b')
127
      pstr--;
128
    else
129
      *pstr++ = c;
130
    putc(c);
131
    c = getc();
132
  }
133
  *pstr = '\0';
134
  printf ("\n");
135
 
136
  /* Skip leading blanks */
137
  pstr = str;
138
  while ( isspace(*pstr) ) pstr++;
139
 
140
  /* Get command from the string */
141
  command_str = pstr;
142
 
143
  while (1) {
144
    /* Go to next argument */
145
    while ( isgraph(*pstr) ) pstr++;
146
    if (*pstr) {
147
      *pstr++ = '\0';
148
      while ( isspace(*pstr) ) pstr++;
149
      argv[argc++] = pstr;
150
    }
151
    else
152
      break;
153
  }
154
 
155
  return execute_ata_command(command_str, argc, argv);
156
}
157
 
158
 
159
int execute_ata_command(char *command_str, int argc, char **argv)
160
{
161
  int i, found = 0;
162
 
163
  for (i = 0; i < ata_num_commands; i++)
164
    if ( !strcmp(command_str, ata_command[i].name) )
165
    {
166
      switch ( ata_command[i].func(argc, argv) )
167
      {
168
        case -1:
169
          printf ("Missing/wrong parameters, usage: %s %s\n", ata_command[i].name, ata_command[i].params);
170
          break;
171
 
172
        case -2:
173
          return -1;
174
      }
175
 
176
      found++;
177
      break;
178
    }
179
 
180
    if (!found)
181
      printf ("Unknown command. Type 'ata help' for help.\n");
182
 
183
  return 0;
184
}
185
 
186
 
187
void register_ata_command (const char *name, const char *params, const char *help, int (*func)(int argc, char *argv[]) )
188
{
189
  if (ata_num_commands < MAX_ATA_COMMANDS)
190
  {
191
    ata_command[ata_num_commands].name = name;
192
    ata_command[ata_num_commands].params = params;
193
    ata_command[ata_num_commands].help = help;
194
    ata_command[ata_num_commands].func = func;
195
    ata_num_commands++;
196
  }
197
  else
198
    printf ("ata-command '%s' ignored; MAX_COMMANDS limit reached\n", name);
199
}
200
 
201
int atabug_help(int argc, char **argv)
202
{
203
  int i;
204
 
205
  for (i = 0; i < ata_num_commands; i++)
206
    printf ("%-15s %-17s -%s\n", ata_command[i].name, ata_command[i].params, ata_command[i].help);
207
 
208
  return 0;
209
}
210
 
211
 
212
 
213
 
214
/**********************************************************************/
215
/*                                                                    */
216
/*      A T A B U G   C O M M A N D S E T                             */
217
/*                                                                    */
218
/**********************************************************************/
219
 
220
/*
221
        A T A _ C L O S E
222
 
223
        closes the ata_device
224
*/
225
int ata_close_cmd(int argc, char **argv)
226
{
227
    inode->i_rdev = (ATA_BASE_ADDR >> 16) | (*argv[0] - '0');
228
 
229
    return ata_release(inode, filp);
230
}
231
 
232
 
233
/*
234
        A T A _ D U M P _ D E V I C E _ R E G S
235
 
236
        Dumps the (readable) ata-registers.
237
        Exception: status register is not read, this could mask an interrupt
238
*/
239
int ata_dump_device_regs_cmd(int argc, char **argv)
240
{
241
    if (argc)
242
      printf("\nWARNING: Ignoring invalid argument(s)\n\n");
243
 
244
 
245
    printf("Alternate status register : 0x%02lX\n", REG32(ATA_BASE_ADDR + ATA_ASR) );
246
    printf("Cylinder high register    : 0x%02lX\n", REG32(ATA_BASE_ADDR + ATA_CHR) );
247
    printf("Cylinder low register     : 0x%02lX\n", REG32(ATA_BASE_ADDR + ATA_CLR) );
248
    printf("Device head register      : 0x%02lX\n", REG32(ATA_BASE_ADDR + ATA_DHR) );
249
    printf("Error register            : 0x%02lX\n", REG32(ATA_BASE_ADDR + ATA_ERR) );
250
    printf("Sector count register     : 0x%02lX\n", REG32(ATA_BASE_ADDR + ATA_SCR) );
251
    printf("Sector number register    : 0x%02lX\n", REG32(ATA_BASE_ADDR + ATA_SNR) );
252
    printf("Status register (see alternate status register)\n" );
253
 
254
    return 0;
255
}
256
 
257
 
258
/*
259
        A T A _ D U M P _ H O S T _ R E G S
260
 
261
        Dumps the ata-host registers
262
*/
263
int ata_dump_host_regs_cmd(int argc, char **argv)
264
{
265
    if (argc)
266
      printf("\nWARNING: Ignoring invalid argument(s)\n\n");
267
 
268
 
269
    printf("Control register                   CTRL : 0x%08lX\n", REG32(ATA_BASE_ADDR + ATA_CTRL) );
270
    printf("Status register                    STAT : 0x%08lX\n", REG32(ATA_BASE_ADDR + ATA_STAT) );
271
    printf("Pio command timing register        PCTR : 0x%08lX\n", REG32(ATA_BASE_ADDR + ATA_PCTR) );
272
    printf("Pio fast timing register (device0) PFTR0: 0x%08lX\n", REG32(ATA_BASE_ADDR + ATA_PFTR0) );
273
    printf("Pio fast timing register (device1) PFTR1: 0x%08lX\n", REG32(ATA_BASE_ADDR + ATA_PFTR0) );
274
    printf("Dma timing register (device0)      DTR0 : 0x%08lX\n", REG32(ATA_BASE_ADDR + ATA_DTR0) );
275
    printf("Dma timing register (device1)      DTR1 : 0x%08lX\n", REG32(ATA_BASE_ADDR + ATA_DTR1) );
276
 
277
    return 0;
278
}
279
 
280
 
281
/*
282
        A T A _ E N A B L E
283
 
284
        clears reset bits
285
*/
286
int ata_enable_cmd(int argc, char **argv)
287
{
288
    if (argc != 1)
289
        return -1;
290
 
291
    inode->i_rdev = (ATA_BASE_ADDR >> 16);
292
 
293
    if ( ata_ioctl(inode, filp, ATA_IOCTL_SET_RST, CLR | (**argv - '0') ) )
294
      return -1;
295
    else
296
      return 0;
297
}
298
 
299
 
300
/*
301
        A T A _ E X E C _ C M D
302
 
303
        Executes the command; writes the command number in the command register
304
*/
305
int ata_exec_cmd_cmd(int argc, char **argv)
306
{
307
    if (argc != 1)
308
        return -1;
309
 
310
    REG32(ATA_BASE_ADDR + ATA_CR) = strtoul(*argv, argv, 16);
311
    return 0;
312
}
313
 
314
 
315
/*
316
        A T A _ I D E N T I F Y _ D E V I C E
317
 
318
        Reads the identify_device block and dumps it to the screen
319
*/
320
int ata_identify_device_cmd(int argc, char **argv)
321
{
322
    unsigned char checksum;
323
 
324
    if (argc != 0)
325
        printf("Ignoring invalid parameters\n");
326
 
327
 
328
    /* check for busy flag                                            */
329
    if ( ata_dev_busy(ATA_BASE_ADDR) )
330
        printf("Selected ata device busy, ignoring command\n");
331
    else
332
    {
333
        /* execute identify device                                    */
334
        ata_ioctl(inode, filp, ATA_IOCTL_IDENTIFY_DEVICE, (unsigned long) buf);
335
 
336
        /* dump data to the screen                                    */
337
        checksum = atabug_dump_data(buf, 256);
338
 
339
        printf("Checksum = 0x%02X (%s)\n", checksum, checksum ? "error" : "OK");
340
    }
341
    return 0;
342
}
343
 
344
 
345
/*
346
        A T A _ O P E N
347
 
348
        opens the ata_device
349
*/
350
int ata_open_cmd(int argc, char **argv)
351
{
352
    inode->i_rdev = (ATA_BASE_ADDR >> 16) | (*argv[0] - '0');
353
 
354
    filp->f_mode = FMODE_READ;
355
 
356
    if (*argv[1] == 'w')
357
      filp->f_mode |= FMODE_WRITE;
358
 
359
    switch( ata_open(inode, filp) ) {
360
      case EOPENIDEV:
361
        printf( "Error: Invalid device (invalid MINOR %02X)\n", MINOR(inode->i_rdev) );
362
        break;
363
 
364
      case EOPENNODEV:
365
        printf( "Error: Requested device not found\n" );
366
        break;
367
 
368
      case EOPENIHOST:
369
        printf( "Error: Invalid host (invalid MAJOR %02X)\n", MAJOR(inode->i_rdev) );
370
      default:
371
        break;
372
    }
373
 
374
    return 0;
375
}
376
 
377
 
378
/*
379
        A T A _ S E T _ P I O M O D E
380
 
381
        Sets the device to the requested PIO mode
382
*/
383
int ata_set_piomode_cmd(int argc, char **argv)
384
{
385
    return 0;
386
}
387
 
388
 
389
/*
390
        A T A _ R E A D _ S E C T O R S
391
 
392
        Reads 1 sector from the device and dumps it to the screen
393
*/
394
int ata_read_sectors_cmd(int argc, char **argv)
395
{
396
    struct request request;
397
    unsigned long sector_cnt, sector;
398
 
399
    sector = strtoul(argv[0], argv, 10);
400
 
401
    switch (argc) {
402
      case 2:
403
        sector_cnt = strtoul(argv[1], argv, 10);
404
        break;
405
 
406
      case 1:
407
        sector_cnt = 1;
408
        break;
409
 
410
      default:
411
        return -1;
412
    }
413
 
414
    if ( !sector_cnt )
415
    {
416
      printf( "Invalid number of sectors.\n" );
417
      return 0;
418
    }
419
 
420
    /* check for busy flag                                            */
421
    if ( ata_dev_busy(ATA_BASE_ADDR) )
422
        printf("Selected ata device busy, ignoring command\n");
423
    else
424
    {
425
        /* fill the request structure                                 */
426
        request.cmd = READ;
427
        request.sector = sector;
428
        request.nr_sectors = sector_cnt;
429
        request.buffer = buf;
430
 
431
        if ( ata_request(inode, filp, &request) )
432
        {
433
            printf("Error while executing READ_SECTOR(S) command\n");
434
            printf("Status register = 0x%02lX, error register = 0x%02lX\n", ata_astatus(ATA_BASE_ADDR), ata_error(ATA_BASE_ADDR) );
435
        }
436
        else
437
        {
438
            /* dump data to the screen                                    */
439
            atabug_dump_data(buf, 256 * sector_cnt);
440
        }
441
    }
442
    return 0;
443
}
444
 
445
 
446
/*
447
        A T A _ R E A D B O O T
448
 
449
        Reads boot sector from the device and dumps it's contents to the screen
450
*/
451
int ata_read_dosboot_cmd(int argc, char **argv)
452
{
453
    struct request request;
454
    char txt[8];
455
 
456
    /* check for busy flag                                            */
457
    if ( ata_dev_busy(ATA_BASE_ADDR) )
458
        printf("Selected ata device busy, ignoring command\n");
459
    else
460
    {
461
        /* fill the request structure                                 */
462
        request.cmd = READ;
463
        request.sector = 0;
464
        request.nr_sectors = 1;
465
        request.buffer = buf;
466
 
467
        if ( ata_request(inode, filp, &request) )
468
        {
469
            printf("Error whilereading boot sector.\n");
470
            printf("Status register = 0x%02lX, error register = 0x%02lX\n", ata_astatus(ATA_BASE_ADDR), ata_error(ATA_BASE_ADDR) );
471
        }
472
        else
473
        {
474
          printf( "ID number: 0x%2X%2X%2X\n", buf[0], buf[1], buf[2] );
475
 
476
          printf( "OEM-name and number: " );
477
          memcpy(txt, &buf[3], 8);
478
          txt[8] = '\0';
479
          printf( "%s\n", txt );
480
 
481
          printf( "Bytes per sector: %5d\n", (buf[12]<<8) | buf[11] );
482
          printf( "Sectors per cluster: %3d\n", buf[13] );
483
          printf( "Reserved IM-sectors: %5d\n", (buf[15]<<8) | buf[14] );
484
          printf( "Number of FATs: %3d\n", buf[16] );
485
          printf( "Number of entries in the root-directory: %5d\n", (buf[18]<<8) | buf[17] );
486
          printf( "Number of logical sectors: %5d\n", (buf[20]<<8) | buf[19] );
487
          printf( "Medium descriptor byte: %02X\n", buf[21] );
488
          printf( "Sectors per FAT: %5d\n", (buf[23]<<8) | buf[22] );
489
          printf( "Sectors per track: %5d\n", (buf[25]<<8) | buf[24] );
490
          printf( "Number of heads: %5d\n", (buf[27]<<8) | buf[26] );
491
          printf( "Number of hidden sectors: %5d\n", (buf[29]<<8) | buf[28] );
492
        }
493
    }
494
    return 0;
495
}
496
 
497
 
498
/*
499
        A T A _ R E S E T
500
 
501
        resets the ATA device, using the select method
502
*/
503
int ata_reset_cmd(int argc, char **argv)
504
{
505
    if (argc != 1)
506
        return -1;
507
 
508
    return ata_ioctl(inode, filp, ATA_IOCTL_SET_RST, SET | (**argv - '0') );
509
}
510
 
511
 
512
/*
513
        A T A _ S E L E C T _ D E V I C E
514
 
515
        selects the ATA device; sets the DEV bit in the device/head register
516
*/
517
int ata_select_device_cmd(int argc, char **argv)
518
{
519
    if (argc != 1)
520
      return -1;
521
 
522
    inode->i_rdev = (ATA_BASE_ADDR >> 16) | (*argv[0] - '0');
523
 
524
    ata_ioctl(inode, filp, ATA_IOCTL_SELECT_DEVICE, **argv - '0');
525
 
526
    printf("Ata device %1d selected.\n", REG32(ATA_BASE_ADDR + ATA_DHR) & ATA_DHR_DEV ? 1 : 0);
527
    return 0;
528
}
529
 
530
 
531
 
532
 
533
/**********************************************************************/
534
/*                                                                    */
535
/*      A T A B U G   T O O L S                                       */
536
/*                                                                    */
537
/**********************************************************************/
538
 
539
/*
540
 D U M P _ D A T A
541
 
542
 dumps byte-data in a buffer of type short to the screen
543
 and returns the byte-checksum
544
 
545
 *buffer = pointer to (short)buffer
546
 cnt     = number of words to display
547
*/
548
unsigned char atabug_dump_data(unsigned char *buffer, int cnt)
549
{
550
    int i, n, bytes_per_line = 16;
551
    unsigned char  c, checksum;
552
    unsigned char *buf_ptr;
553
 
554
    /* prepare stored data for display & calculate checksum           */
555
    checksum = 0;
556
    buf_ptr = buffer;
557
 
558
    /* display data                                                   */
559
    for (i=0; i < cnt; i += bytes_per_line /2)
560
    {
561
      printf("%2X ", i);
562
 
563
      /* print hexadecimal notation                                   */
564
      for (n=0; n < bytes_per_line; n++)
565
          printf("%02X ", *buf_ptr++);
566
 
567
      buf_ptr -= bytes_per_line; /* back to the start (of this block) */
568
 
569
      /* print ASCII notation & calculate checksum                    */
570
      for (n=0; n < bytes_per_line; n++)
571
      {
572
        c = *buf_ptr++;
573
        printf(" %c", isprint(c) ? c : '.');
574
        checksum += c;
575
      }
576
      printf("\n");
577
    }
578
 
579
    return checksum;
580
}
581
 

powered by: WebSVN 2.1.0

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