VirtualBox

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

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

xtide util hacking.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 24.5 KB
Line 
1/* $Id: atalib.c 73 2015-12-20 21:17:34Z 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;
45uint16_t g_uPortShift;
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)
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)
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_SECTORS);
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
469 /* Wait for the busy flag response. */
470 ATA_DELAY_400NS();
471 ATA_DELAY_400NS();
472 while (!(bSts = inp(ATA_REG_STATUS(g_uBasePort))) & ATA_STS_BUSY)
473 ATA_DELAY_400NS();
474
475 /* Clear the reset flag. */
476 outp(ATA_REG_CONTROL(g_uBasePort), 0);
477 ATA_DELAY_400NS();
478
479 /* Wait for the controller to become non-busy. */
480 bSts = AtaWaitBusy();
481 if (bSts & ATA_STS_ERR)
482 return AtaError(bSts, "Software reset failed");
483 return 0;
484}
485
486int AtaReInit(void)
487{
488 int rc;
489
490 /* Reset the controller + devices. */
491 if (AtaReset() != 0)
492 return -1;
493
494 if (g_fSupportsSetFeature8BitData)
495 {
496 if (g_f8BitData)
497 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_EN_8BIT_DATA, 0);
498 else
499 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_DI_8BIT_DATA, 0);
500 if (rc != 0)
501 return rc;
502 }
503
504 /* Try disable write cache. */
505 if (g_fSupportsSetFeatureWriteCache)
506 {
507 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_DI_WRITE_CACHE, 0);
508 if (rc != 0)
509 return rc;
510 }
511
512 /* Select PIO mode without IORDY. */
513 if (g_fSupportsSetFeatureXferMode)
514 {
515 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_SET_XFERMODE, ATA_FV_XFERMODE_PIO_MODE_DEFAULT_NO_IORDY);
516 if (rc != 0)
517 return rc;
518 }
519
520 return 0;
521}
522
523int AtaInit(uint16_t uBasePort, uint16_t uCtrlPort, uint8_t uPortShift, uint8_t bDevice, uint8_t f8BitData)
524{
525 int rc;
526 uint8_t bSts, bStsAlt;
527
528 g_uBasePort = uBasePort;
529 g_uCtrlPort = uCtrlPort;
530 g_uPortShift = uPortShift;
531 g_bDevice = bDevice;
532 g_f8BitData = f8BitData;
533 g_fSupportsSetFeature8BitData = 1;
534 g_fSupportsSetFeatureWriteCache = 1;
535 g_fSupportsSetFeatureXferMode = 1;
536
537 /* Check whether the two status registers match up. If they don't we
538 probably don't have a controller at this address. */
539 inp(ATA_REG_STATUS(g_uBasePort));
540 bSts = inp(ATA_REG_STATUS(g_uBasePort));
541 bStsAlt = inp(ATA_REG_ALT_STATUS(g_uBasePort));
542 if (bSts != bStsAlt || bSts == 0xff)
543 {
544 fprintf(stderr, "Status register differs or is 0xff\n");
545 fprintf(stderr, " status=");
546 AtaPrintStatus(stdout, bSts);
547 fprintf(stderr, "\n");
548 fprintf(stderr, " alt status=");
549 AtaPrintStatus(stdout, bStsAlt);
550 fprintf(stderr, "\n");
551 return -1;
552 }
553 printf("Pre init status=");
554 AtaPrintStatus(stdout, bSts);
555 printf("\n");
556
557 for (;;)
558 {
559 /* Reset the controller + devices. */
560 if (AtaReset() != 0)
561 return -1;
562
563 /* Enable 8-bit data transfers (just to be on the safe side). */
564 if (g_fSupportsSetFeature8BitData)
565 {
566 if (g_f8BitData)
567 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_EN_8BIT_DATA, 0);
568 else
569 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_DI_8BIT_DATA, 0);
570 if (rc != 0)
571 {
572 fprintf(stderr,
573 f8BitData
574 ? "warning: ATA_FEATURE_EN_8BIT_DATA failed, assuming not supported. Retrying in 16-bit mode."
575 : "warning: ATA_FEATURE_DI_8BIT_DATA failed, assuming not supported. Retrying.");
576 g_fSupportsSetFeature8BitData = 0;
577 g_f8BitData = 0;
578 continue;
579 }
580 }
581
582 /* Try disable write cache. */
583 if (g_fSupportsSetFeatureWriteCache)
584 {
585 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_DI_WRITE_CACHE, 0);
586 if (rc != 0)
587 {
588 fprintf(stderr, "warning: ATA_FEATURE_DI_WRITE_CACHE failed, assuming not supported. Retrying.");
589 g_fSupportsSetFeatureWriteCache = 0;
590 continue;
591 }
592 }
593
594 /* Select PIO mode without IORDY. */
595 if (g_fSupportsSetFeatureXferMode)
596 {
597 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_SET_XFERMODE, ATA_FV_XFERMODE_PIO_MODE_DEFAULT_NO_IORDY);
598 if (rc != 0)
599 {
600 fprintf(stderr, "warning: ATA_FEATURE_SET_XFERMODE = DEFAULT_NO_IORDY failed, assuming not supported. Retrying.");
601 g_fSupportsSetFeatureXferMode = 0;
602 continue;
603 }
604 }
605
606 /* Identify the device. */
607 memset(g_awIdentify, 0, sizeof(g_awIdentify));
608 if (AtaIdentifyDevice(g_bDevice, g_awIdentify) != 0)
609 return -1;
610
611 /** @todo this is rather simple... */
612 g_cCylinders = g_awIdentify[1];
613 g_cHeads = g_awIdentify[3];
614 g_cSectorsPerTrack = g_awIdentify[6];
615 g_cSectorsPerCylinder = g_cHeads * g_cSectorsPerTrack;
616 printf("Device %#x at %#x/%#x: %u cylinders, %u heads, %u sectors, %s data\n",
617 g_bDevice, g_uBasePort, g_uCtrlPort, g_cCylinders, g_cHeads, g_cSectorsPerTrack,
618 g_f8BitData ? "8-bit" : "16-bit");
619
620 /* Figure 5-9 in SanDisk Manual Rev 12.0: */
621 if ( (g_awIdentify[83] & UINT16_C(0xc00)) == UINT16_C(0x4000)
622 && (g_awIdentify[84] & UINT16_C(0xc00)) == UINT16_C(0x4000))
623 {
624 g_fSupportsWriteBuffer = (g_awIdentify[82] & UINT16_C(0x1000)) != 0;
625 g_fSupportsReadBuffer = (g_awIdentify[82] & UINT16_C(0x2000)) != 0;
626 }
627 printf(" %s WRITE_BUFFER, %s READ_BUFFER\n",
628 g_fSupportsWriteBuffer == 1 ? "have" : g_fSupportsWriteBuffer == 0 ? "no" : "uncertain",
629 g_fSupportsReadBuffer == 1 ? "have" : g_fSupportsReadBuffer == 0 ? "no" : "uncertain");
630 }
631
632 return 0;
633}
634
635int AtaArgMatchWithValue(const char *pszArg, const char *pszMatch, size_t cchMatch,
636 int cArgs, char **papszArgs, int *piArg, const char **ppszValue)
637{
638 if (strncmp(pszArg, pszMatch, cchMatch) == 0)
639 {
640 pszArg += cchMatch;
641 if (!*pszArg)
642 {
643 if (*piArg < cArgs)
644 {
645 *ppszValue = papszArgs[*piArg];
646 *piArg += 1;
647 }
648 else
649 {
650 fprintf(stderr, "syntax error: Option '%s' is missing argument value\n", pszMatch);
651 *ppszValue = NULL;
652 }
653 return 1;
654 }
655
656 if (*pszArg == ':' || *pszArg == '=')
657 {
658 if (!*pszArg)
659 fprintf(stderr, "syntax error: Option '%s' is missing argument value\n", pszMatch);
660 *ppszValue = pszArg;
661 return 1;
662 }
663 }
664
665 return 0;
666}
667
668int AtaInitFromArgv(int iArg, int cArgs, char **papszArgs)
669{
670 uint8_t bDevice = ATA_DEV_MASTER;
671#if 0
672 uint16_t uBasePort = 0x1f0; /* Primary ATA host controller. */
673 uint16_t uCtrlPort = 0x3f0; /* The control block of the primary ATA host controller. */
674 uint8_t cShiftPort = 0;
675 uint8_t f8BitData = 0;
676#else
677 uint16_t uBasePort = 0x300; /* Lo-tech CF-lite. */
678 uint16_t uCtrlPort = 0x310; /* Lo-tech CF-lite. */
679 uint8_t cShiftPort = 1; /* Special Lo-tech CF-lite hack. */
680 uint8_t f8BitData = 1;
681#endif
682
683 while (iArg < cArgs)
684 {
685 const char *pszArg = papszArgs[iArg++];
686 const char *pszValue;
687 int iWhich = 0;
688 if ( (iWhich = AtaArgMatchWithValue(pszArg, STR_TUPLE("--base-port"), cArgs, papszArgs, &iArg, &pszValue))
689 || (iWhich = AtaArgMatchWithValue(pszArg, STR_TUPLE("-b"), cArgs, papszArgs, &iArg, &pszValue))
690 || (iWhich = AtaArgMatchWithValue(pszArg, STR_TUPLE("--ctrl-port"), cArgs, papszArgs, &iArg, &pszValue) * 2)
691 || (iWhich = AtaArgMatchWithValue(pszArg, STR_TUPLE("-c"), cArgs, papszArgs, &iArg, &pszValue) * 2) )
692 {
693 unsigned long uTmp = strtoul(pszValue, NULL, 16);
694 if (uTmp < 16 || uTmp >= 1024)
695 {
696 fprintf(stderr, "error: Invalid port number %#lx for %s (valid range 0x010..0x3ff)\n", uTmp, pszArg);
697 return -1;
698 }
699 if (iWhich == 1)
700 uBasePort = (uint16_t)uTmp;
701 else
702 uCtrlPort = (uint16_t)uTmp;
703 }
704 else if ( AtaArgMatchWithValue(pszArg, STR_TUPLE("--port-shift"), cArgs, papszArgs, &iArg, &pszValue)
705 || AtaArgMatchWithValue(pszArg, STR_TUPLE("-s"), cArgs, papszArgs, &iArg, &pszValue) )
706 {
707 unsigned long uTmp = strtoul(pszValue, NULL, 0);
708 if (uTmp >= 4)
709 {
710 fprintf(stderr, "error: Invalid port shift number %#lx (valid range 0..3)\n", uTmp);
711 return -1;
712 }
713 cShiftPort = (uint8_t)uTmp;
714 }
715 else if ( AtaArgMatchWithValue(pszArg, STR_TUPLE("--device"), cArgs, papszArgs, &iArg, &pszValue)
716 || AtaArgMatchWithValue(pszArg, STR_TUPLE("-d"), cArgs, papszArgs, &iArg, &pszValue) )
717 {
718 unsigned long uTmp = strtoul(pszValue, NULL, 16);
719 if ( uTmp != ATA_DEV_MASTER
720 && uTmp != ATA_DEV_SLAVE)
721 {
722 fprintf(stderr, "error: Invalid device number %#lx; only %#x (master) or %#x (slave) are allowed.\n",
723 uTmp, ATA_DEV_MASTER, ATA_DEV_SLAVE);
724 return -1;
725 }
726 bDevice = (uint8_t)uTmp;
727 }
728 else if ( strcmp(pszArg, "--8-bit-data") == 0
729 || strcmp(pszArg, "-8") == 0)
730 f8BitData = 1;
731 else if ( strcmp(pszArg, "--16-bit-data") == 0
732 || strcmp(pszArg, "-16") == 0)
733 f8BitData = 0;
734 }
735
736 return AtaInit(uBasePort, uCtrlPort, cShiftPort, bDevice, f8BitData);
737}
738
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