VirtualBox

source: kStuff/hacks/xtide/atalib.c@ 75

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

xtide-utils: added ataid for dumping the identify device response. (untested)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 25.7 KB
Line 
1/* $Id: atalib.c 75 2015-12-27 19:47:37Z 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/*********************************************************************************************************************************
26* Header Files *
27*********************************************************************************************************************************/
28#include <stdarg.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <stdint.h>
33#include <io.h>
34#include <conio.h>
35#include "atalib.h"
36
37#define STR_TUPLE(a_szStr) a_szStr, sizeof(a_szStr) - 1
38
39
40/*********************************************************************************************************************************
41* Global Variables *
42*********************************************************************************************************************************/
43uint16_t g_uBasePort;
44uint16_t g_uCtrlPort;
45uint8_t g_cPortShift;
46uint8_t g_bDevice;
47uint8_t g_fUseLbaMode = 1;
48uint8_t g_f8BitData;
49uint8_t g_fSupportsSetFeature8BitData;
50uint8_t g_fSupportsSetFeatureWriteCache;
51uint8_t g_fSupportsSetFeatureXferMode;
52int8_t g_fSupportsReadBuffer = -1;
53int8_t g_fSupportsWriteBuffer = -1;
54
55uint16_t g_cHeads;
56uint8_t g_cSectorsPerTrack;
57uint16_t g_cCylinders;
58uint16_t g_cSectorsPerCylinder;
59
60/** The result of the identify command. */
61uint16_t g_awIdentify[256];
62
63
64size_t AtaPrintStatus(FILE *pOut, uint8_t bSts)
65{
66 size_t cch = fprintf(pOut, "%#x", bSts);
67 if (bSts & ATA_STS_BUSY) cch += fprintf(pOut, " busy");
68 if (bSts & ATA_STS_DRDY) cch += fprintf(pOut, " drdy");
69 if (bSts & ATA_STS_DF ) cch += fprintf(pOut, " df");
70 if (bSts & ATA_STS_DSC ) cch += fprintf(pOut, " dsc");
71 if (bSts & ATA_STS_DRQ ) cch += fprintf(pOut, " drq");
72 if (bSts & ATA_STS_CORR) cch += fprintf(pOut, " corr");
73 if (bSts & ATA_STS_IDX ) cch += fprintf(pOut, " idx");
74 if (bSts & ATA_STS_ERR ) cch += fprintf(pOut, " err");
75 return cch;
76}
77
78size_t AtaPrintError(FILE *pOut, uint8_t bErr)
79{
80 size_t cch = fprintf(pOut, "%#x", bErr);
81 if (bErr & ATA_ERR_RSVR ) cch += fprintf(pOut, " rsrv");
82 if (bErr & ATA_ERR_UNC ) cch += fprintf(pOut, " unc");
83 if (bErr & ATA_ERR_MC ) cch += fprintf(pOut, " mc");
84 if (bErr & ATA_ERR_IDNF ) cch += fprintf(pOut, " idnf");
85 if (bErr & ATA_ERR_MCR ) cch += fprintf(pOut, " mcr");
86 if (bErr & ATA_ERR_ABRT ) cch += fprintf(pOut, " abrt");
87 if (bErr & ATA_ERR_TKNONF) cch += fprintf(pOut, " tknonf");
88 if (bErr & ATA_ERR_AMNF ) cch += fprintf(pOut, " amnf");
89 return cch;
90}
91
92static int AtaError(uint8_t bSts, const char *pszFormat, ...)
93{
94 va_list va;
95
96 fprintf(stderr, "error: ");
97 va_start(va, pszFormat);
98 vfprintf(stderr, pszFormat, va);
99 va_end(va);
100
101 fprintf(stderr, "\n status=");
102 AtaPrintStatus(stderr, bSts);
103 fprintf(stderr, "\n error= ");
104 AtaPrintError(stderr, inp(ATA_REG_ERROR(g_uBasePort)));
105 fprintf(stderr, "\n");
106
107 return -1;
108}
109
110uint8_t AtaWaitBusy(void)
111{
112 uint32_t cLoops = 0;
113 uint8_t bStatus;
114 do
115 {
116 if ((++cLoops & 0xfffff) == 0)
117 fprintf(stderr, "AtaWaitBusyForData: cLoops=%#lx\n", cLoops);
118 bStatus = inp(ATA_REG_STATUS(g_uBasePort));
119 } while ((bStatus & (ATA_STS_BUSY | ATA_STS_ERR)) == ATA_STS_BUSY);
120 return bStatus;
121}
122
123uint8_t AtaWaitBusyDeviceReady(void)
124{
125 uint32_t cLoops = 0;
126 uint8_t bStatus;
127 do
128 {
129 if ((++cLoops & 0xfffff) == 0)
130 fprintf(stderr, "AtaWaitBusyForData: cLoops=%#lx\n", cLoops);
131 bStatus = inp(ATA_REG_STATUS(g_uBasePort));
132 } while ( (bStatus & (ATA_STS_BUSY | ATA_STS_DRDY)) != ATA_STS_DRDY
133 && !(bStatus & ATA_STS_ERR) );
134 return bStatus;
135}
136
137uint8_t AtaWaitBusyForData(void)
138{
139 uint32_t cLoops = 0;
140 uint8_t bStatus;
141 do
142 {
143 if ((++cLoops & 0xfffff) == 0)
144 fprintf(stderr, "AtaWaitBusyForData: cLoops=%#lx\n", cLoops);
145 bStatus = inp(ATA_REG_STATUS(g_uBasePort));
146 } while ( (bStatus & (ATA_STS_BUSY | ATA_STS_DRQ)) != ATA_STS_DRQ
147 && !(bStatus & ATA_STS_ERR) );
148 return bStatus;
149}
150
151uint8_t AtaSubmitCommandAndWait(uint8_t bCommand)
152{
153
154 outp(ATA_REG_COMMAND(g_uBasePort), bCommand);
155 ATA_DELAY_400NS();
156 return AtaWaitBusy();
157}
158
159uint8_t AtaSubmitCommandAndWaitForData(uint8_t bCommand)
160{
161
162 outp(ATA_REG_COMMAND(g_uBasePort), bCommand);
163 ATA_DELAY_400NS();
164 return AtaWaitBusyForData();
165}
166
167uint8_t AtaSelectDevice(uint8_t bDevice)
168{
169 outp(ATA_REG_DEVICE_SELECT(g_uBasePort), g_bDevice);
170 ATA_DELAY_400NS();
171 return AtaWaitBusyDeviceReady();
172}
173
174void AtaSetSectorAddress(uint32_t iSector, uint8_t bDevice)
175{
176 if (g_fUseLbaMode)
177 {
178 outp(ATA_REG_LBA_0_7(g_uBasePort), iSector & 0xff);
179 outp(ATA_REG_LBA_8_15(g_uBasePort), (iSector >> 8) & 0xff);
180 outp(ATA_REG_LBA_16_23(g_uBasePort), (iSector >> 16) & 0xff);
181 outp(ATA_REG_LBA_24_27_MODE(g_uBasePort), ((iSector >> 24) & 0x0f) | ATA_LBA_MODE | bDevice);
182 }
183 else
184 {
185 uint16_t iCyl = iSector / g_cSectorsPerCylinder;
186 uint16_t iRem = iSector % g_cSectorsPerCylinder;
187 uint8_t iHd = iRem / g_cSectorsPerTrack;
188 uint8_t iSec = iRem % g_cSectorsPerTrack;
189
190 outp(ATA_REG_SECTOR_NUMBER(g_uBasePort), iSec);
191 outp(ATA_REG_CYLINDER_LOW(g_uBasePort), iCyl & 0xff);
192 outp(ATA_REG_CYLINDER_HIGH(g_uBasePort), iCyl >> 8);
193 outp(ATA_REG_HEAD(g_uBasePort), iHd | bDevice);
194 }
195}
196
197void AtaReadData(void *pvBuf, size_t cb, uint8_t f8BitData)
198{
199 uint16_t uDataPort = ATA_REG_DATA(g_uBasePort);
200 uint16_t *pu16 = (uint16_t *)pvBuf;
201 cb >>= 1;
202
203 if (f8BitData == 1)
204 {
205 while (cb-- > 0)
206 {
207 uint8_t b1 = inp(uDataPort);
208 uint8_t b2 = inp(uDataPort);
209 *pu16++ = b1 | ((uint16_t)b2 << 8);
210 }
211 }
212 else
213 {
214 while (cb-- > 0)
215 *pu16++ = inpw(uDataPort);
216 }
217}
218
219void AtaWriteData(void const *pvBuf, size_t cb, uint8_t f8BitData)
220{
221 uint16_t register uDataPort = ATA_REG_DATA(g_uBasePort);
222 uint16_t const *pu16 = (uint16_t const *)pvBuf;
223
224 cb >>= 1;
225 if (f8BitData == 1)
226 {
227 while (cb-- > 0)
228 {
229 uint16_t register u16 = *pu16++;
230 outp(uDataPort, (uint8_t)u16);
231 outp(uDataPort, (uint8_t)(u16 >> 8));
232 }
233 }
234 else
235 while (cb-- > 0)
236 outpw(uDataPort, *pu16++);
237}
238
239int AtaReadSector(uint32_t iSector, void *pvBuf)
240{
241 uint8_t bSts = AtaWaitBusy();
242 if (bSts & ATA_STS_ERR)
243 return AtaError(bSts, "Prepping for reading sector %lu", iSector);
244
245 bSts = AtaSelectDevice(g_bDevice);
246 if (bSts & ATA_STS_ERR)
247 return AtaError(bSts, "Selecting device for reading sector %lu", iSector);
248
249 outp(ATA_REG_FEATURES(g_uBasePort), 0x0);
250 outp(ATA_REG_SECTOR_COUNT(g_uBasePort), 1);
251 AtaSetSectorAddress(iSector, g_bDevice);
252
253 bSts = AtaSubmitCommandAndWaitForData(ATA_CMD_READ_SECTORS);
254 if (bSts & ATA_STS_ERR)
255 return AtaError(bSts, "Reading sector %lu", iSector);
256
257 if (!(bSts & ATA_STS_DRQ))
258 return AtaError(bSts, "DRQ not set after reading sector %lu", iSector);
259
260 AtaReadData(pvBuf, 512, g_f8BitData);
261 bSts = inp(ATA_REG_STATUS(g_uBasePort));
262 if (bSts & ATA_STS_DRQ)
263 return AtaError(bSts, "DRQ is still set after reading sector %lu", iSector);
264 if (bSts & ATA_STS_ERR)
265 return AtaError(bSts, "ERR is set after reading sector %lu (#2)", iSector);
266 return 0;
267}
268
269int AtaWriteSector(uint32_t iSector, void const *pvBuf)
270{
271 uint8_t bSts = AtaWaitBusy();
272 if (bSts & ATA_STS_ERR)
273 return AtaError(bSts, "Prepping for writing sector %lu", iSector);
274
275 bSts = AtaSelectDevice(g_bDevice);
276 if (bSts & ATA_STS_ERR)
277 return AtaError(bSts, "Selecting device for writing sector %lu", iSector);
278
279 outp(ATA_REG_FEATURES(g_uBasePort), 0x0);
280 outp(ATA_REG_SECTOR_COUNT(g_uBasePort), 1);
281 AtaSetSectorAddress(iSector, g_bDevice);
282
283 bSts = AtaSubmitCommandAndWaitForData(ATA_CMD_WRITE_SECTORS);
284 if (bSts & ATA_STS_ERR)
285 return AtaError(bSts, "writing sector (#1) %lu", iSector);
286 if (!(bSts & ATA_STS_DRQ))
287 return AtaError(bSts, "DRQ not set after writing sector (#1) %lu", iSector);
288
289 AtaWriteData(pvBuf, 512, g_f8BitData);
290 ATA_DELAY_400NS();
291 bSts = AtaWaitBusy();
292 if (bSts & ATA_STS_ERR)
293 return AtaError(bSts, "writing sector (#2) %lu", iSector);
294 if (bSts & ATA_STS_DRQ)
295 return AtaError(bSts, "DRQ is set after writing sector (#2) %lu", iSector);
296
297 return 0;
298}
299
300
301/**
302 * @param pvBuf Pointer to a 512-byte buffer.
303 */
304int AtaReadBuffer(void *pvBuf, uint8_t fExtraChecks)
305{
306 uint8_t bSts;
307
308 if (!g_fSupportsReadBuffer)
309 return -2;
310
311 bSts = AtaWaitBusy();
312 if (bSts & ATA_STS_ERR)
313 return AtaError(bSts, "Prepping for reading buffer");
314
315 bSts = AtaSelectDevice(g_bDevice);
316 if (bSts & ATA_STS_ERR)
317 return AtaError(bSts, "Selecting device for reading buffer");
318
319 outp(ATA_REG_FEATURES(g_uBasePort), 0);
320 outp(ATA_REG_SECTOR_COUNT(g_uBasePort), 1); /* ignored */
321 outp(ATA_REG_SECTOR_NUMBER(g_uBasePort), 0);
322 outp(ATA_REG_CYLINDER_LOW(g_uBasePort), 0);
323 outp(ATA_REG_CYLINDER_HIGH(g_uBasePort), 0);
324
325 bSts = AtaSubmitCommandAndWaitForData(ATA_CMD_READ_BUFFER);
326 if (bSts & ATA_STS_ERR)
327 return AtaError(bSts, "Reading buffer");
328
329 if (!(bSts & ATA_STS_DRQ))
330 return AtaError(bSts, "DRQ not set after reading buffer");
331
332 if (!fExtraChecks)
333 AtaReadData(pvBuf, 512, g_f8BitData);
334 else
335 AtaReadData(pvBuf, 512, g_f8BitData);
336 bSts = inp(ATA_REG_STATUS(g_uBasePort));
337 if (bSts & ATA_STS_DRQ)
338 return AtaError(bSts, "DRQ is still set after reading buffer");
339 if (bSts & ATA_STS_ERR)
340 return AtaError(bSts, "ERR is set after reading buffer");
341 return 0;
342}
343
344int AtaWriteBuffer(void const *pvBuf, uint8_t fExtraChecks)
345{
346 uint8_t bSts;
347
348 if (!g_fSupportsWriteBuffer)
349 return -2;
350
351 bSts = AtaWaitBusy();
352 if (bSts & ATA_STS_ERR)
353 return AtaError(bSts, "Prepping for writing buffer");
354
355 bSts = AtaSelectDevice(g_bDevice);
356 if (bSts & ATA_STS_ERR)
357 return AtaError(bSts, "Selecting device for writing buffer");
358
359 outp(ATA_REG_FEATURES(g_uBasePort), 0);
360 outp(ATA_REG_SECTOR_COUNT(g_uBasePort), 1); /* ignored */
361 outp(ATA_REG_SECTOR_NUMBER(g_uBasePort), 0);
362 outp(ATA_REG_CYLINDER_LOW(g_uBasePort), 0);
363 outp(ATA_REG_CYLINDER_HIGH(g_uBasePort), 0);
364
365 bSts = AtaSubmitCommandAndWaitForData(ATA_CMD_WRITE_BUFFER);
366 if (bSts & ATA_STS_ERR)
367 return AtaError(bSts, "writing buffer (#1)");
368 if (!(bSts & ATA_STS_DRQ))
369 return AtaError(bSts, "DRQ not set after writing buffer (#1)");
370
371 if (!fExtraChecks)
372 AtaWriteData(pvBuf, 512, g_f8BitData);
373 else
374 AtaWriteData(pvBuf, 512, g_f8BitData);
375 ATA_DELAY_400NS();
376 bSts = AtaWaitBusy();
377 if (bSts & ATA_STS_ERR)
378 return AtaError(bSts, "writing buffer (#2)");
379 if (bSts & ATA_STS_DRQ)
380 return AtaError(bSts, "DRQ is set after writing buffer (#2)");
381
382 return 0;
383}
384
385int AtaIdentifyDevice(uint8_t bDevice, void *pvBuf)
386{
387 uint8_t bSts = AtaWaitBusy();
388 if (bSts & ATA_STS_ERR)
389 return AtaError(bSts, "Prepping for device %#x identification", bDevice);
390
391 bSts = AtaSelectDevice(g_bDevice);
392 if (bSts & ATA_STS_ERR)
393 return AtaError(bSts, "Selecting device %#x for identification", bDevice);
394
395 outp(ATA_REG_FEATURES(g_uBasePort), 0);
396 outp(ATA_REG_SECTOR_COUNT(g_uBasePort), 0);
397 outp(ATA_REG_SECTOR_NUMBER(g_uBasePort), 0);
398 outp(ATA_REG_CYLINDER_LOW(g_uBasePort), 0);
399 outp(ATA_REG_CYLINDER_HIGH(g_uBasePort), 0);
400 //outp(ATA_REG_HEAD(g_uBasePort), g_bDevice);
401
402 bSts = AtaSubmitCommandAndWaitForData(ATA_CMD_IDENTIFY_DEVICE);
403 if (bSts & ATA_STS_ERR)
404 return AtaError(bSts, "Device %#x identification", bDevice);
405 if (!(bSts & ATA_STS_DRQ))
406 return AtaError(bSts, "DRQ not set after device %#x identification", bDevice);
407
408 AtaReadData(pvBuf, 512, g_f8BitData);
409 return 0;
410}
411
412int AtaSetFeature(uint8_t bDevice, uint8_t bFeature, uint8_t bValue)
413{
414 uint8_t bSts = AtaWaitBusy();
415 if (bSts & ATA_STS_ERR)
416 return AtaError(bSts, "Prepping for setting device %#x feature %#x (%#x)", bDevice, bFeature, bValue);
417
418 bSts = AtaSelectDevice(g_bDevice);
419 if (bSts & ATA_STS_ERR)
420 return AtaError(bSts, "Selecting device %#x for setting feature %#x (%#x)", bDevice, bFeature, bValue);
421
422 outp(ATA_REG_FEATURES(g_uBasePort), bFeature);
423 outp(ATA_REG_SECTOR_COUNT(g_uBasePort), 0);
424 outp(ATA_REG_SECTOR_NUMBER(g_uBasePort), bValue);
425 outp(ATA_REG_CYLINDER_LOW(g_uBasePort), 0);
426 outp(ATA_REG_CYLINDER_HIGH(g_uBasePort), 0);
427 //outp(ATA_REG_HEAD(g_uBasePort), g_bDevice);
428
429 bSts = AtaSubmitCommandAndWait(ATA_CMD_SET_FEATURES);
430 if (bSts & ATA_STS_ERR)
431 return AtaError(bSts, "Setting device %#x feature %#x (%#x)", bDevice, bFeature, bValue);
432 if (bSts & ATA_STS_DRQ)
433 return AtaError(bSts, "DRQ is set after setting device %#x feature %#x (%#x)", bDevice, bFeature, bValue);
434 return 0;
435}
436
437int AtaInitDeviceParams(uint8_t bDevice, uint8_t cSectorsPerTrack, uint8_t cHeads)
438{
439 uint8_t bSts = AtaWaitBusy();
440 if (bSts & ATA_STS_ERR)
441 return AtaError(bSts, "Prepping for device %#x parameter initialization", bDevice);
442
443 bSts = AtaSelectDevice(g_bDevice);
444 if (bSts & ATA_STS_ERR)
445 return AtaError(bSts, "Selecting device for device %#x parameter initialization", bDevice);
446
447 outp(ATA_REG_FEATURES(g_uBasePort), 0);
448 outp(ATA_REG_SECTOR_COUNT(g_uBasePort), cSectorsPerTrack);
449 outp(ATA_REG_SECTOR_NUMBER(g_uBasePort), 0);
450 outp(ATA_REG_CYLINDER_LOW(g_uBasePort), 0);
451 outp(ATA_REG_CYLINDER_HIGH(g_uBasePort), 0);
452 outp(ATA_REG_HEAD(g_uBasePort), g_bDevice | cHeads);
453
454 bSts = AtaSubmitCommandAndWait(ATA_CMD_INIT_DEVICE_PARAMS);
455 if (bSts & ATA_STS_ERR)
456 return AtaError(bSts, "Device %#x parameter initialization", bDevice);
457 if (bSts & ATA_STS_DRQ)
458 return AtaError(bSts, "DRQ is set after device %#x parameter initialization", bDevice);
459 return 0;
460}
461
462int AtaReset(void)
463{
464 uint8_t bSts;
465
466 /* Set the reset flat. */
467 outp(ATA_REG_CONTROL(g_uBasePort), ATA_CTL_SRST);
468/** @todo This still needs work - it doesn't work when ERR is set. */
469
470 /* Wait for the busy flag response. */
471 for (bSts = 0; bSts < 20; bSts++)
472 ATA_DELAY_400NS();
473 while (!(bSts = inp(ATA_REG_STATUS(g_uBasePort))) & ATA_STS_BUSY)
474 ATA_DELAY_400NS();
475
476 /* Clear the reset flag. */
477 outp(ATA_REG_CONTROL(g_uBasePort), 0);
478 ATA_DELAY_400NS();
479
480 /* Wait for the controller to become non-busy. */
481 bSts = AtaWaitBusy();
482 if (bSts & ATA_STS_ERR)
483 return AtaError(bSts, "Software reset failed");
484 return 0;
485}
486
487int AtaReInit(void)
488{
489 int rc;
490
491 /* Reset the controller + devices. */
492 if (AtaReset() != 0)
493 return -1;
494
495 if (g_fSupportsSetFeature8BitData)
496 {
497 if (g_f8BitData)
498 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_EN_8BIT_DATA, 0);
499 else
500 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_DI_8BIT_DATA, 0);
501 if (rc != 0)
502 return rc;
503 }
504
505 /* Try disable write cache. */
506 if (g_fSupportsSetFeatureWriteCache)
507 {
508 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_DI_WRITE_CACHE, 0);
509 if (rc != 0)
510 return rc;
511 }
512
513 /* Select PIO mode without IORDY. */
514 if (g_fSupportsSetFeatureXferMode)
515 {
516 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_SET_XFERMODE, ATA_FV_XFERMODE_PIO_MODE_DEFAULT_NO_IORDY);
517 if (rc != 0)
518 return rc;
519 }
520
521 return 0;
522}
523
524int AtaInit(uint16_t uBasePort, uint16_t uCtrlPort, uint8_t cPortShift, uint8_t bDevice, uint8_t f8BitData, uint8_t fReset)
525{
526 int rc;
527 uint8_t bSts, bStsAlt;
528
529 g_uBasePort = uBasePort;
530 g_uCtrlPort = uCtrlPort;
531 g_cPortShift = cPortShift;
532 g_bDevice = bDevice;
533 g_f8BitData = f8BitData;
534 g_fSupportsSetFeature8BitData = 1;
535 g_fSupportsSetFeatureWriteCache = 1;
536 g_fSupportsSetFeatureXferMode = 1;
537
538 /* Check whether the two status registers match up. If they don't we
539 probably don't have a controller at this address. */
540 inp(ATA_REG_STATUS(g_uBasePort));
541 bSts = inp(ATA_REG_STATUS(g_uBasePort));
542 bStsAlt = inp(ATA_REG_ALT_STATUS(g_uCtrlPort));
543 if (bSts != bStsAlt || bSts == 0xff)
544 {
545 fprintf(stderr, "Status register differs or is 0xff\n");
546 fprintf(stderr, " port %#05x status=", ATA_REG_STATUS(g_uBasePort));
547 AtaPrintStatus(stderr, bSts);
548 fprintf(stderr, "\n");
549 fprintf(stderr, " port %#05x alt status=", ATA_REG_ALT_STATUS(g_uCtrlPort));
550 AtaPrintStatus(stderr, bStsAlt);
551 fprintf(stderr, "\n");
552 return -1;
553 }
554 printf("Pre init status=");
555 AtaPrintStatus(stdout, bSts);
556 printf("\n");
557
558 for (;;)
559 {
560 /* Reset the controller + devices. */
561 if (fReset)
562 if (AtaReset() != 0)
563 return -1;
564 fReset = 1;
565
566 /* Enable 8-bit data transfers (just to be on the safe side). */
567 if (g_fSupportsSetFeature8BitData)
568 {
569 if (g_f8BitData)
570 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_EN_8BIT_DATA, 0);
571 else
572 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_DI_8BIT_DATA, 0);
573 if (rc != 0)
574 {
575 fprintf(stderr,
576 f8BitData
577 ? "warning: ATA_FEATURE_EN_8BIT_DATA failed, assuming not supported. Retrying in 16-bit mode."
578 : "warning: ATA_FEATURE_DI_8BIT_DATA failed, assuming not supported. Retrying.");
579 g_fSupportsSetFeature8BitData = 0;
580 g_f8BitData = 0;
581 continue;
582 }
583 }
584
585 /* Try disable write cache. */
586 if (g_fSupportsSetFeatureWriteCache)
587 {
588 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_DI_WRITE_CACHE, 0);
589 if (rc != 0)
590 {
591 fprintf(stderr, "warning: ATA_FEATURE_DI_WRITE_CACHE failed, assuming not supported. Retrying.");
592 g_fSupportsSetFeatureWriteCache = 0;
593 continue;
594 }
595 }
596
597 /* Select PIO mode without IORDY. */
598 if (g_fSupportsSetFeatureXferMode)
599 {
600 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_SET_XFERMODE, ATA_FV_XFERMODE_PIO_MODE_DEFAULT_NO_IORDY);
601 if (rc != 0)
602 {
603 fprintf(stderr, "warning: ATA_FEATURE_SET_XFERMODE = DEFAULT_NO_IORDY failed, assuming not supported. Retrying.");
604 g_fSupportsSetFeatureXferMode = 0;
605 continue;
606 }
607 }
608
609 /* Identify the device. */
610 memset(g_awIdentify, 0, sizeof(g_awIdentify));
611 if (AtaIdentifyDevice(g_bDevice, g_awIdentify) != 0)
612 return -1;
613
614 /** @todo this is rather simple... */
615 g_cCylinders = g_awIdentify[1];
616 g_cHeads = g_awIdentify[3];
617 g_cSectorsPerTrack = g_awIdentify[6];
618 g_cSectorsPerCylinder = g_cHeads * g_cSectorsPerTrack;
619 printf("Device %#x at %#x/%#x: %u cylinders, %u heads, %u sectors, %s data\n",
620 g_bDevice, g_uBasePort, g_uCtrlPort, g_cCylinders, g_cHeads, g_cSectorsPerTrack,
621 g_f8BitData ? "8-bit" : "16-bit");
622
623 /* Figure 5-9 in SanDisk Manual Rev 12.0: */
624 if ( g_awIdentify[82] != 0 && g_awIdentify[82] != UINT16_C(0xffff)
625 && g_awIdentify[83] != 0 && g_awIdentify[83] != UINT16_C(0xffff)
626 && g_awIdentify[84] != 0 && g_awIdentify[84] != UINT16_C(0xffff)
627 && (g_awIdentify[83] & UINT16_C(0xc000)) == UINT16_C(0x4000)
628 && (g_awIdentify[84] & UINT16_C(0xc000)) == UINT16_C(0x4000) )
629 {
630 g_fSupportsWriteBuffer = (g_awIdentify[82] & UINT16_C(0x1000)) != 0;
631 g_fSupportsReadBuffer = (g_awIdentify[82] & UINT16_C(0x2000)) != 0;
632 }
633 printf(" %s WRITE_BUFFER, %s READ_BUFFER\n",
634 g_fSupportsWriteBuffer == 1 ? "have" : g_fSupportsWriteBuffer == 0 ? "no" : "uncertain",
635 g_fSupportsReadBuffer == 1 ? "have" : g_fSupportsReadBuffer == 0 ? "no" : "uncertain");
636 break;
637 }
638
639 return 0;
640}
641
642int AtaArgMatchWithValue(const char *pszArg, const char *pszMatch, size_t cchMatch,
643 int cArgs, char **papszArgs, int *piArg, const char **ppszValue)
644{
645 if (strncmp(pszArg, pszMatch, cchMatch) == 0)
646 {
647 pszArg += cchMatch;
648 if (!*pszArg)
649 {
650 if (*piArg < cArgs)
651 {
652 *ppszValue = papszArgs[*piArg];
653 *piArg += 1;
654 }
655 else
656 {
657 fprintf(stderr, "syntax error: Option '%s' is missing argument value\n", pszMatch);
658 *ppszValue = NULL;
659 }
660 return 1;
661 }
662
663 if (*pszArg == ':' || *pszArg == '=')
664 {
665 if (!*pszArg)
666 fprintf(stderr, "syntax error: Option '%s' is missing argument value\n", pszMatch);
667 *ppszValue = pszArg;
668 return 1;
669 }
670 }
671
672 return 0;
673}
674
675int AtaInitFromArgv(int iArg, int cArgs, char **papszArgs)
676{
677 uint8_t bDevice = ATA_DEV_MASTER;
678 uint8_t fReset = 0;
679#if 0
680 uint16_t uBasePort = 0x1f0; /* Primary ATA host controller. */
681 uint16_t uCtrlPort = 0x3f0; /* The control block of the primary ATA host controller. */
682 uint8_t cShiftPort = 0;
683 uint8_t f8BitData = 0;
684#else
685 uint16_t uBasePort = 0x300; /* Lo-tech CF-lite. */
686 uint16_t uCtrlPort = 0x310; /* Lo-tech CF-lite. */
687 uint8_t cShiftPort = 1; /* Special Lo-tech CF-lite hack. */
688 uint8_t f8BitData = 1;
689#endif
690
691 while (iArg < cArgs)
692 {
693 const char *pszArg = papszArgs[iArg++];
694 const char *pszValue;
695 int iWhich = 0;
696 if ( (iWhich = AtaArgMatchWithValue(pszArg, STR_TUPLE("--base-port"), cArgs, papszArgs, &iArg, &pszValue))
697 || (iWhich = AtaArgMatchWithValue(pszArg, STR_TUPLE("-b"), cArgs, papszArgs, &iArg, &pszValue))
698 || (iWhich = AtaArgMatchWithValue(pszArg, STR_TUPLE("--ctrl-port"), cArgs, papszArgs, &iArg, &pszValue) * 2)
699 || (iWhich = AtaArgMatchWithValue(pszArg, STR_TUPLE("-c"), cArgs, papszArgs, &iArg, &pszValue) * 2) )
700 {
701 unsigned long uTmp = strtoul(pszValue, NULL, 16);
702 if (uTmp < 16 || uTmp >= 1024)
703 {
704 fprintf(stderr, "error: Invalid port number %#lx for %s (valid range 0x010..0x3ff)\n", uTmp, pszArg);
705 return -1;
706 }
707 if (iWhich == 1)
708 uBasePort = (uint16_t)uTmp;
709 else
710 uCtrlPort = (uint16_t)uTmp;
711 }
712 else if ( AtaArgMatchWithValue(pszArg, STR_TUPLE("--port-shift"), cArgs, papszArgs, &iArg, &pszValue)
713 || AtaArgMatchWithValue(pszArg, STR_TUPLE("-s"), cArgs, papszArgs, &iArg, &pszValue) )
714 {
715 unsigned long uTmp = strtoul(pszValue, NULL, 0);
716 if (uTmp >= 4)
717 {
718 fprintf(stderr, "error: Invalid port shift number %#lx (valid range 0..3)\n", uTmp);
719 return -1;
720 }
721 cShiftPort = (uint8_t)uTmp;
722 }
723 else if ( AtaArgMatchWithValue(pszArg, STR_TUPLE("--device"), cArgs, papszArgs, &iArg, &pszValue)
724 || AtaArgMatchWithValue(pszArg, STR_TUPLE("-d"), cArgs, papszArgs, &iArg, &pszValue) )
725 {
726 unsigned long uTmp = strtoul(pszValue, NULL, 16);
727 if ( uTmp != ATA_DEV_MASTER
728 && uTmp != ATA_DEV_SLAVE)
729 {
730 fprintf(stderr, "error: Invalid device number %#lx; only %#x (master) or %#x (slave) are allowed.\n",
731 uTmp, ATA_DEV_MASTER, ATA_DEV_SLAVE);
732 return -1;
733 }
734 bDevice = (uint8_t)uTmp;
735 }
736 else if ( strcmp(pszArg, "--8-bit-data") == 0
737 || strcmp(pszArg, "-8") == 0)
738 f8BitData = 1;
739 else if ( strcmp(pszArg, "--8-bit-data-plus") == 0
740 || strcmp(pszArg, "-8+") == 0)
741 f8BitData = 3;
742 else if ( strcmp(pszArg, "--16-bit-data") == 0
743 || strcmp(pszArg, "-16") == 0)
744 f8BitData = 0;
745 else if (strcmp(pszArg, "--reset") == 0)
746 fReset = 1;
747 else if (strcmp(pszArg, "--no-reset") == 0)
748 fReset = 0;
749 else if (strcmp(pszArg, "--ide") == 0)
750 {
751 /* Normal IDE, primary. */
752 uBasePort = 0x1f0;
753 uCtrlPort = 0x3f0;
754 cShiftPort = 0;
755 f8BitData = 0;
756 }
757 else if (strcmp(pszArg, "--xt-cf") == 0)
758 {
759 /* Lo-tech CF-lite. */
760 uBasePort = 0x300;
761 uCtrlPort = 0x310;
762 cShiftPort = 1;
763 f8BitData = 1;
764 }
765 }
766
767 return AtaInit(uBasePort, uCtrlPort, cShiftPort, bDevice, f8BitData, fReset);
768}
769
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