VirtualBox

source: kStuff/hacks/xtide/writetest.c

Last change on this file was 72, checked in by bird, 9 years ago

some ata and int13h read+write testing.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.2 KB
Line 
1/* $Id: writetest.c 72 2015-12-20 18:29:17Z bird $ */
2/** @file
3 * Does a little write test.
4 */
5
6/*
7 * Copyright (c) 2015 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with This program. If not, see <http://www.gnu.org/licenses/>
21 *
22 */
23
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <stdint.h>
29#include <io.h>
30#include <conio.h>
31
32/*********************************************************************************************************************************
33* Structures and Typedefs *
34*********************************************************************************************************************************/
35typedef struct REGS16
36{
37 uint16_t ax; /**< 0 */
38 uint16_t cx; /**< 2 */
39 uint16_t dx; /**< 4 */
40 uint16_t si; /**< 6 */
41 uint16_t di; /**< 8 */
42 uint16_t es; /**< 10 */
43 uint16_t efl; /**< 12 */
44 uint16_t ds; /**< 14 */
45 uint16_t bx; /**< 16 */
46} REGS16;
47
48#define X86_EFL_CF 1
49
50
51/*********************************************************************************************************************************
52* Global Variables *
53*********************************************************************************************************************************/
54uint8_t g_bDrv;
55uint16_t g_cHeads;
56uint8_t g_cSectorsPerTrack;
57uint16_t g_cCylinders;
58uint16_t g_cSectorsPerCylinder;
59
60
61void BiosCall13(REGS16 *pRegs);
62#pragma aux BiosCall13 = \
63 "push ax" \
64 "push cx" \
65 "push dx" \
66 "push bp" \
67 "push si" \
68 "push di" \
69 "push es" \
70 "push bx" \
71 "push ds" \
72 \
73 "mov ax, [bx]" \
74 "mov cx, [bx + 2]" \
75 "mov dx, [bx + 4]" \
76 "mov si, [bx + 6]" \
77 "mov di, [bx + 8]" \
78 "mov es, [bx + 10]" \
79 "push word ptr [bx + 12]" \
80 "popf" \
81 "push word ptr [bx + 14]" \
82 "push word ptr [bx + 16]" \
83 "pop bx" \
84 "pop ds" \
85 \
86 "int 13h"\
87 \
88 "push ds" \
89 "push bx" \
90 "mov bp, sp" \
91 "mov ds, [bp + 4]" \
92 "mov bx, [bp + 6]" \
93 "mov [bx], ax" \
94 "mov [bx + 2], cx" \
95 "mov [bx + 4], dx" \
96 "mov [bx + 6], si" \
97 "mov [bx + 8], di" \
98 "mov [bx + 10], es" \
99 "pushf" \
100 "pop ax" \
101 "mov [bx + 12], ax" \
102 "pop ax" \
103 "mov [bx + 14], ax" \
104 "pop ax" \
105 "mov [bx + 16], ax" \
106 \
107 "pop ds" \
108 "pop bx" \
109 "pop es" \
110 "pop di" \
111 "pop si" \
112 "pop bp" \
113 "pop dx" \
114 "pop cx" \
115 "pop ax" \
116 parm [bx];
117
118
119int GetDriveParams(void)
120{
121 REGS16 Regs;
122 memset(&Regs, 0, sizeof(Regs));
123 Regs.ax = 0x0800;
124 Regs.dx = g_bDrv;
125 BiosCall13(&Regs);
126 /** @todo check for errors. */
127 g_cHeads = (Regs.dx >> 8) + 1;
128 g_cSectorsPerTrack = Regs.cx & 0x3f;
129 g_cCylinders = (Regs.cx >> 8) | ((Regs.cx & 0xc0) << 2);
130 g_cSectorsPerCylinder = g_cHeads * g_cSectorsPerTrack;
131
132 printf("Drive %#x parameters: %u cylinders, %u heads, %u sectors\n",
133 g_bDrv, g_cCylinders, g_cHeads, g_cSectorsPerTrack);
134 if (!(Regs.efl & X86_EFL_CF))
135 return 0;
136 fprintf(stderr, "Error getting disk params: %#x\n", Regs.ax);
137 return -1;
138}
139
140void SectorNoToInt13(uint32_t iSector, REGS16 *pRegs)
141{
142 uint16_t iRem = iSector % g_cSectorsPerCylinder;
143 uint16_t iCyl = iSector / g_cSectorsPerCylinder;
144 pRegs->cx = iCyl << 8;
145 pRegs->cx |= (iCyl >> 2) & 0xc0;
146 pRegs->cx |= (iRem % g_cSectorsPerTrack) & 0x3f;
147 pRegs->dx &= UINT16_C(0x00ff);
148 pRegs->dx |= (iRem / g_cSectorsPerTrack) << 8;
149}
150
151int ReadSector(uint32_t iSector, void *pvBuf)
152{
153 REGS16 Regs;
154 memset(&Regs, 0, sizeof(Regs));
155 Regs.ax = 0x0201;
156 Regs.dx = g_bDrv;
157 Regs.bx = (unsigned)(void __near *)pvBuf;
158 Regs.es = (__segment)pvBuf;
159 SectorNoToInt13(iSector, &Regs);
160 printf("ax=%#x dx=%#x cx=%#x es:bx=%04x:%04x\n", Regs.ax, Regs.dx, Regs.cx, Regs.es, Regs.bx);
161 BiosCall13(&Regs);
162 if (!(Regs.efl & X86_EFL_CF))
163 return 0;
164 fprintf(stderr, "Error reading sector %lu on %#x: %#x\n", iSector, g_bDrv, Regs.ax);
165 return -1;
166}
167
168int WriteSector(uint32_t iSector, void const *pvBuf)
169{
170 REGS16 Regs;
171 memset(&Regs, 0, sizeof(Regs));
172 Regs.ax = 0x0301;
173 Regs.dx = g_bDrv;
174 Regs.bx = (unsigned)(void const __near *)pvBuf;
175 Regs.es = (__segment)pvBuf;
176 SectorNoToInt13(iSector, &Regs);
177 printf("ax=%#x dx=%#x cx=%#x es:bx=%04x:%04x\n", Regs.ax, Regs.dx, Regs.cx, Regs.es, Regs.bx);
178 BiosCall13(&Regs);
179 if (!(Regs.efl & X86_EFL_CF))
180 return 0;
181 fprintf(stderr, "Error writing sector %lu on %#x: %#x\n", iSector, g_bDrv, Regs.ax);
182 return -1;
183}
184
185
186static int usage(void)
187{
188 printf("usage: writetst [sector] [drv]\n");
189 return 1;
190}
191
192
193int main(int argc, char **argv)
194{
195 int rc = 1;
196
197 /*
198 * Parse parameters.
199 */
200 uint32_t iSector = 3;
201 g_bDrv = 0x80;
202
203 if (argc > 3)
204 {
205 fprintf(stderr, "too many parameters!\n");
206 return usage();
207 }
208 if (argc > 1)
209 {
210 iSector = strtoul(argv[1], NULL, 0);
211 if ( iSector == 0
212 || (iSector >= 32 && iSector < 65535)
213 || iSector > 0x800000 /*4G*/)
214 {
215 fprintf(stderr, "error: start sector is out of bounds: %s (%lu)\n", argv[1], iSector);
216 return usage();
217 }
218 }
219 if (argc > 2)
220 {
221 unsigned long uTmp = strtoul(argv[2], NULL, 0);
222 if (uTmp < 0x80 || uTmp > 0x8f)
223 {
224 fprintf(stderr, "error: drive number is out of bounds: %s (%lu)\n", argv[1], uTmp);
225 return usage();
226 }
227 g_bDrv = (uint8_t)uTmp;
228 }
229
230 /*
231 * Detect drive parameters.
232 */
233 if (GetDriveParams() == 0)
234 {
235 static uint8_t s_abSaved[512];
236 if (ReadSector(iSector, s_abSaved) == 0)
237 {
238 static uint8_t s_abWrite[512];
239 unsigned i;
240 unsigned cTries;
241
242 for (i = 0; i < 512; i++)
243 s_abWrite[i] = (uint8_t)i;
244
245 for (cTries = 0; cTries < 20 && rc != 0; cTries++)
246 {
247 if (WriteSector(iSector, s_abWrite) == 0)
248 {
249 static uint8_t s_abReadBack[512];
250
251 if (ReadSector(iSector, s_abReadBack) == 0)
252 {
253 for (i = 0; i < 512; i++)
254 s_abWrite[i] = (uint8_t)i;
255
256 if (memcmp(s_abReadBack, s_abWrite, sizeof(s_abReadBack)) == 0)
257 {
258 rc = 0;
259 printf("wrote sector and successfully read it back\n");
260 }
261 else if (cTries >= 19)
262 {
263 unsigned cErrors = 0;
264 fprintf(stderr, "read back doesn't match what was written:\n");
265 for (i = 0; i < 512; i++)
266 if (s_abReadBack[i] != (uint8_t)i)
267 {
268 fprintf(stderr, " %03x: %02x->%02x", i, (uint8_t)i, s_abReadBack[i]);
269 if ((cErrors % 5) == 4)
270 fprintf(stderr, "\n");
271 cErrors++;
272 }
273 if ((cErrors % 5) != 0)
274 fprintf(stderr, "\n");
275 }
276 }
277
278 }
279 }
280
281 /* restore */
282 WriteSector(iSector, s_abSaved);
283 }
284 }
285
286
287 return rc;
288}
289
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette