source: trunk/src/lbatest/readtest.c

Last change on this file was 104, checked in by Markus Thielen, 14 years ago

added readtest.c (sector read program)

File size: 6.7 KB
RevLine 
[54]1/******************************************************************************
2
3 readtest.c - simple (dumb) read test program for os2ahci
4
5 Reads each sector of a logical drive under OS/2 and verifies that the
6 sector number (LBA) written (by lbatest) in the first 4 bytes of each sector
7 matches its real LBA.
8
[55]9 To run the test, run lbatest under Linux, then attach the drive to an OS/2
10 system an create a single primary partition that stretches the entire drive.
11 Then run readtest.exe with the drive letter as a parameter.
12
[54]13
14 Author: Markus Thielen
15
16 Compilation (Watcom): wcl386 -bt=os2 readtest.c
17
18 Copyright (c) 2010 by thi.guten Software development, www.thiguten.de
19
20 This program is free software; you can redistribute it and/or modify
21 it under the terms of the GNU General Public License as published by
22 the Free Software Foundation; either version 2 of the License, or
23 (at your option) any later version.
24
25 This program is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 GNU General Public License for more details.
29
30 You should have received a copy of the GNU General Public License
31 along with this program; if not, write to the Free Software
32 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33
34******************************************************************************/
35
36/*---- includes -------------------------------------------------------------*/
37
38#define INCL_DOS
39#define INCL_ERRORS
40#define INCL_DOSDEVICES
41#define INCL_DOSDEVIOCTL
42#include <os2.h>
43#include <stdio.h>
44#include <stddef.h>
45#include <stdlib.h>
46#include <ctype.h>
47#include <string.h>
48#include <signal.h>
49
50#define SECTOR_SIZE 512
[55]51#define SECTORS_PER_READ 200
[54]52
53
54/*--- function prototypes ---------------------------------------------------*/
55
56void usage (void);
57
58int read_test (char *drv);
59
60void signal_handler (int sig_no);
61
62/*--- global data -----------------------------------------------------------*/
63
64unsigned long lba_pos;
65unsigned long first_wrong_sector = 0xffffffff;
66
[55]67
[54]68/*--- start of code ---------------------------------------------------------*/
69
70/******************************************************************************
71 * main()
72 */
73int main(int argc, char **argv)
74{
75 HFILE hf;
[55]76 char drv[50];
[54]77
78 if (argc < 2) {
79 usage();
80 return -1;
81 }
82
[55]83 if (isalpha(argv[1][0])) {
84 sprintf(drv, "\\\\.\\%c", toupper(argv[1][0]));
85 } else if (isdigit(argv[1][0])) {
86 sprintf(drv, "\\\\.\\Physical_Disk%c", argv[1][0]);
87 } else {
[54]88 usage();
89 return -1;
90 }
91
92 return read_test(drv);
93
94}
95
96/******************************************************************************
97 * read_test() - read each sector's first 4 bytes and compare to its LBA
98 */
99int read_test(char *drv)
100{
101 unsigned long ret;
102 HFILE hf_disk;
103 unsigned long action;
104 unsigned long cb_read;
[55]105 char *buf;
[54]106 int rc = 0;
[55]107 unsigned long cb_take = SECTOR_SIZE * SECTORS_PER_READ;
[54]108 unsigned long err_cnt = 0;
109 float gbf = 1024.0 * 1024.0 * 1024.0 / 512.0;
[55]110 LONGLONG cbfile = {0};
111 int s;
112 unsigned long sectors;
113 unsigned long val;
[54]114
[55]115 buf = calloc(SECTOR_SIZE, SECTORS_PER_READ);
116
[54]117 /* open drive */
[104]118 printf("Getting handle for drive %s\n", drv);
[55]119 ret = DosOpen(drv, &hf_disk, &action, 0, 0,
120 OPEN_ACTION_OPEN_IF_EXISTS,
121/* OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR | */
122/* OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_NO_CACHE | */
123/* OPEN_FLAGS_SEQUENTIAL | OPEN_SHARE_DENYREADWRITE | */
124 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,
125 NULL);
[54]126 if (ret != NO_ERROR) {
127 fprintf(stderr, "Failed to open disk %s for reading: %d\n", drv, ret);
128 return -1;
129 }
130
131 /* lock disk */
[55]132/* ret = DosDevIOCtl(hf_disk, IOCTL_DISK, DSK_LOCKDRIVE, NULL, 0, */
133/* &action, NULL, 0, &cb_read); */
134/* if (ret != NO_ERROR) { */
135/* fprintf(stderr, "Failed to lock drive, code %d\n", ret); */
136/* rc = -1; */
137/* goto cleanup; */
138/* } */
[54]139
140 /* catch Ctrl+C */
141 signal(SIGINT, signal_handler);
142
143 /* go... */
144 memset(buf, 0x00, sizeof(buf));
[55]145 for (lba_pos = 0; ; lba_pos += SECTORS_PER_READ) {
146 ret = DosRead(hf_disk, buf, cb_take, &cb_read);
[54]147 if (ret != NO_ERROR) {
148 fprintf(stderr, "\nFailed to read from disk %s, code %d\n", drv, ret);
149 rc = -1;
150 goto cleanup;
151 }
152
[55]153 if (cb_read == 0) {
154 goto cleanup;
155 }
156
157 sectors = cb_read / SECTOR_SIZE;
158
159 for (s = 0; s < sectors; s++) {
160
161 if (lba_pos + s < 64) {
162 continue;
[54]163 }
[55]164
165 val = *((unsigned long*) (buf + s * SECTOR_SIZE));
166 if (val == 0xf6f6f6f6) {
167 /* appearantly, this is the funny first partition sector
168 * created by LVM - skip it */
169 continue;
170 }
171
172 if (val != lba_pos + s) {
173 printf("\nWrong sector number: read 0x%08x from sector 0x%08x",
174 val, lba_pos + s);
175 err_cnt++;
176 if (first_wrong_sector == 0xffffffff) {
177 first_wrong_sector = lba_pos + s;
178 }
179 }
[54]180 }
181
182 /* progress */
[55]183 printf("\r%dk sectors read (%0.02f GB)", lba_pos / 1000,
184 (float) lba_pos / gbf);
[54]185 }
186
187cleanup:
188 /* unlock drive */
189 DosDevIOCtl(hf_disk, IOCTL_DISK, DSK_UNLOCKDRIVE, NULL, 0, &action,
190 NULL, 0, &cb_read);
191 DosClose(hf_disk);
[55]192 free(buf);
[54]193
194 /* print summary */
195 printf("Found %d logical errors\n", err_cnt);
196 if (first_wrong_sector != 0xffffffff) {
197 printf("First wrong sector was %u.\n", err_cnt, first_wrong_sector);
198 }
199
200 return rc;
201}
202
203/******************************************************************************
204 * usage() - print usage summary to STDOUT
205 */
206void usage(void)
207{
208 printf("LBA (read sector number) test for os2ahci.add\n"
[55]209 "Call with a drive letter (for logical drive) or 1-based disk number (for\n"
210 "physical drive)\n\n"
[54]211 "Usage:\n\n"
[55]212 "lbatest <drive letter|drive number>\n\n");
[54]213}
214
215
216/******************************************************************************
217 * signal_handler for SIGINT - prints summary to STDOUT
218 */
219void signal_handler(int sig_no)
220{
221
[55]222 if (sig_no == SIGINT) {
[54]223 /* read mode interrupted; show summary */
[55]224 printf("\n\nLast block read: 0x%08x\n", lba_pos);
[54]225 if (first_wrong_sector != 0xffffffff) {
[55]226 printf("First wrong sector: 0x%08x\n", first_wrong_sector);
[54]227 } else {
228 printf("All sectors read ok\n");
229 }
230 }
231
232 exit(0);
233
234}
Note: See TracBrowser for help on using the repository browser.