Changeset 51


Ignore:
Timestamp:
Dec 4, 2010, 9:38:12 PM (15 years ago)
Author:
markus
Message:

ported lbatest to unix

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/lbatest/lbatest.c

    r50 r51  
    55  Writes the actual LBA to each sector on a hard disk. The purpose is to
    66  find out if the sector mapping of os2ahci.add is correct.
     7 
     8  THe program was written to run under Linux, since OS/2 physical disk
     9  access IOCTLs support CHS addressing, only.
    710
    8   To run the test, attach a HD to an AHCI controller with os2ahci.add loaded
    9   and run the test in write mode, then attach the disk to an IDE adapter
    10   with an S506 driver and run lbatest in read mode.
     11  The os2ahci.add driver provides a special operating mode that does nothing
     12  but verifying that the tests drive's sector's are addressed in the correct
     13  manner by verifying the sector numbers written under Linux.
    1114
    1215  Author: Markus Thielen
    1316
    14   Compilation (Watcom): wcl386 -bt=os2 lbatest.c
     17  Compilation: gcc -o lbatest lbatest.c
    1518
    1619  Copyright (c) 2010 by thi.guten Software development, www.thiguten.de
     
    3437/*---- includes -------------------------------------------------------------*/
    3538
    36 #define INCL_DOS
    37 #define INCL_ERRORS
    38 #define INCL_DOSDEVICES
    39 #define INCL_DOSDEVIOCTL
    40 #include <os2.h>
    41 #include <stdio.h>
    4239#include <stddef.h>
    4340#include <stdlib.h>
    4441#include <ctype.h>
    4542#include <string.h>
    46 #include <signal.h>
     43#include <stdio.h>
    4744
    4845#define SECTOR_SIZE        512
    49 #define SECTORS_PER_WRITE  32
     46#define SECTORS_PER_WRITE  256
    5047
    5148
     
    5451void          usage            (void);
    5552
    56 int           write_test       (char *drv);
    57 
    58 int           read_test        (char *drv);
    59 
    60 void          signal_handler   (int sig_no);
     53void          write_test       (char *dev);
    6154
    6255/*--- global data -----------------------------------------------------------*/
    63 
    64 DEVICEPARAMETERBLOCK dev_parms;
    6556
    6657
     
    7263int main(int argc, char **argv)
    7364{
    74   char *drv;
    75   HFILE hf;
    7665
    77   if (argc < 3) {
     66  if (argc < 2) {
    7867    usage();
    7968    return -1;
    8069  }
    8170
    82   /* get arguments */
    83   drv = argv[1];
    84   mode = toupper(argv[2][0]);
    85   if (mode != 'W' && mode != 'R') {
    86     usage();
    87     return -1;
    88   }
    89 
    90   if (drv[1] != ':' && drv[2] != '\0') {
    91     /* we want a drive letter, which is a letter and a colon */
    92     usage();
    93     return -1;
    94   }
    95 
    96   /* determine physical drive layout */
    97   get_drive_layout(drv);
    98 
    99   if (mode == 'W') {
    100     return write_test(drv);
    101   }
    102   if (mode == 'R') {
    103     return read_test(drv);
    104   }
     71  write_test(argv[1]);
    10572
    10673  return 0;
    10774}
    10875
    109 /******************************************************************************
    110  * determine CHS layout of the drive we're running on
    111  */
    112 void get_drive_layout(char *disk)
    113 {
    114  
    115 
    116 }
    11776
    11877
     
    12079 * write_test() - write each sector's address to the sector itself
    12180 */
    122 int write_test(char *drv)
     81void write_test(char *dev)
    12382{
    12483  unsigned long lba;
    125   unsigned long ret;
    126   HFILE hf_disk;
    127   unsigned long action;
    128   unsigned long cb_written;
    129   int rc = 0;
    13084  float gbf = 1024.0 * 1024.0 * 1024.0 / 512.0;
    131   unsigned long i;
     85  size_t i;
    13286  unsigned char *wbuf;
    13387  char buf[100];
    134   unsigned long cbtake = SECTOR_SIZE * SECTORS_PER_WRITE;
    135   unsigned long cb;
     88  size_t cbtake = SECTOR_SIZE * SECTORS_PER_WRITE;
     89  size_t cb_written;
     90  FILE *fp;
    13691
    13792  /* ask for confirmation, we destroy the drive's contents */
    13893  printf("I'm going to destroy ALL DATA on drive %s now.\n"
    139          "type 'DESTROY' to continue, anything else to bail out.\n", drv);
    140   if (gets(buf) == NULL || strcmp(buf, "DESTROY")) {
    141     return -1;
     94         "type 'DESTROY' to continue, anything else to bail out.\n", dev);
     95  if (fgets(buf, sizeof(buf), stdin) == NULL || strcmp(buf, "DESTROY\n")) {
     96    return;
    14297  }
    14398
    14499  /* open drive */
    145   ret = DosOpen(drv, &hf_disk, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS,
    146                 OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |
    147                 OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_NO_CACHE |
    148                 OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_WRITEONLY,
    149                 NULL);
    150   if (ret != NO_ERROR) {
    151     fprintf(stderr, "Failed to open disk %s for writing: %d\n", drv, ret);
    152     return -1;
    153   }
    154 
    155   /* lock disk */
    156   ret = DosDevIOCtl(hf_disk, IOCTL_DISK, DSK_LOCKDRIVE, NULL, 0,
    157                     &action, NULL, 0, &cb_written);
    158   if (ret != NO_ERROR) {
    159     fprintf(stderr, "Failed to lock drive, code %d\n", ret);
    160     rc = -1;
    161     goto cleanup;
     100  if ((fp = fopen(dev, "wb")) == NULL) {
     101    perror("Failed to open device");
     102    return;
    162103  }
    163104
     
    175116
    176117    /* write buffer to disk */
    177     cb = cbtake;
    178     while (cb) {
    179       ret = DosWrite(hf_disk, wbuf + cbtake - cb, cb, &cb_written);
    180       if (ret != NO_ERROR) {
    181         fprintf(stderr, "\nFailed to write to disk %s, code %d\n", drv, ret);
    182         rc = -1;
    183         goto cleanup;
     118    cb_written = fwrite(wbuf, 1, cbtake, fp);
     119    if (cb_written < cbtake) {
     120      if (!feof(fp)) {
     121        perror("Failed to write to target device");
    184122      }
    185       if (cb_written >= cb) {
    186         break;
    187       }
    188 
    189       if (cb_written == 0) {
    190         /* what the heck... */
    191         fprintf(stderr, "\nWrote 0 bytes of %u, no error return code\n",
    192                 cb);
    193         ret = DosSetFilePtr(hf_disk, lba * SECTOR_SIZE + cbtake - cb,
    194                             FILE_BEGIN, &action);
    195         if (ret != NO_ERROR) {
    196           fprintf(stderr, "Failed to set file pointer after writing "
    197                   "0 bytes: %d\n", ret);
    198           goto cleanup;
    199         }
    200       }
    201       cb -= cb_written;
     123      break;
    202124    }
    203 
     125   
    204126    /* write progress */
    205     printf("\r%dk sectors written (%0.02f GB)", lba / 1000, (float)lba / gbf);
     127    printf("\r%uk sectors written (%0.02f GB)",
     128           (size_t)(lba / 1000), (float)lba / gbf);
    206129   
    207130  }
    208131
    209 cleanup:
    210   /* unlock drive */
    211   DosDevIOCtl(hf_disk, IOCTL_DISK, DSK_UNLOCKDRIVE, NULL, 0, &action,
    212               NULL, 0, &cb_written);
    213   DosClose(hf_disk);
     132  /* cleanup */
     133  fclose(fp);
    214134  free(wbuf);
    215   return rc;
    216135
    217 }
    218 
    219 /******************************************************************************
    220  * read_test() - read each sector's first 4 bytes and compare to its LBA
    221  */
    222 int read_test(char *drv)
    223 {
    224   unsigned long ret;
    225   HFILE hf_disk;
    226   unsigned long action;
    227   unsigned long cb_read;
    228   char buf[SECTOR_SIZE];
    229   int rc = 0;
    230   unsigned long err_cnt = 0;
    231   float gbf = 1024.0 * 1024.0 * 1024.0 / 512.0;
    232 
    233   /* open drive */
    234   ret = DosOpen(drv, &hf_disk, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS,
    235                 OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |
    236                 OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_NO_CACHE |
    237                 OPEN_FLAGS_SEQUENTIAL | OPEN_SHARE_DENYREADWRITE |
    238                 OPEN_ACCESS_READONLY,
    239                 NULL);
    240   if (ret != NO_ERROR) {
    241     fprintf(stderr, "Failed to open disk %s for reading: %d\n", drv, ret);
    242     return -1;
    243   }
    244 
    245   /* lock disk */
    246   ret = DosDevIOCtl(hf_disk, IOCTL_DISK, DSK_LOCKDRIVE, NULL, 0,
    247                     &action, NULL, 0, &cb_read);
    248   if (ret != NO_ERROR) {
    249     fprintf(stderr, "Failed to lock drive, code %d\n", ret);
    250     rc = -1;
    251     goto cleanup;
    252   }
    253 
    254   /* catch Ctrl+C */
    255   signal(SIGINT, signal_handler);
    256 
    257   /* go... */
    258   memset(buf, 0x00, sizeof(buf));
    259   for (lba_pos = 0; ; lba_pos++) {
    260     ret = DosRead(hf_disk, buf, SECTOR_SIZE, &cb_read);
    261     if (ret != NO_ERROR) {
    262       fprintf(stderr, "\nFailed to read from disk %s, code %d\n", drv, ret);
    263       rc = -1;
    264       goto cleanup;
    265     }
    266 
    267     if (*((unsigned long*) buf) != lba_pos) {
    268       printf("\nWrong sector number: read %d from sector %d\n",
    269               *((unsigned long*) buf), lba_pos);
    270       err_cnt++;
    271       if (first_wrong_sector == 0xffffffff) {
    272         first_wrong_sector = lba_pos;
    273       }
    274     }
    275 
    276     /* progress */
    277     if (lba_pos % 100 == 0) {
    278       printf("\r%dk sectors read (%0.02f GB)", lba_pos / 1000,
    279              (float) lba_pos / gbf);
    280     }
    281   }
    282 
    283 cleanup:
    284   /* unlock drive */
    285   DosDevIOCtl(hf_disk, IOCTL_DISK, DSK_UNLOCKDRIVE, NULL, 0, &action,
    286               NULL, 0, &cb_read);
    287   DosClose(hf_disk);
    288 
    289   /* print summary */
    290   printf("Found %d logical errors\n", err_cnt);
    291   if (first_wrong_sector != 0xffffffff) {
    292     printf("First wrong sector was %u.\n", err_cnt, first_wrong_sector);
    293   }
    294 
    295   return rc;
    296136}
    297137
     
    303143  printf("lbatest for os2ahci.add\n"
    304144         "Usage:\n\n"
    305          "lbatest <drive letter> <mode>\n\n"
    306          "where mode is either W for writing or R for reading.\n\n"
    307          "In write mode, this program COMPLETELY DESTROYS ALL DATA on the specified\n"
    308          "partition/disc. It writes the address of each sector to the sector itself.\n\n"
    309          "In read mode, each sector is read and its address verified.\n");
     145         "lbatest <device>\n\n");
    310146}
    311147
    312 
    313 /******************************************************************************
    314  * signal_handler for SIGINT - prints summary to STDOUT
    315  */
    316 void signal_handler(int sig_no)
    317 {
    318 
    319   if (sig_no == SIGINT && mode == 'R') {
    320     /* read mode interrupted; show summary */
    321     printf("\n\nLast block read:    %u\n", lba_pos);
    322     if (first_wrong_sector != 0xffffffff) {
    323       printf("First wrong sector: %u\n", first_wrong_sector);
    324     } else {
    325       printf("All sectors read ok\n");
    326     }
    327   }
    328 
    329   exit(0);
    330 
    331 }
Note: See TracChangeset for help on using the changeset viewer.