VirtualBox

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

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

xtide util hacking, included bios patch.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 25.6 KB
Line 
1/* $Id: atalib.c 74 2015-12-21 00:40:51Z 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)
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 (AtaReset() != 0)
562 return -1;
563
564 /* Enable 8-bit data transfers (just to be on the safe side). */
565 if (g_fSupportsSetFeature8BitData)
566 {
567 if (g_f8BitData)
568 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_EN_8BIT_DATA, 0);
569 else
570 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_DI_8BIT_DATA, 0);
571 if (rc != 0)
572 {
573 fprintf(stderr,
574 f8BitData
575 ? "warning: ATA_FEATURE_EN_8BIT_DATA failed, assuming not supported. Retrying in 16-bit mode."
576 : "warning: ATA_FEATURE_DI_8BIT_DATA failed, assuming not supported. Retrying.");
577 g_fSupportsSetFeature8BitData = 0;
578 g_f8BitData = 0;
579 continue;
580 }
581 }
582
583 /* Try disable write cache. */
584 if (g_fSupportsSetFeatureWriteCache)
585 {
586 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_DI_WRITE_CACHE, 0);
587 if (rc != 0)
588 {
589 fprintf(stderr, "warning: ATA_FEATURE_DI_WRITE_CACHE failed, assuming not supported. Retrying.");
590 g_fSupportsSetFeatureWriteCache = 0;
591 continue;
592 }
593 }
594
595 /* Select PIO mode without IORDY. */
596 if (g_fSupportsSetFeatureXferMode)
597 {
598 rc = AtaSetFeature(g_bDevice, ATA_FEATURE_SET_XFERMODE, ATA_FV_XFERMODE_PIO_MODE_DEFAULT_NO_IORDY);
599 if (rc != 0)
600 {
601 fprintf(stderr, "warning: ATA_FEATURE_SET_XFERMODE = DEFAULT_NO_IORDY failed, assuming not supported. Retrying.");
602 g_fSupportsSetFeatureXferMode = 0;
603 continue;
604 }
605 }
606
607 /* Identify the device. */
608 memset(g_awIdentify, 0, sizeof(g_awIdentify));
609 if (AtaIdentifyDevice(g_bDevice, g_awIdentify) != 0)
610 return -1;
611
612 /** @todo this is rather simple... */
613 g_cCylinders = g_awIdentify[1];
614 g_cHeads = g_awIdentify[3];
615 g_cSectorsPerTrack = g_awIdentify[6];
616 g_cSectorsPerCylinder = g_cHeads * g_cSectorsPerTrack;
617 printf("Device %#x at %#x/%#x: %u cylinders, %u heads, %u sectors, %s data\n",
618 g_bDevice, g_uBasePort, g_uCtrlPort, g_cCylinders, g_cHeads, g_cSectorsPerTrack,
619 g_f8BitData ? "8-bit" : "16-bit");
620
621 /* Figure 5-9 in SanDisk Manual Rev 12.0: */
622printf("debug: word82=%#x word83=%#x word84=%#x\n", g_awIdentify[82], g_awIdentify[83], g_awIdentify[84]);
623 if ( g_awIdentify[82] != 0 && g_awIdentify[82] != UINT16_C(0xffff)
624 && g_awIdentify[83] != 0 && g_awIdentify[83] != UINT16_C(0xffff)
625 && g_awIdentify[84] != 0 && g_awIdentify[84] != UINT16_C(0xffff)
626 && (g_awIdentify[83] & UINT16_C(0xc000)) == UINT16_C(0x4000)
627 && (g_awIdentify[84] & UINT16_C(0xc000)) == UINT16_C(0x4000) )
628 {
629 g_fSupportsWriteBuffer = (g_awIdentify[82] & UINT16_C(0x1000)) != 0;
630 g_fSupportsReadBuffer = (g_awIdentify[82] & UINT16_C(0x2000)) != 0;
631 }
632 printf(" %s WRITE_BUFFER, %s READ_BUFFER\n",
633 g_fSupportsWriteBuffer == 1 ? "have" : g_fSupportsWriteBuffer == 0 ? "no" : "uncertain",
634 g_fSupportsReadBuffer == 1 ? "have" : g_fSupportsReadBuffer == 0 ? "no" : "uncertain");
635 break;
636 }
637
638 return 0;
639}
640
641int AtaArgMatchWithValue(const char *pszArg, const char *pszMatch, size_t cchMatch,
642 int cArgs, char **papszArgs, int *piArg, const char **ppszValue)
643{
644 if (strncmp(pszArg, pszMatch, cchMatch) == 0)
645 {
646 pszArg += cchMatch;
647 if (!*pszArg)
648 {
649 if (*piArg < cArgs)
650 {
651 *ppszValue = papszArgs[*piArg];
652 *piArg += 1;
653 }
654 else
655 {
656 fprintf(stderr, "syntax error: Option '%s' is missing argument value\n", pszMatch);
657 *ppszValue = NULL;
658 }
659 return 1;
660 }
661
662 if (*pszArg == ':' || *pszArg == '=')
663 {
664 if (!*pszArg)
665 fprintf(stderr, "syntax error: Option '%s' is missing argument value\n", pszMatch);
666 *ppszValue = pszArg;
667 return 1;
668 }
669 }
670
671 return 0;
672}
673
674int AtaInitFromArgv(int iArg, int cArgs, char **papszArgs)
675{
676 uint8_t bDevice = ATA_DEV_MASTER;
677#if 0
678 uint16_t uBasePort = 0x1f0; /* Primary ATA host controller. */
679 uint16_t uCtrlPort = 0x3f0; /* The control block of the primary ATA host controller. */
680 uint8_t cShiftPort = 0;
681 uint8_t f8BitData = 0;
682#else
683 uint16_t uBasePort = 0x300; /* Lo-tech CF-lite. */
684 uint16_t uCtrlPort = 0x310; /* Lo-tech CF-lite. */
685 uint8_t cShiftPort = 1; /* Special Lo-tech CF-lite hack. */
686 uint8_t f8BitData = 1;
687#endif
688
689 while (iArg < cArgs)
690 {
691 const char *pszArg = papszArgs[iArg++];
692 const char *pszValue;
693 int iWhich = 0;
694 if ( (iWhich = AtaArgMatchWithValue(pszArg, STR_TUPLE("--base-port"), cArgs, papszArgs, &iArg, &pszValue))
695 || (iWhich = AtaArgMatchWithValue(pszArg, STR_TUPLE("-b"), cArgs, papszArgs, &iArg, &pszValue))
696 || (iWhich = AtaArgMatchWithValue(pszArg, STR_TUPLE("--ctrl-port"), cArgs, papszArgs, &iArg, &pszValue) * 2)
697 || (iWhich = AtaArgMatchWithValue(pszArg, STR_TUPLE("-c"), cArgs, papszArgs, &iArg, &pszValue) * 2) )
698 {
699 unsigned long uTmp = strtoul(pszValue, NULL, 16);
700 if (uTmp < 16 || uTmp >= 1024)
701 {
702 fprintf(stderr, "error: Invalid port number %#lx for %s (valid range 0x010..0x3ff)\n", uTmp, pszArg);
703 return -1;
704 }
705 if (iWhich == 1)
706 uBasePort = (uint16_t)uTmp;
707 else
708 uCtrlPort = (uint16_t)uTmp;
709 }
710 else if ( AtaArgMatchWithValue(pszArg, STR_TUPLE("--port-shift"), cArgs, papszArgs, &iArg, &pszValue)
711 || AtaArgMatchWithValue(pszArg, STR_TUPLE("-s"), cArgs, papszArgs, &iArg, &pszValue) )
712 {
713 unsigned long uTmp = strtoul(pszValue, NULL, 0);
714 if (uTmp >= 4)
715 {
716 fprintf(stderr, "error: Invalid port shift number %#lx (valid range 0..3)\n", uTmp);
717 return -1;
718 }
719 cShiftPort = (uint8_t)uTmp;
720 }
721 else if ( AtaArgMatchWithValue(pszArg, STR_TUPLE("--device"), cArgs, papszArgs, &iArg, &pszValue)
722 || AtaArgMatchWithValue(pszArg, STR_TUPLE("-d"), cArgs, papszArgs, &iArg, &pszValue) )
723 {
724 unsigned long uTmp = strtoul(pszValue, NULL, 16);
725 if ( uTmp != ATA_DEV_MASTER
726 && uTmp != ATA_DEV_SLAVE)
727 {
728 fprintf(stderr, "error: Invalid device number %#lx; only %#x (master) or %#x (slave) are allowed.\n",
729 uTmp, ATA_DEV_MASTER, ATA_DEV_SLAVE);
730 return -1;
731 }
732 bDevice = (uint8_t)uTmp;
733 }
734 else if ( strcmp(pszArg, "--8-bit-data") == 0
735 || strcmp(pszArg, "-8") == 0)
736 f8BitData = 1;
737 else if ( strcmp(pszArg, "--8-bit-data-plus") == 0
738 || strcmp(pszArg, "-8+") == 0)
739 f8BitData = 3;
740 else if ( strcmp(pszArg, "--16-bit-data") == 0
741 || strcmp(pszArg, "-16") == 0)
742 f8BitData = 0;
743 else if (strcmp(pszArg, "--ide") == 0)
744 {
745 /* Normal IDE, primary. */
746 uBasePort = 0x1f0;
747 uCtrlPort = 0x3f0;
748 cShiftPort = 0;
749 f8BitData = 0;
750 }
751 else if (strcmp(pszArg, "--xt-cf") == 0)
752 {
753 /* Lo-tech CF-lite. */
754 uBasePort = 0x300;
755 uCtrlPort = 0x310;
756 cShiftPort = 1;
757 f8BitData = 1;
758 }
759 }
760
761 return AtaInit(uBasePort, uCtrlPort, cShiftPort, bDevice, f8BitData);
762}
763
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