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

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

sped up writing (larger buffer)

File size: 8.5 KB
Line 
1/******************************************************************************
2
3 lbatest.c - simple (dumb) 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
10 with an S506 driver and run lbatest 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 <stdlib.h>
44#include <ctype.h>
45#include <string.h>
46#include <signal.h>
47
48#define SECTOR_SIZE 512
49#define SECTORS_PER_WRITE 200
50
51
52/*--- function prototypes ---------------------------------------------------*/
53
54void usage (void);
55
56int write_test (char *drv);
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;
66char mode;
67
68/*--- start of code ---------------------------------------------------------*/
69
70/******************************************************************************
71 * main()
72 */
73int main(int argc, char **argv)
74{
75 char *drv;
76 HFILE hf;
77
78 if (argc < 3) {
79 usage();
80 return -1;
81 }
82
83 /* get arguments */
84 drv = argv[1];
85 mode = toupper(argv[2][0]);
86 if (mode != 'W' && mode != 'R') {
87 usage();
88 return -1;
89 }
90
91 if (drv[1] != ':' && drv[2] != '\0') {
92 /* we want a drive letter, which is a letter and a colon */
93 usage();
94 return -1;
95 }
96
97 if (mode == 'W') {
98 return write_test(drv);
99 }
100 if (mode == 'R') {
101 return read_test(drv);
102 }
103
104 return 0;
105}
106
107/******************************************************************************
108 * write_test() - write each sector's address to the sector itself
109 */
110int write_test(char *drv)
111{
112 unsigned long lba;
113 unsigned long ret;
114 HFILE hf_disk;
115 unsigned long action;
116 unsigned long cb_written;
117 int rc = 0;
118 float gbf = 1024.0 * 1024.0 * 1024.0 / 512.0;
119 unsigned long i;
120 unsigned char *wbuf;
121 char buf[100];
122
123 /* ask for confirmation, we destroy the drive's contents */
124 printf("I'm going to destroy ALL DATA on drive %s now.\n"
125 "type 'DESTROY' to continue, anything else to bail out.\n", drv);
126 if (gets(buf) == NULL || strcmp(buf, "DESTROY")) {
127 return -1;
128 }
129
130 /* open drive */
131 ret = DosOpen(drv, &hf_disk, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS,
132 OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |
133 OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_NO_CACHE |
134 OPEN_SHARE_DENYREADWRITE | OPEN_ACCESS_WRITEONLY,
135 NULL);
136 if (ret != NO_ERROR) {
137 fprintf(stderr, "Failed to open disk %s for writing: %d\n", drv, ret);
138 return -1;
139 }
140
141 /* lock disk */
142 ret = DosDevIOCtl(hf_disk, IOCTL_DISK, DSK_LOCKDRIVE, NULL, 0,
143 &action, NULL, 0, &cb_written);
144 if (ret != NO_ERROR) {
145 fprintf(stderr, "Failed to lock drive, code %d\n", ret);
146 rc = -1;
147 goto cleanup;
148 }
149
150 /* allocate big write buffer */
151 wbuf = calloc(SECTOR_SIZE, SECTORS_PER_WRITE);
152
153 /* go... */
154 for (lba = 0; ; lba += SECTORS_PER_WRITE) {
155
156 /* prepare buffer; set the first 4 bytes of each sector
157 * to its LBA */
158 for (i = 0; i < SECTORS_PER_WRITE; i++) {
159 *((unsigned long *)(wbuf + i * SECTOR_SIZE)) = lba + i;
160 }
161
162 /* write buffer to disk */
163 ret = DosWrite(hf_disk, wbuf, SECTOR_SIZE * SECTORS_PER_WRITE, &cb_written);
164 if (cb_written < SECTOR_SIZE * SECTORS_PER_WRITE) {
165 /* done?! */
166 goto cleanup;
167 }
168 if (ret != NO_ERROR) {
169 fprintf(stderr, "\nFailed to write to disk %s, code %d\n", drv, ret);
170 rc = -1;
171 goto cleanup;
172 }
173
174 /* write progress */
175 printf("\r%dk sectors written (%0.02f GB)", lba / 1000, (float)lba / gbf);
176
177 }
178
179cleanup:
180 /* unlock drive */
181 DosDevIOCtl(hf_disk, IOCTL_DISK, DSK_UNLOCKDRIVE, NULL, 0, &action,
182 NULL, 0, &cb_written);
183 DosClose(hf_disk);
184 free(wbuf);
185 return rc;
186
187}
188
189/******************************************************************************
190 * read_test() - read each sector's first 4 bytes and compare to its LBA
191 */
192int read_test(char *drv)
193{
194 unsigned long ret;
195 HFILE hf_disk;
196 unsigned long action;
197 unsigned long cb_read;
198 char buf[SECTOR_SIZE];
199 int rc = 0;
200 unsigned long err_cnt = 0;
201 float gbf = 1024.0 * 1024.0 * 1024.0 / 512.0;
202
203 /* open drive */
204 ret = DosOpen(drv, &hf_disk, &action, 0, 0, OPEN_ACTION_OPEN_IF_EXISTS,
205 OPEN_FLAGS_DASD | OPEN_FLAGS_FAIL_ON_ERROR |
206 OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_NO_CACHE |
207 OPEN_FLAGS_SEQUENTIAL | OPEN_SHARE_DENYREADWRITE |
208 OPEN_ACCESS_READONLY,
209 NULL);
210 if (ret != NO_ERROR) {
211 fprintf(stderr, "Failed to open disk %s for reading: %d\n", drv, ret);
212 return -1;
213 }
214
215 /* lock disk */
216 ret = DosDevIOCtl(hf_disk, IOCTL_DISK, DSK_LOCKDRIVE, NULL, 0,
217 &action, NULL, 0, &cb_read);
218 if (ret != NO_ERROR) {
219 fprintf(stderr, "Failed to lock drive, code %d\n", ret);
220 rc = -1;
221 goto cleanup;
222 }
223
224 /* catch Ctrl+C */
225 signal(SIGINT, signal_handler);
226
227 /* go... */
228 memset(buf, 0x00, sizeof(buf));
229 for (lba_pos = 0; ; lba_pos++) {
230 ret = DosRead(hf_disk, buf, SECTOR_SIZE, &cb_read);
231 if (ret != NO_ERROR) {
232 fprintf(stderr, "\nFailed to read from disk %s, code %d\n", drv, ret);
233 rc = -1;
234 goto cleanup;
235 }
236
237 if (*((unsigned long*) buf) != lba_pos) {
238 printf("\nWrong sector number: read %d from sector %d\n",
239 *((unsigned long*) buf), lba_pos);
240 err_cnt++;
241 if (first_wrong_sector == 0xffffffff) {
242 first_wrong_sector = lba_pos;
243 }
244 }
245
246 /* progress */
247 if (lba_pos % 100 == 0) {
248 printf("\r%dk sectors read (%0.02f GB)", lba_pos / 1000,
249 (float) lba_pos / gbf);
250 }
251 }
252
253cleanup:
254 /* unlock drive */
255 DosDevIOCtl(hf_disk, IOCTL_DISK, DSK_UNLOCKDRIVE, NULL, 0, &action,
256 NULL, 0, &cb_read);
257 DosClose(hf_disk);
258
259 /* print summary */
260 printf("Found %d logical errors\n", err_cnt);
261 if (first_wrong_sector != 0xffffffff) {
262 printf("First wrong sector was %u.\n", err_cnt, first_wrong_sector);
263 }
264
265 return rc;
266}
267
268/******************************************************************************
269 * usage() - print usage summary to STDOUT
270 */
271void usage(void)
272{
273 printf("lbatest for os2ahci.add\n"
274 "Usage:\n\n"
275 "lbatest <drive letter> <mode>\n\n"
276 "where mode is either W for writing or R for reading.\n\n"
277 "In write mode, this program COMPLETELY DESTROYS ALL DATA on the specified\n"
278 "partition/disc. It writes the address of each sector to the sector itself.\n\n"
279 "In read mode, each sector is read and its address verified.\n");
280}
281
282
283/******************************************************************************
284 * signal_handler for SIGINT - prints summary to STDOUT
285 */
286void signal_handler(int sig_no)
287{
288
289 if (sig_no == SIGINT && mode == 'R') {
290 /* read mode interrupted; show summary */
291 printf("\n\nLast block read: %u\n", lba_pos);
292 if (first_wrong_sector != 0xffffffff) {
293 printf("First wrong sector: %u\n", first_wrong_sector);
294 } else {
295 printf("All sectors read ok\n");
296 }
297 }
298
299 exit(0);
300
301}
Note: See TracBrowser for help on using the repository browser.