source: trunk/src/lbatest/lbatest.c@ 44

Last change on this file since 44 was 44, checked in by markus, 15 years ago

added lbatest

File size: 7.0 KB
Line 
1/******************************************************************************
2
3 lbatest.c - simple test program for os2ahci
4
5 Writes the actual LBA to each sector on a hard disk. The purpose is to
6 find out if the sector mapping of os2ahci.add is correct.
7
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 with
10 with an S506 driver and run lbdatest in read mode.
11
12 Author: Markus Thielen
13
14 Compilation (Watcom): wcl386 -bt=os2 lbatest.c
15
16 Copyright (c) 2010 by thi.guten Software development, www.thiguten.de
17
18 This program is free software; you can redistribute it and/or modify
19 it under the terms of the GNU General Public License as published by
20 the Free Software Foundation; either version 2 of the License, or
21 (at your option) any later version.
22
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
27
28 You should have received a copy of the GNU General Public License
29 along with this program; if not, write to the Free Software
30 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31
32******************************************************************************/
33
34/*---- includes -------------------------------------------------------------*/
35
36#define INCL_DOS
37#define INCL_ERRORS
38#define INCL_DOSDEVICES
39#define INCL_DOSDEVIOCTL
40#include <os2.h>
41#include <stdio.h>
42#include <stddef.h>
43#include <ctype.h>
44#include <string.h>
45
46#define SECTOR_SIZE 512
47
48/*--- function prototypes ---------------------------------------------------*/
49
50void usage (void);
51
52int write_test (const char *drv);
53
54int read_test (const char *drv);
55
56
57/*--- start of code ---------------------------------------------------------*/
58
59/******************************************************************************
60 * main()
61 */
62int main(int argc, char **argv)
63{
64 char *drv;
65 char mode;
66 HFILE hf;
67
68 if (argc < 3) {
69 usage();
70 return -1;
71 }
72
73 /* get arguments */
74 drv = argv[1];
75 mode = toupper(argv[2][0]);
76 if (mode != 'W' && mode != 'R') {
77 usage();
78 return -1;
79 }
80
81 if (drv[1] != ':' && drv[2] != '\0') {
82 /* we want a drive letter, which is a letter and a colon */
83 usage();
84 return -1;
85 }
86
87 if (mode == 'W') {
88 return write_test(drv);
89 }
90 if (mode == 'R') {
91 return read_test(drv);
92 }
93
94 return 0;
95}
96
97/******************************************************************************
98 * write_test() - write each sector's address to the sector itself
99 */
100int write_test(const char *drv)
101{
102 unsigned long lba;
103 unsigned long ret;
104 HFILE hf_disk;
105 unsigned long action;
106 unsigned long cb_written;
107 char buf[SECTOR_SIZE];
108 int rc = 0;
109 float gbf = 1024.0 * 1024.0 * 1024.0 / 512.0;
110
111 /* ask for confirmation, we destroy the drive's contents */
112 printf("I'm going to destroy ALL DATA on drive %s now.\n"
113 "type 'DESTROY' to continue, anything else to bail out.\n", drv);
114 if (gets(buf) == NULL || strcmp(buf, "DESTROY")) {
115 return -1;
116 }
117
118 /* open drive */
119 ret = DosOpen(drv, &hf_disk, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS,
120 OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |
121 OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_NO_CACHE |
122 OPEN_FLAGS_SEQUENTIAL | OPEN_SHARE_DENYREADWRITE |
123 OPEN_ACCESS_WRITEONLY,
124 NULL);
125 if (ret != NO_ERROR) {
126 fprintf(stderr, "Failed to open disk %s for writing: %d\n", drv, ret);
127 return -1;
128 }
129
130 /* lock disk */
131 ret = DosDevIOCtl(hf_disk, IOCTL_DISK, DSK_LOCKDRIVE, NULL, 0,
132 &action, NULL, 0, &cb_written);
133 if (ret != NO_ERROR) {
134 fprintf(stderr, "Failed to lock drive, code %d\n", ret);
135 rc = -1;
136 goto cleanup;
137 }
138
139 /* go... */
140 memset(buf, 0x00, sizeof(buf));
141 for (lba = 0; ; lba++) {
142 memcpy(buf, &lba, sizeof(lba));
143 ret = DosWrite(hf_disk, buf, SECTOR_SIZE, &cb_written);
144 if (ret != NO_ERROR) {
145 fprintf(stderr, "\nFailed to write to disk %s, code %d\n", drv, ret);
146 rc = -1;
147 goto cleanup;
148 }
149
150 /* write progress */
151 if (lba % 100 == 0) {
152 printf("\r%dk sectors written (%0.02f GB)", lba / 1000, (float)lba / gbf);
153 }
154 }
155
156cleanup:
157 /* unlock drive */
158 DosDevIOCtl(hf_disk, IOCTL_DISK, DSK_UNLOCKDRIVE, NULL, 0, &action,
159 NULL, 0, &cb_written);
160
161 DosClose(hf_disk);
162 return rc;
163
164}
165
166/******************************************************************************
167 * read_test() - read each sector's first 4 bytes and compare to its LBA
168 */
169int read_test(const char *drv)
170{
171 unsigned long lba;
172 unsigned long ret;
173 HFILE hf_disk;
174 unsigned long action;
175 unsigned long cb_read;
176 char buf[SECTOR_SIZE];
177 int rc = 0;
178 unsigned long err_cnt = 0;
179 float gbf = 1024.0 * 1024.0 * 1024.0 / 512.0;
180
181 /* open drive */
182 ret = DosOpen(drv, &hf_disk, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS,
183 OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |
184 OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_NO_CACHE |
185 OPEN_FLAGS_SEQUENTIAL | OPEN_SHARE_DENYREADWRITE |
186 OPEN_ACCESS_READONLY,
187 NULL);
188 if (ret != NO_ERROR) {
189 fprintf(stderr, "Failed to open disk %s for reading: %d\n", drv, ret);
190 return -1;
191 }
192
193 /* lock disk */
194 ret = DosDevIOCtl(hf_disk, IOCTL_DISK, DSK_LOCKDRIVE, NULL, 0,
195 &action, NULL, 0, &cb_read);
196 if (ret != NO_ERROR) {
197 fprintf(stderr, "Failed to lock drive, code %d\n", ret);
198 rc = -1;
199 goto cleanup;
200 }
201
202 /* go... */
203 memset(buf, 0x00, sizeof(buf));
204 for (lba = 0; ; lba++) {
205 ret = DosRead(hf_disk, buf, SECTOR_SIZE, &cb_read);
206 if (ret != NO_ERROR) {
207 fprintf(stderr, "\nFailed to read from disk %s, code %d\n", drv, ret);
208 rc = -1;
209 goto cleanup;
210 }
211
212 if (*((unsigned long*)buf) != lba) {
213 fprintf(stderr, "\nFailure: read %d from sector %d\n",
214 *((unsigned long*)buf), lba);
215 err_cnt++;
216 }
217
218 /* progress */
219 if (lba % 100 == 0) {
220 printf("\r%dk sectors read (%0.02f GB)", lba / 1000, (float)lba / gbf);
221 }
222 }
223
224cleanup:
225 /* unlock drive */
226 DosDevIOCtl(hf_disk, IOCTL_DISK, DSK_UNLOCKDRIVE, NULL, 0, &action,
227 NULL, 0, &cb_read);
228
229 DosClose(hf_disk);
230
231 printf("Found %d logical errors (wrong values)\n", err_cnt);
232 return rc;
233}
234
235/******************************************************************************
236 * usage() - print usage summary to STDOUT
237 */
238void usage(void)
239{
240 printf("lbatest for os2ahci.add\n"
241 "Usage:\n\n"
242 "lbatest <drive letter> <mode>\n\n"
243 "where mode is either W for writing or R for reading.\n\n"
244 "In write mode, this program COMPLETELY DESTROYS ALL DATA on the specified\n"
245 "disc. It writes the address of each sector to the sector itself.\n\n"
246 "In read mode, each sector is read and its address verified.\n");
247}
Note: See TracBrowser for help on using the repository browser.