Changeset 51
- Timestamp:
- Dec 4, 2010, 9:38:12 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/lbatest/lbatest.c
r50 r51 5 5 Writes the actual LBA to each sector on a hard disk. The purpose is to 6 6 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. 7 10 8 T o run the test, attach a HD to an AHCI controller with os2ahci.add loaded9 and run the test in write mode, then attach the disk to an IDE adapter10 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. 11 14 12 15 Author: Markus Thielen 13 16 14 Compilation (Watcom): wcl386 -bt=os2lbatest.c17 Compilation: gcc -o lbatest lbatest.c 15 18 16 19 Copyright (c) 2010 by thi.guten Software development, www.thiguten.de … … 34 37 /*---- includes -------------------------------------------------------------*/ 35 38 36 #define INCL_DOS37 #define INCL_ERRORS38 #define INCL_DOSDEVICES39 #define INCL_DOSDEVIOCTL40 #include <os2.h>41 #include <stdio.h>42 39 #include <stddef.h> 43 40 #include <stdlib.h> 44 41 #include <ctype.h> 45 42 #include <string.h> 46 #include <s ignal.h>43 #include <stdio.h> 47 44 48 45 #define SECTOR_SIZE 512 49 #define SECTORS_PER_WRITE 3246 #define SECTORS_PER_WRITE 256 50 47 51 48 … … 54 51 void usage (void); 55 52 56 int write_test (char *drv); 57 58 int read_test (char *drv); 59 60 void signal_handler (int sig_no); 53 void write_test (char *dev); 61 54 62 55 /*--- global data -----------------------------------------------------------*/ 63 64 DEVICEPARAMETERBLOCK dev_parms;65 56 66 57 … … 72 63 int main(int argc, char **argv) 73 64 { 74 char *drv;75 HFILE hf;76 65 77 if (argc < 3) {66 if (argc < 2) { 78 67 usage(); 79 68 return -1; 80 69 } 81 70 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]); 105 72 106 73 return 0; 107 74 } 108 75 109 /******************************************************************************110 * determine CHS layout of the drive we're running on111 */112 void get_drive_layout(char *disk)113 {114 115 116 }117 76 118 77 … … 120 79 * write_test() - write each sector's address to the sector itself 121 80 */ 122 int write_test(char *drv)81 void write_test(char *dev) 123 82 { 124 83 unsigned long lba; 125 unsigned long ret;126 HFILE hf_disk;127 unsigned long action;128 unsigned long cb_written;129 int rc = 0;130 84 float gbf = 1024.0 * 1024.0 * 1024.0 / 512.0; 131 unsigned longi;85 size_t i; 132 86 unsigned char *wbuf; 133 87 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; 136 91 137 92 /* ask for confirmation, we destroy the drive's contents */ 138 93 printf("I'm going to destroy ALL DATA on drive %s now.\n" 139 "type 'DESTROY' to continue, anything else to bail out.\n", d rv);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; 142 97 } 143 98 144 99 /* 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; 162 103 } 163 104 … … 175 116 176 117 /* 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"); 184 122 } 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; 202 124 } 203 125 204 126 /* 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); 206 129 207 130 } 208 131 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); 214 134 free(wbuf); 215 return rc;216 135 217 }218 219 /******************************************************************************220 * read_test() - read each sector's first 4 bytes and compare to its LBA221 */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;296 136 } 297 137 … … 303 143 printf("lbatest for os2ahci.add\n" 304 144 "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"); 310 146 } 311 147 312 313 /******************************************************************************314 * signal_handler for SIGINT - prints summary to STDOUT315 */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.