Ignore:
Timestamp:
Dec 20, 2015, 10:17:34 PM (10 years ago)
Author:
bird
Message:

xtide util hacking.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • hacks/xtide/writeatatest.c

    r72 r73  
    3333#include <io.h>
    3434#include <conio.h>
     35#include "atalib.h"
     36
    3537
    3638/*********************************************************************************************************************************
     
    5254#define X86_EFL_CF 1
    5355
    54 /* The necessary I/O ports, indexed by "bus". */
    55 #define ATA_PORT_SHIFT      1 /* For XT-CF trick */
    56 #define ATA_REG_DATA(x)             (x)
    57 #define ATA_REG_FEATURES(x)         ((x) + (1 << ATA_PORT_SHIFT))
    58 #define ATA_REG_SECTOR_COUNT(x)     ((x) + (2 << ATA_PORT_SHIFT))
    59 
    60 #define ATA_REG_SECTOR_NUMBER(x)    ((x) + (3 << ATA_PORT_SHIFT))
    61 #define ATA_REG_CYLINDER_LOW(x)     ((x) + (4 << ATA_PORT_SHIFT))
    62 #define ATA_REG_CYLINDER_HIGH(x)    ((x) + (5 << ATA_PORT_SHIFT))
    63 #define ATA_REG_HEAD(x)             ((x) + (6 << ATA_PORT_SHIFT))
    64 
    65 #define ATA_REG_LBA_0_7(x)          ((x) + (3 << ATA_PORT_SHIFT))
    66 #define ATA_REG_LBA_8_15(x)         ((x) + (4 << ATA_PORT_SHIFT))
    67 #define ATA_REG_LBA_16_23(x)        ((x) + (5 << ATA_PORT_SHIFT))
    68 #define ATA_REG_LBA_24_27_MODE(x)   ((x) + (6 << ATA_PORT_SHIFT))
    69 #define ATA_LBA_MODE                UINT8_C(0x40) /**< Selects LBA mode in ATA_REG_LBA_24_27_MODE. */
    70 
    71 #define ATA_REG_DEVICE_SELECT(x)    ((x) + (6 << ATA_PORT_SHIFT))
    72 #define ATA_REG_COMMAND(x)          ((x) + (7 << ATA_PORT_SHIFT))
    73 
    74 
    75 #define ATA_REG_STATUS(x)           ATA_REG_COMMAND(x)
    76 #define ATA_REG_ALT_STATUS(x)       ATA_REG_CONTROL(x)
    77 #define ATA_STS_BUSY                UINT8_C(0x80)
    78 #define ATA_STS_DRDY                UINT8_C(0x40)
    79 #define ATA_STS_DF                  UINT8_C(0x20)
    80 #define ATA_STS_DSC                 UINT8_C(0x10)
    81 #define ATA_STS_DRQ                 UINT8_C(0x08)
    82 #define ATA_STS_CORR                UINT8_C(0x04)
    83 #define ATA_STS_IDX                 UINT8_C(0x02)
    84 #define ATA_STS_ERR                 UINT8_C(0x01)
    85 
    86 #define ATA_REG_ERROR(x)            ATA_REG_FEATURES(x)
    87 #define ATA_ERR_RSVR                UINT8_C(0x80)
    88 #define ATA_ERR_UNC                 UINT8_C(0x40)
    89 #define ATA_ERR_MC                  UINT8_C(0x20)
    90 #define ATA_ERR_IDNF                UINT8_C(0x10)
    91 #define ATA_ERR_MCR                 UINT8_C(0x08)
    92 #define ATA_ERR_ABRT                UINT8_C(0x04)
    93 #define ATA_ERR_TKNONF              UINT8_C(0x02)
    94 #define ATA_ERR_AMNF                UINT8_C(0x01)
    95 
    96 #define ATA_REG_CONTROL(x)          ((x) + (14 << ATA_PORT_SHIFT))
    97 #define ATA_CTL_IEN                 UINT8_C(0x02) /**< Interrupt enable. */
    98 #define ATA_CTL_SRST                UINT8_C(0x04) /**< software reset */
    99 
    100 #define ATA_CMD_NOP                 UINT8_C(0x00)
    101 #define ATA_CMD_READ_SECTORS        UINT8_C(0x20)
    102 #define ATA_CMD_READ_SECTORS_NR     UINT8_C(0x21)
    103 #define ATA_CMD_READ_LONG           UINT8_C(0x22)
    104 #define ATA_CMD_READ_LONG_NR        UINT8_C(0x23)
    105 #define ATA_CMD_WRITE_SECTORS       UINT8_C(0x30)
    106 #define ATA_CMD_WRITE_SECTORS_NR    UINT8_C(0x31)
    107 #define ATA_CMD_WRITE_LONG          UINT8_C(0x32)
    108 #define ATA_CMD_WRITE_LONG_NR       UINT8_C(0x33)
    109 #define ATA_CMD_INIT_DEVICE_PARAMS  UINT8_C(0x91)
    110 #define ATA_CMD_SET_FEATURES        UINT8_C(0xef)
    111 #define ATA_CMD_IDENTIFY_DEVICE     UINT8_C(0xec)
    112 
    113 
    114 #define ATA_DEV_MASTER              UINT8_C(0x00)  /**< Master device selection bit value. */
    115 #define ATA_DEV_SLAVE               UINT8_C(0x10)  /**< Slave device selection bit value. */
    116 
    117 #define ATA_FEATURE_EN_8BIT_DATA        UINT8_C(0x01)
    118 #define ATA_FEATURE_DI_8BIT_DATA        UINT8_C(0x81)
    119 #define ATA_FEATURE_EN_WRITE_CACHE      UINT8_C(0x02)
    120 #define ATA_FEATURE_DI_WRITE_CACHE      UINT8_C(0x82)
    121 #define ATA_FEATURE_SET_XFERMODE        UINT8_C(0x03)
    122 #define ATA_FV_XFERMODE_PIO_MODE_DEFAULT             UINT8_C(0x00)
    123 #define ATA_FV_XFERMODE_PIO_MODE_DEFAULT_NO_IORDY    UINT8_C(0x01)
    124 #define ATA_FV_XFERMODE_PIO_MODE_XXX_FLAG            UINT8_C(0x08)
    125 #define ATA_FV_XFERMODE_SWDMA_MODE_XXX_FLAG          UINT8_C(0x10)
    126 #define ATA_FV_XFERMODE_MWDMA_MODE_XXX_FLAG          UINT8_C(0x20)
    127 
    128 /** Delay a bit by reading PIC mask. Should take 4-5 bus cycles,
    129  * and thus be more than the required 400ns delay on old computers. */
    130 #define ATA_DELAY_400NS()   do { inp(0x21); } while (0)
    131 
    132 
    13356
    13457/*********************************************************************************************************************************
    13558*   Global Variables                                                                                                             *
    13659*********************************************************************************************************************************/
    137 uint16_t g_uBasePort   = 0x300;
    138 uint16_t g_uPortShift  = 1;
    139 uint8_t  g_fUseLbaMode = 1;
    140 uint8_t  g_f8BitData   = 1;
    141 uint8_t  g_bDevice     = ATA_DEV_MASTER;
    14260uint8_t  g_bDrv        = 0x80;
    143 
    144 
    145 uint16_t g_cHeads;
    146 uint8_t  g_cSectorsPerTrack;
    147 uint16_t g_cCylinders;
    148 uint16_t g_cSectorsPerCylinder;
    149 
    150 /** The result of the identify command. */
    151 uint16_t g_awIdentify[256];
    152 
    153 
    154 size_t AtaPrintStatus(FILE *pOut, uint8_t bSts)
    155 {
    156     size_t cch = fprintf(pOut, "%#x", bSts);
    157     if (bSts & ATA_STS_BUSY) cch += fprintf(pOut, " busy");
    158     if (bSts & ATA_STS_DRDY) cch += fprintf(pOut, " drdy");
    159     if (bSts & ATA_STS_DF  ) cch += fprintf(pOut, " df");
    160     if (bSts & ATA_STS_DSC ) cch += fprintf(pOut, " dsc");
    161     if (bSts & ATA_STS_DRQ ) cch += fprintf(pOut, " drq");
    162     if (bSts & ATA_STS_CORR) cch += fprintf(pOut, " corr");
    163     if (bSts & ATA_STS_IDX ) cch += fprintf(pOut, " idx");
    164     if (bSts & ATA_STS_ERR ) cch += fprintf(pOut, " err");
    165     return cch;
    166 }
    167 
    168 size_t AtaPrintError(FILE *pOut, uint8_t bErr)
    169 {
    170     size_t cch = fprintf(pOut, "%#x", bErr);
    171     if (bErr & ATA_ERR_RSVR  ) cch += fprintf(pOut, " rsrv");
    172     if (bErr & ATA_ERR_UNC   ) cch += fprintf(pOut, " unc");
    173     if (bErr & ATA_ERR_MC    ) cch += fprintf(pOut, " mc");
    174     if (bErr & ATA_ERR_IDNF  ) cch += fprintf(pOut, " idnf");
    175     if (bErr & ATA_ERR_MCR   ) cch += fprintf(pOut, " mcr");
    176     if (bErr & ATA_ERR_ABRT  ) cch += fprintf(pOut, " abrt");
    177     if (bErr & ATA_ERR_TKNONF) cch += fprintf(pOut, " tknonf");
    178     if (bErr & ATA_ERR_AMNF  ) cch += fprintf(pOut, " amnf");
    179     return cch;
    180 }
    181 
    182 static int AtaError(uint8_t bSts, const char *pszFormat, ...)
    183 {
    184     va_list va;
    185 
    186     fprintf(stderr, "error: ");
    187     va_start(va, pszFormat);
    188     vfprintf(stderr, pszFormat, va);
    189     va_end(va);
    190 
    191     fprintf(stderr, "\n status=");
    192     AtaPrintStatus(stderr, bSts);
    193     fprintf(stderr, "\n  error= ");
    194     AtaPrintError(stderr, inp(ATA_REG_ERROR(g_uBasePort)));
    195     fprintf(stderr, "\n");
    196 
    197     return -1;
    198 }
    199 
    200 uint8_t AtaWaitBusy(void)
    201 {
    202     uint32_t cLoops = 0;
    203     uint8_t  bStatus;
    204     do
    205     {
    206         if ((++cLoops & 0xfffff) == 0)
    207             fprintf(stderr, "AtaWaitBusyForData: cLoops=%#lx\n", cLoops);
    208         bStatus = inp(ATA_REG_STATUS(g_uBasePort));
    209     } while ((bStatus & (ATA_STS_BUSY | ATA_STS_ERR)) == ATA_STS_BUSY);
    210     return bStatus;
    211 }
    212 
    213 uint8_t AtaWaitBusyDeviceReady(void)
    214 {
    215     uint32_t cLoops = 0;
    216     uint8_t bStatus;
    217     do
    218     {
    219         if ((++cLoops & 0xfffff) == 0)
    220             fprintf(stderr, "AtaWaitBusyForData: cLoops=%#lx\n", cLoops);
    221         bStatus = inp(ATA_REG_STATUS(g_uBasePort));
    222     } while (    (bStatus & (ATA_STS_BUSY | ATA_STS_DRDY)) != ATA_STS_DRDY
    223              && !(bStatus & ATA_STS_ERR) );
    224     return bStatus;
    225 }
    226 
    227 uint8_t AtaWaitBusyForData(void)
    228 {
    229     uint32_t cLoops = 0;
    230     uint8_t bStatus;
    231     do
    232     {
    233         if ((++cLoops & 0xfffff) == 0)
    234             fprintf(stderr, "AtaWaitBusyForData: cLoops=%#lx\n", cLoops);
    235         bStatus = inp(ATA_REG_STATUS(g_uBasePort));
    236     } while (    (bStatus & (ATA_STS_BUSY | ATA_STS_DRQ)) != ATA_STS_DRQ
    237              && !(bStatus & ATA_STS_ERR) );
    238     return bStatus;
    239 }
    240 
    241 uint8_t AtaSubmitCommandAndWait(uint8_t bCommand)
    242 {
    243 
    244     outp(ATA_REG_COMMAND(g_uBasePort), bCommand);
    245     ATA_DELAY_400NS();
    246     return AtaWaitBusy();
    247 }
    248 
    249 uint8_t AtaSubmitCommandAndWaitForData(uint8_t bCommand)
    250 {
    251 
    252     outp(ATA_REG_COMMAND(g_uBasePort), bCommand);
    253     ATA_DELAY_400NS();
    254     return AtaWaitBusyForData();
    255 }
    256 
    257 uint8_t AtaSelectDevice(uint8_t bDevice)
    258 {
    259     outp(ATA_REG_DEVICE_SELECT(g_uBasePort), g_bDevice);
    260     ATA_DELAY_400NS();
    261     return AtaWaitBusyDeviceReady();
    262 }
    263 
    264 void AtaSetSectorAddress(uint32_t iSector, uint8_t bDevice)
    265 {
    266     if (g_fUseLbaMode)
    267     {
    268         outp(ATA_REG_LBA_0_7(g_uBasePort), iSector & 0xff);
    269         outp(ATA_REG_LBA_8_15(g_uBasePort), (iSector >> 8) & 0xff);
    270         outp(ATA_REG_LBA_16_23(g_uBasePort), (iSector >> 16) & 0xff);
    271         outp(ATA_REG_LBA_24_27_MODE(g_uBasePort), ((iSector >> 24) & 0x0f) | ATA_LBA_MODE | bDevice);
    272     }
    273     else
    274     {
    275         uint16_t iCyl = iSector / g_cSectorsPerCylinder;
    276         uint16_t iRem = iSector % g_cSectorsPerCylinder;
    277         uint8_t  iHd  = iRem / g_cSectorsPerTrack;
    278         uint8_t  iSec = iRem % g_cSectorsPerTrack;
    279 
    280         outp(ATA_REG_SECTOR_NUMBER(g_uBasePort), iSec);
    281         outp(ATA_REG_CYLINDER_LOW(g_uBasePort), iCyl & 0xff);
    282         outp(ATA_REG_CYLINDER_HIGH(g_uBasePort), iCyl >> 8);
    283         outp(ATA_REG_HEAD(g_uBasePort), iHd | bDevice);
    284     }
    285 }
    286 
    287 void AtaReadData(void *pvBuf, size_t cb, uint8_t f8BitData)
    288 {
    289     uint16_t  uDataPort = ATA_REG_DATA(g_uBasePort);
    290     uint16_t *pu16      = (uint16_t *)pvBuf;
    291     cb >>= 1;
    292 
    293     if (f8BitData)
    294     {
    295         while (cb-- > 0)
    296         {
    297             uint8_t b1 = inp(uDataPort);
    298             uint8_t b2 = inp(uDataPort);
    299             *pu16++ = b1 | ((uint16_t)b2 << 8);
    300         }
    301     }
    302     else
    303     {
    304         while (cb-- > 0)
    305             *pu16++ = inpw(uDataPort);
    306     }
    307 }
    308 
    309 ////static uint8_t AtaWaitForDataRequest(size_t cbLeft)
    310 ////{
    311 ////    uint16_t uAltStsPort = ATA_REG_ALT_STATUS(g_uBasePort);
    312 ////    uint8_t  bStsFirst = inp(uAltStsPort);
    313 ////    uint8_t  bSts = bStsFirst;
    314 ////    uint32_t cLoops = 0;
    315 ////    do
    316 ////    {
    317 ////        if (++cLoops & 0xffff)
    318 ////        {
    319 ////static unsigned x = 0;
    320 ////if (x < 16)
    321 ////{
    322 ////    printf("AtaWaitForDataRequest: bFirst=%#x bLast=%#x cbLeft=%#x\n", bStsFirst, bSts, cbLeft);
    323 ////    x++;
    324 ////}
    325 ////            break;
    326 ////        }
    327 ////        bSts = inp(uAltStsPort);
    328 ////    } while (!(bSts & (ATA_STS_DRQ | ATA_STS_ERR)));
    329 ////    return bSts;
    330 ////}
    331 
    332 void xchg(uint8_t volatile *pb);
    333 #pragma aux xchg = \
    334     "xchg [si], cx" \
    335     "xchg [si], cx" \
    336     "xchg [si], cx" \
    337     "xchg [si], cx" \
    338     parm [si] \
    339     modify exact [cx];
    340 
    341 void AtaWriteData(void const *pvBuf, size_t cb, uint8_t f8BitData)
    342 {
    343 //    uint16_t        uAltStsPort = ATA_REG_ALT_STATUS(g_uBasePort);
    344     uint16_t register uDataPort = ATA_REG_DATA(g_uBasePort);
    345 
    346     if (f8BitData)
    347     {
    348 #if 0
    349         uint8_t const   * volatile pbSrc = (uint8_t const *)pvBuf;
    350         uint8_t volatile ab[64];
    351         uint8_t volatile *pb = &ab[0];
    352         while (((uintptr_t)pb & 0x1f) != 0x1f)
    353             pb++;
    354         //uint8_t  bSts1, bSts2;
    355 inp(0x21);
    356 xchg(pb);
    357 
    358         while (cb-- > 0)
    359         {
    360             uint8_t b = *pbSrc++;
    361             xchg(pb);
    362             outp(uDataPort, b);
    363             xchg(pb);
    364             b = *pbSrc++;
    365             xchg(pb);
    366 //inp(0x21);
    367             outp(uDataPort, b);
    368             xchg(pb);
    369 //inp(0x21);
    370             //if (cb < 30)
    371             //{
    372             //    if ((cb & 3) == 3)
    373             //        printf("bSts1=%#x bSts2=%#x ", bSts1, bSts2);
    374             //    else
    375             //        printf("bSts1=%#x bSts2=%#x\n", bSts1, bSts2);
    376             //}
    377         }
    378 inp(0x21);
    379 #else
    380         uint16_t const *pu16      = (uint16_t const *)pvBuf;
    381         cb >>= 1;
    382         while (cb-- > 0)
    383         {
    384             uint16_t register u16 = *pu16++;
    385             outp(uDataPort, (uint8_t)u16);
    386             outp(uDataPort, (uint8_t)(u16 >> 8));
    387         }
    388 #endif
    389     }
    390     else
    391     {
    392         uint16_t const *pu16      = (uint16_t const *)pvBuf;
    393         cb >>= 1;
    394         while (cb-- > 0)
    395             outp(uDataPort, *pu16++);
    396     }
    397 }
    398 
    399 int AtaReadSector(uint32_t iSector, void *pvBuf)
    400 {
    401     uint8_t bSts = AtaWaitBusy();
    402     if (bSts & ATA_STS_ERR)
    403         return AtaError(bSts, "Prepping for reading sector %lu", iSector);
    404 
    405 printf("AtaReadSector #2\n");
    406     bSts = AtaSelectDevice(g_bDevice);
    407     if (bSts & ATA_STS_ERR)
    408         return AtaError(bSts, "Selecting device for reading sector %lu", iSector);
    409 
    410 //printf("AtaReadSector #3\n");
    411     outp(ATA_REG_FEATURES(g_uBasePort), 0x0);
    412     outp(ATA_REG_SECTOR_COUNT(g_uBasePort), 1);
    413     AtaSetSectorAddress(iSector, g_bDevice);
    414 
    415 //printf("AtaReadSector #4\n");
    416     bSts = AtaSubmitCommandAndWaitForData(ATA_CMD_READ_SECTORS);
    417     if (bSts & ATA_STS_ERR)
    418         return AtaError(bSts, "Reading sector %lu", iSector);
    419 
    420     if (!(bSts & ATA_STS_DRQ))
    421         return AtaError(bSts, "DRQ not set after reading sector %lu", iSector);
    422 
    423 
    424 //printf("AtaReadSector #5\n");
    425     AtaReadData(pvBuf, 512, g_f8BitData);
    426 //printf("AtaReadSector #6: bSts=%#x\n", inp(ATA_REG_ALT_STATUS(g_uBasePort)));
    427     bSts = inp(ATA_REG_STATUS(g_uBasePort));
    428     if ((bSts & ATA_STS_DRQ))
    429         return AtaError(bSts, "DRQ is still set after reading sector %lu", iSector);
    430     if ((bSts & ATA_STS_ERR))
    431         return AtaError(bSts, "ERR is set after reading sector %lu (#2)", iSector);
    432     return 0;
    433 }
    434 
    435 int AtaWriteSector(uint32_t iSector, void const *pvBuf)
    436 {
    437 //int x = printf("AtaWriteSector #1\n");
    438     uint8_t bSts = AtaWaitBusy();
    439     if (bSts & ATA_STS_ERR)
    440         return AtaError(bSts, "Prepping for writing sector %lu", iSector);
    441 printf("AtaWriteSector #2\n");
    442 
    443     bSts = AtaSelectDevice(g_bDevice);
    444     if (bSts & ATA_STS_ERR)
    445         return AtaError(bSts, "Selecting device for writing sector %lu", iSector);
    446 
    447     outp(ATA_REG_FEATURES(g_uBasePort), 0x0);
    448     outp(ATA_REG_SECTOR_COUNT(g_uBasePort), 1);
    449     AtaSetSectorAddress(iSector, g_bDevice);
    450 
    451 //printf("AtaWriteSector #3\n");
    452     bSts = AtaSubmitCommandAndWaitForData(ATA_CMD_WRITE_SECTORS);
    453     if (bSts & ATA_STS_ERR)
    454         return AtaError(bSts, "writing sector (#1) %lu", iSector);
    455     if (!(bSts & ATA_STS_DRQ))
    456         return AtaError(bSts, "DRQ not set after writing sector (#1) %lu", iSector);
    457 
    458 //printf("AtaWriteSector #4\n");
    459     AtaWriteData(pvBuf, 512, g_f8BitData);
    460 //printf("AtaWriteSector #5\n");
    461     ATA_DELAY_400NS();
    462     bSts = AtaWaitBusy();
    463 //printf("AtaWriteSector #6\n");
    464     if (bSts & ATA_STS_ERR)
    465         return AtaError(bSts, "writing sector (#2) %lu", iSector);
    466     if (bSts & ATA_STS_DRQ)
    467         return AtaError(bSts, "DRQ is set after writing sector (#2) %lu", iSector);
    468 
    469     return 0;
    470 }
    471 
    472 int AtaIdentifyDevice(uint8_t bDevice, void *pvBuf)
    473 {
    474     uint8_t bSts = AtaWaitBusy();
    475     if (bSts & ATA_STS_ERR)
    476         return AtaError(bSts, "Prepping for device %#x identification", bDevice);
    477 
    478     bSts = AtaSelectDevice(g_bDevice);
    479     if (bSts & ATA_STS_ERR)
    480         return AtaError(bSts, "Selecting device %#x for identification", bDevice);
    481 
    482     outp(ATA_REG_FEATURES(g_uBasePort),         0);
    483     outp(ATA_REG_SECTOR_COUNT(g_uBasePort),     0);
    484     outp(ATA_REG_SECTOR_NUMBER(g_uBasePort),    0);
    485     outp(ATA_REG_CYLINDER_LOW(g_uBasePort),     0);
    486     outp(ATA_REG_CYLINDER_HIGH(g_uBasePort),    0);
    487     //outp(ATA_REG_HEAD(g_uBasePort), g_bDevice);
    488 
    489     bSts = AtaSubmitCommandAndWaitForData(ATA_CMD_IDENTIFY_DEVICE);
    490     if (bSts & ATA_STS_ERR)
    491         return AtaError(bSts, "Device %#x identification", bDevice);
    492     if (!(bSts & ATA_STS_DRQ))
    493         return AtaError(bSts, "DRQ not set after device %#x identification", bDevice);
    494 
    495     AtaReadData(pvBuf, 512, g_f8BitData);
    496     return 0;
    497 }
    498 
    499 int AtaSetFeature(uint8_t bDevice, uint8_t bFeature, uint8_t bValue)
    500 {
    501     uint8_t bSts = AtaWaitBusy();
    502     if (bSts & ATA_STS_ERR)
    503         return AtaError(bSts, "Prepping for setting device %#x feature %#x (%#x)", bDevice, bFeature, bValue);
    504 
    505     bSts = AtaSelectDevice(g_bDevice);
    506     if (bSts & ATA_STS_ERR)
    507         return AtaError(bSts, "Selecting device %#x for setting feature %#x (%#x)", bDevice, bFeature, bValue);
    508 
    509     outp(ATA_REG_FEATURES(g_uBasePort),         bFeature);
    510     outp(ATA_REG_SECTOR_COUNT(g_uBasePort),     0);
    511     outp(ATA_REG_SECTOR_NUMBER(g_uBasePort),    bValue);
    512     outp(ATA_REG_CYLINDER_LOW(g_uBasePort),     0);
    513     outp(ATA_REG_CYLINDER_HIGH(g_uBasePort),    0);
    514     //outp(ATA_REG_HEAD(g_uBasePort), g_bDevice);
    515 
    516     bSts = AtaSubmitCommandAndWait(ATA_CMD_SET_FEATURES);
    517     if (bSts & ATA_STS_ERR)
    518         return AtaError(bSts, "Setting device %#x feature %#x (%#x)", bDevice, bFeature, bValue);
    519     if (bSts & ATA_STS_DRQ)
    520         return AtaError(bSts, "DRQ is set after setting device %#x feature %#x (%#x)", bDevice, bFeature, bValue);
    521     return 0;
    522 }
    523 
    524 int AtaInitDeviceParams(uint8_t bDevice, uint8_t cSectorsPerTrack, uint8_t cHeads)
    525 {
    526     uint8_t bSts = AtaWaitBusy();
    527     if (bSts & ATA_STS_ERR)
    528         return AtaError(bSts, "Prepping for device %#x parameter initialization", bDevice);
    529 
    530     bSts = AtaSelectDevice(g_bDevice);
    531     if (bSts & ATA_STS_ERR)
    532         return AtaError(bSts, "Selecting device for device %#x parameter initialization", bDevice);
    533 
    534     outp(ATA_REG_FEATURES(g_uBasePort),         0);
    535     outp(ATA_REG_SECTOR_COUNT(g_uBasePort),     cSectorsPerTrack);
    536     outp(ATA_REG_SECTOR_NUMBER(g_uBasePort),    0);
    537     outp(ATA_REG_CYLINDER_LOW(g_uBasePort),     0);
    538     outp(ATA_REG_CYLINDER_HIGH(g_uBasePort),    0);
    539     outp(ATA_REG_HEAD(g_uBasePort), g_bDevice | cHeads);
    540 
    541     bSts = AtaSubmitCommandAndWait(ATA_CMD_INIT_DEVICE_PARAMS);
    542     if (bSts & ATA_STS_ERR)
    543         return AtaError(bSts, "Device %#x parameter initialization", bDevice);
    544     if (bSts & ATA_STS_DRQ)
    545         return AtaError(bSts, "DRQ is set after device %#x parameter initialization", bDevice);
    546     return 0;
    547 }
    548 
    549 int AtaReset(void)
    550 {
    551     uint8_t bSts;
    552 
    553     /* Set the reset flat. */
    554     outp(ATA_REG_CONTROL(g_uBasePort), ATA_CTL_SRST);
    555 
    556     /* Wait for the busy flag response. */
    557     ATA_DELAY_400NS();
    558     ATA_DELAY_400NS();
    559     while (!(bSts = inp(ATA_REG_STATUS(g_uBasePort))) & ATA_STS_BUSY)
    560         ATA_DELAY_400NS();
    561 
    562     /* Clear the reset flag. */
    563     outp(ATA_REG_CONTROL(g_uBasePort), 0);
    564     ATA_DELAY_400NS();
    565 
    566     /* Wait for the controller to become non-busy. */
    567     bSts = AtaWaitBusy();
    568     if (bSts & ATA_STS_ERR)
    569         return AtaError(bSts, "Software reset failed");
    570     return 0;
    571 }
    572 
    573 
    574 int AtaInit(void)
    575 {
    576     uint8_t bSts = inp(ATA_REG_ALT_STATUS(g_uBasePort));
    577     printf("alt status=");
    578     AtaPrintStatus(stdout, bSts);
    579     printf("\n");
    580 
    581     bSts = inp(ATA_REG_STATUS(g_uBasePort));
    582     printf("    status=");
    583     AtaPrintStatus(stdout, bSts);
    584     printf("\n");
    585 
    586     if (AtaReset() != 0)
    587         return -1;
    588 
    589     /* Enable 8-bit data transfers (just to be on the safe side). */
    590     AtaSetFeature(g_bDevice, ATA_FEATURE_EN_8BIT_DATA, 0);
    591 
    592     /* Identify the device. */
    593     memset(g_awIdentify, 0, sizeof(g_awIdentify));
    594     if (AtaIdentifyDevice(g_bDevice, g_awIdentify) != 0)
    595         return -1;
    596 
    597     /** @todo this is rather simple... */
    598     g_cCylinders = g_awIdentify[1];
    599     g_cHeads     = g_awIdentify[3];
    600     g_cSectorsPerTrack = g_awIdentify[6];
    601     g_cSectorsPerCylinder = g_cHeads * g_cSectorsPerTrack;
    602     printf("Device %#x parameters: %u cylinders, %u heads, %u sectors\n",
    603            g_bDevice, g_cCylinders, g_cHeads, g_cSectorsPerTrack);
    604 
    605     /* Disable stuff and try select pio modes. */
    606     AtaSetFeature(g_bDevice, ATA_FEATURE_DI_WRITE_CACHE, 0);
    607     AtaSetFeature(g_bDevice, ATA_FEATURE_SET_XFERMODE, ATA_FV_XFERMODE_PIO_MODE_DEFAULT_NO_IORDY);
    608     AtaSetFeature(g_bDevice, ATA_FEATURE_SET_XFERMODE, ATA_FV_XFERMODE_PIO_MODE_XXX_FLAG | 0);
    609 
    610     return 0;
    611 }
    612 
    613 
    61461
    61562
     
    746193
    747194
    748 int GetDriveParams(void)
     195int GetDriveParams(uint8_t bDevice)
    749196{
    750197#ifdef USE_INT13H
    751198    return Int13hInit();
    752199#else
    753     return AtaInit();
     200    return 0;
    754201#endif
    755202}
     
    791238     */
    792239    uint32_t iSector = 3;
     240    uint8_t  bDevice = ATA_DEV_MASTER;
    793241    g_bDrv = 0x80;
    794     g_bDevice = ATA_DEV_MASTER;
    795242
    796243    if (argc > 3)
     
    812259    if (argc > 2)
    813260    {
    814         unsigned long uTmp = strtoul(argv[2], NULL, 0);
    815         if (uTmp < 0x80 || uTmp > 0x8f)
    816         {
    817             fprintf(stderr, "error: drive number is out of bounds: %s (%lu)\n", argv[1], uTmp);
     261        if (AtaInitFromArgv(2, argc, argv) != 0)
    818262            return usage();
    819         }
    820         g_bDrv = (uint8_t)uTmp;
    821         g_bDevice = g_bDrv == 0x80 ? ATA_DEV_MASTER : ATA_DEV_SLAVE; /* simplified */
    822263    }
    823264
     
    825266     * Detect drive parameters.
    826267     */
    827     if (GetDriveParams() == 0)
     268    if (GetDriveParams(bDevice) == 0)
    828269    {
    829270        static uint8_t s_abSaved[512];
Note: See TracChangeset for help on using the changeset viewer.