Changeset 73 for hacks/xtide/atalib.h


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

xtide util hacking.

File:
1 copied

Legend:

Unmodified
Added
Removed
  • hacks/xtide/atalib.h

    r72 r73  
    2323
    2424
    25 /*********************************************************************************************************************************
    26 *   Header Files                                                                                                                 *
    27 *********************************************************************************************************************************/
    28 #include <stdarg.h>
    29 #include <stdio.h>
    30 #include <stdlib.h>
    31 #include <string.h>
     25#ifndef ___atalib_h___
     26#define ___atalib_h___
     27
    3228#include <stdint.h>
    33 #include <io.h>
    34 #include <conio.h>
    35 
    36 /*********************************************************************************************************************************
    37 *   Structures and Typedefs                                                                                                      *
    38 *********************************************************************************************************************************/
    39 typedef struct REGS16
    40 {
    41     uint16_t    ax;     /**<  0 */
    42     uint16_t    cx;     /**<  2 */
    43     uint16_t    dx;     /**<  4 */
    44     uint16_t    si;     /**<  6 */
    45     uint16_t    di;     /**<  8 */
    46     uint16_t    es;     /**< 10 */
    47     uint16_t    efl;    /**< 12 */
    48     uint16_t    ds;     /**< 14 */
    49     uint16_t    bx;     /**< 16 */
    50 } REGS16;
    51 
    52 #define X86_EFL_CF 1
    5329
    5430/* The necessary I/O ports, indexed by "bus". */
    5531#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))
     32#define ATA_REG_DATA(a_uBasePort)           (a_uBasePort)
     33#define ATA_REG_FEATURES(a_uBasePort)       ((a_uBasePort) + (1 << ATA_PORT_SHIFT))
     34#define ATA_REG_SECTOR_COUNT(a_uBasePort)   ((a_uBasePort) + (2 << ATA_PORT_SHIFT))
    5935
    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))
     36#define ATA_REG_SECTOR_NUMBER(a_uBasePort)  ((a_uBasePort) + (3 << ATA_PORT_SHIFT))
     37#define ATA_REG_CYLINDER_LOW(a_uBasePort)   ((a_uBasePort) + (4 << ATA_PORT_SHIFT))
     38#define ATA_REG_CYLINDER_HIGH(a_uBasePort)  ((a_uBasePort) + (5 << ATA_PORT_SHIFT))
     39#define ATA_REG_HEAD(a_uBasePort)           ((a_uBasePort) + (6 << ATA_PORT_SHIFT))
    6440
    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. */
     41#define ATA_REG_LBA_0_7(a_uBasePort)        ((a_uBasePort) + (3 << ATA_PORT_SHIFT))
     42#define ATA_REG_LBA_8_15(a_uBasePort)       ((a_uBasePort) + (4 << ATA_PORT_SHIFT))
     43#define ATA_REG_LBA_16_23(a_uBasePort)      ((a_uBasePort) + (5 << ATA_PORT_SHIFT))
     44#define ATA_REG_LBA_24_27_MODE(a_uBasePort) ((a_uBasePort) + (6 << ATA_PORT_SHIFT))
     45#define ATA_LBA_MODE                        UINT8_C(0x40) /**< Selects LBA mode in ATA_REG_LBA_24_27_MODE. */
    7046
    71 #define ATA_REG_DEVICE_SELECT(x)    ((x) + (6 << ATA_PORT_SHIFT))
    72 #define ATA_REG_COMMAND(x)          ((x) + (7 << ATA_PORT_SHIFT))
     47#define ATA_REG_DEVICE_SELECT(a_uBasePort)  ((a_uBasePort) + (6 << ATA_PORT_SHIFT))
     48#define ATA_REG_COMMAND(a_uBasePort)        ((a_uBasePort) + (7 << ATA_PORT_SHIFT))
    7349
    7450
    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)
     51#define ATA_REG_STATUS(a_uBasePort)         ATA_REG_COMMAND(a_uBasePort)
     52#define ATA_REG_ALT_STATUS(a_uCtrlPort)     ATA_REG_CONTROL(a_uCtrlPort)
     53#define ATA_STS_BUSY                        UINT8_C(0x80)
     54#define ATA_STS_DRDY                        UINT8_C(0x40)
     55#define ATA_STS_DF                          UINT8_C(0x20)
     56#define ATA_STS_DSC                         UINT8_C(0x10)
     57#define ATA_STS_DRQ                         UINT8_C(0x08)
     58#define ATA_STS_CORR                        UINT8_C(0x04)
     59#define ATA_STS_IDX                         UINT8_C(0x02)
     60#define ATA_STS_ERR                         UINT8_C(0x01)
    8561
    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)
     62#define ATA_REG_ERROR(a_uBasePort)          ATA_REG_FEATURES(a_uBasePort)
     63#define ATA_ERR_RSVR                        UINT8_C(0x80)
     64#define ATA_ERR_UNC                         UINT8_C(0x40)
     65#define ATA_ERR_MC                          UINT8_C(0x20)
     66#define ATA_ERR_IDNF                        UINT8_C(0x10)
     67#define ATA_ERR_MCR                         UINT8_C(0x08)
     68#define ATA_ERR_ABRT                        UINT8_C(0x04)
     69#define ATA_ERR_TKNONF                      UINT8_C(0x02)
     70#define ATA_ERR_AMNF                        UINT8_C(0x01)
    9571
    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 */
     72#define ATA_REG_CONTROL(a_uCtrlPort)        ((a_uCtrlPort) + (6 << ATA_PORT_SHIFT))
     73#define ATA_CTL_IEN                         UINT8_C(0x02) /**< Interrupt enable. */
     74#define ATA_CTL_SRST                        UINT8_C(0x04) /**< software reset */
    9975
    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)
     76#define ATA_CMD_NOP                         UINT8_C(0x00)
     77#define ATA_CMD_READ_SECTORS                UINT8_C(0x20)
     78#define ATA_CMD_READ_SECTORS_NR             UINT8_C(0x21)
     79#define ATA_CMD_READ_LONG                   UINT8_C(0x22)
     80#define ATA_CMD_READ_LONG_NR                UINT8_C(0x23)
     81#define ATA_CMD_READ_BUFFER                 UINT8_C(0xe4)
     82#define ATA_CMD_WRITE_SECTORS               UINT8_C(0x30)
     83#define ATA_CMD_WRITE_SECTORS_NR            UINT8_C(0x31)
     84#define ATA_CMD_WRITE_LONG                  UINT8_C(0x32)
     85#define ATA_CMD_WRITE_LONG_NR               UINT8_C(0x33)
     86#define ATA_CMD_WRITE_BUFFER                UINT8_C(0xe8)
     87#define ATA_CMD_INIT_DEVICE_PARAMS          UINT8_C(0x91)
     88#define ATA_CMD_SET_FEATURES                UINT8_C(0xef)
     89#define ATA_CMD_IDENTIFY_DEVICE             UINT8_C(0xec)
    11290
     91#define ATA_DEV_MASTER                      UINT8_C(0x00)  /**< Master device selection bit value. */
     92#define ATA_DEV_SLAVE                       UINT8_C(0x10)  /**< Slave device selection bit value. */
    11393
    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)
     94#define ATA_FEATURE_EN_8BIT_DATA            UINT8_C(0x01)
     95#define ATA_FEATURE_DI_8BIT_DATA            UINT8_C(0x81)
     96#define ATA_FEATURE_EN_WRITE_CACHE          UINT8_C(0x02)
     97#define ATA_FEATURE_DI_WRITE_CACHE          UINT8_C(0x82)
     98#define ATA_FEATURE_SET_XFERMODE            UINT8_C(0x03)
    12299#define ATA_FV_XFERMODE_PIO_MODE_DEFAULT             UINT8_C(0x00)
    123100#define ATA_FV_XFERMODE_PIO_MODE_DEFAULT_NO_IORDY    UINT8_C(0x01)
     
    130107#define ATA_DELAY_400NS()   do { inp(0x21); } while (0)
    131108
     109extern uint16_t g_cHeads;
     110extern uint8_t  g_cSectorsPerTrack;
     111extern uint16_t g_cCylinders;
     112extern uint16_t g_cSectorsPerCylinder;
     113extern uint16_t g_awIdentify[256];
    132114
     115int  AtaInit(uint16_t uBasePort, uint16_t uCtrlPort, uint8_t uPortShift, uint8_t bDevice, uint8_t f8BitData);
     116int  AtaInitFromArgv(int iArg, int cArgs, char **papszArgs);
     117int  AtaReInit(void);
     118int  AtaReset(void);
     119int  AtaIdentifyDevice(uint8_t bDevice, void *pvBuf);
     120int  AtaInitDeviceParams(uint8_t bDevice, uint8_t cSectorsPerTrack, uint8_t cHeads);
     121int  AtaSetFeature(uint8_t bDevice, uint8_t bFeature, uint8_t bValue);
     122int  AtaWriteSector(uint32_t iSector, void const *pvBuf);
     123int  AtaReadSector(uint32_t iSector, void *pvBuf);
     124int  AtaWriteBuffer(void const *pvBuf, uint8_t fExtraChecks);
     125int  AtaReadBuffer(void *pvBuf, uint8_t fExtraChecks);
     126void AtaWriteData(void const *pvBuf, size_t cb, uint8_t f8BitData);
     127void AtaReadData(void *pvBuf, size_t cb, uint8_t f8BitData);
    133128
    134 /*********************************************************************************************************************************
    135 *   Global Variables                                                                                                             *
    136 *********************************************************************************************************************************/
    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;
    142 uint8_t  g_bDrv        = 0x80;
     129#endif
    143130
    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 
    614 
    615 
    616 /*
    617  * INT13h access methods
    618  * INT13h access methods
    619  * INT13h access methods
    620  */
    621 
    622 void BiosCall13(REGS16 *pRegs);
    623 #pragma aux BiosCall13 = \
    624     "push   ax" \
    625     "push   cx" \
    626     "push   dx" \
    627     "push   bp" \
    628     "push   si" \
    629     "push   di" \
    630     "push   es" \
    631     "push   bx" \
    632     "push   ds" \
    633     \
    634     "mov    ax,  [bx]" \
    635     "mov    cx,  [bx +  2]" \
    636     "mov    dx,  [bx +  4]" \
    637     "mov    si,  [bx +  6]" \
    638     "mov    di,  [bx +  8]" \
    639     "mov    es,  [bx + 10]" \
    640     "push   word ptr [bx + 12]" \
    641     "popf" \
    642     "push   word ptr [bx + 14]" \
    643     "push   word ptr [bx + 16]" \
    644     "pop    bx" \
    645     "pop    ds" \
    646     \
    647     "int    13h"\
    648     \
    649     "push   ds" \
    650     "push   bx" \
    651     "mov    bp, sp" \
    652     "mov    ds, [bp + 4]" \
    653     "mov    bx, [bp + 6]" \
    654     "mov    [bx], ax" \
    655     "mov    [bx +  2], cx" \
    656     "mov    [bx +  4], dx" \
    657     "mov    [bx +  6], si" \
    658     "mov    [bx +  8], di" \
    659     "mov    [bx + 10], es" \
    660     "pushf" \
    661     "pop    ax" \
    662     "mov    [bx + 12], ax" \
    663     "pop    ax" \
    664     "mov    [bx + 14], ax" \
    665     "pop    ax" \
    666     "mov    [bx + 16], ax" \
    667     \
    668     "pop    ds" \
    669     "pop    bx" \
    670     "pop    es" \
    671     "pop    di" \
    672     "pop    si" \
    673     "pop    bp" \
    674     "pop    dx" \
    675     "pop    cx" \
    676     "pop    ax" \
    677     parm [bx];
    678 
    679 
    680 int Int13hInit(void)
    681 {
    682     REGS16 Regs;
    683     memset(&Regs, 0, sizeof(Regs));
    684     Regs.ax = 0x0800;
    685     Regs.dx = g_bDrv;
    686     BiosCall13(&Regs);
    687     /** @todo check for errors.   */
    688     g_cHeads = (Regs.dx >> 8) + 1;
    689     g_cSectorsPerTrack = Regs.cx & 0x3f;
    690     g_cCylinders = (Regs.cx >> 8) | ((Regs.cx & 0xc0) << 2);
    691     g_cSectorsPerCylinder = g_cHeads * g_cSectorsPerTrack;
    692 
    693     printf("Drive %#x parameters: %u cylinders, %u heads, %u sectors\n",
    694            g_bDrv, g_cCylinders, g_cHeads, g_cSectorsPerTrack);
    695     if (!(Regs.efl & X86_EFL_CF))
    696         return 0;
    697     fprintf(stderr, "Error getting disk params: %#x\n", Regs.ax);
    698     return -1;
    699 }
    700 
    701 void SectorNoToInt13(uint32_t iSector, REGS16 *pRegs)
    702 {
    703     uint16_t iRem = iSector % g_cSectorsPerCylinder;
    704     uint16_t iCyl = iSector / g_cSectorsPerCylinder;
    705     pRegs->cx  = iCyl << 8;
    706     pRegs->cx |= (iCyl >> 2) & 0xc0;
    707     pRegs->cx |= (iRem % g_cSectorsPerTrack) & 0x3f;
    708     pRegs->dx &= UINT16_C(0x00ff);
    709     pRegs->dx |= (iRem / g_cSectorsPerTrack) << 8;
    710 }
    711 
    712 int Int13hReadSector(uint32_t iSector, void *pvBuf)
    713 {
    714     REGS16   Regs;
    715     memset(&Regs, 0, sizeof(Regs));
    716     Regs.ax = 0x0201;
    717     Regs.dx = g_bDrv;
    718     Regs.bx = (unsigned)(void __near *)pvBuf;
    719     Regs.es = (__segment)pvBuf;
    720     SectorNoToInt13(iSector, &Regs);
    721     printf("ax=%#x dx=%#x cx=%#x es:bx=%04x:%04x\n", Regs.ax, Regs.dx, Regs.cx, Regs.es, Regs.bx);
    722     BiosCall13(&Regs);
    723     if (!(Regs.efl & X86_EFL_CF))
    724         return 0;
    725     fprintf(stderr, "Error reading sector %lu on %#x: %#x\n", iSector, g_bDrv, Regs.ax);
    726     return -1;
    727 }
    728 
    729 int Int13hWriteSector(uint32_t iSector, void const *pvBuf)
    730 {
    731     REGS16   Regs;
    732     memset(&Regs, 0, sizeof(Regs));
    733     Regs.ax = 0x0301;
    734     Regs.dx = g_bDrv;
    735     Regs.bx = (unsigned)(void const __near *)pvBuf;
    736     Regs.es = (__segment)pvBuf;
    737     SectorNoToInt13(iSector, &Regs);
    738     printf("ax=%#x dx=%#x cx=%#x es:bx=%04x:%04x\n", Regs.ax, Regs.dx, Regs.cx, Regs.es, Regs.bx);
    739     BiosCall13(&Regs);
    740     if (!(Regs.efl & X86_EFL_CF))
    741         return 0;
    742     fprintf(stderr, "Error writing sector %lu on %#x: %#x\n", iSector, g_bDrv, Regs.ax);
    743     return -1;
    744 }
    745 
    746 
    747 
    748 int GetDriveParams(void)
    749 {
    750 #ifdef USE_INT13H
    751     return Int13hInit();
    752 #else
    753     return AtaInit();
    754 #endif
    755 }
    756 
    757 int ReadSector(uint32_t iSector, void *pvBuf)
    758 {
    759 #ifdef USE_INT13H
    760     return Int13hReadSector(iSector, pvBuf);
    761 #else
    762     return AtaReadSector(iSector, pvBuf);
    763 #endif
    764 }
    765 
    766 int WriteSector(uint32_t iSector, void const *pvBuf)
    767 {
    768 #ifdef USE_INT13H
    769     return Int13hWriteSector(iSector, pvBuf);
    770 #else
    771     return AtaWriteSector(iSector, pvBuf);
    772 #endif
    773 }
    774 
    775 
    776 
    777 
    778 static int usage(void)
    779 {
    780     printf("usage: writetst [sector] [drv]\n");
    781     return 1;
    782 }
    783 
    784 
    785 int main(int argc, char **argv)
    786 {
    787     int rc = 1;
    788 
    789     /*
    790      * Parse parameters.
    791      */
    792     uint32_t iSector = 3;
    793     g_bDrv = 0x80;
    794     g_bDevice = ATA_DEV_MASTER;
    795 
    796     if (argc > 3)
    797     {
    798         fprintf(stderr, "too many parameters!\n");
    799         return usage();
    800     }
    801     if (argc > 1)
    802     {
    803         iSector = strtoul(argv[1], NULL, 0);
    804         if (   iSector == 0
    805             || (iSector >= 32 && iSector < 65535)
    806             || iSector > 0x800000 /*4G*/)
    807         {
    808             fprintf(stderr, "error: start sector is out of bounds: %s (%lu)\n", argv[1], iSector);
    809             return usage();
    810         }
    811     }
    812     if (argc > 2)
    813     {
    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);
    818             return usage();
    819         }
    820         g_bDrv = (uint8_t)uTmp;
    821         g_bDevice = g_bDrv == 0x80 ? ATA_DEV_MASTER : ATA_DEV_SLAVE; /* simplified */
    822     }
    823 
    824     /*
    825      * Detect drive parameters.
    826      */
    827     if (GetDriveParams() == 0)
    828     {
    829         static uint8_t s_abSaved[512];
    830         if (ReadSector(iSector, s_abSaved) == 0)
    831         {
    832             static uint8_t s_abWrite[512];
    833             unsigned i;
    834             unsigned cTries;
    835             //unsigned cMaxTries = 20;
    836             unsigned cMaxTries = 1;
    837 
    838             for (i = 0; i < 512; i++)
    839                 s_abWrite[i] = (uint8_t)i;
    840 
    841             for (cTries = 0; cTries < cMaxTries && rc != 0; cTries++)
    842             {
    843                 if (WriteSector(iSector, s_abWrite) == 0)
    844                 {
    845                     static uint8_t s_abReadBack[512];
    846 
    847                     if (ReadSector(iSector, s_abReadBack) == 0)
    848                     {
    849                         for (i = 0; i < 512; i++)
    850                             s_abWrite[i] = (uint8_t)i;
    851 
    852                         if (memcmp(s_abReadBack, s_abWrite, sizeof(s_abReadBack)) == 0)
    853                         {
    854                             rc = 0;
    855                             printf("wrote sector and successfully read it back\n");
    856                         }
    857                         else if (cTries >= cMaxTries - 1)
    858                         {
    859                             unsigned cErrors = 0;
    860                             fprintf(stderr, "read back doesn't match what was written:\n");
    861                             for (i = 0; i < 512; i++)
    862                                 if (s_abReadBack[i] != (uint8_t)i)
    863                                 {
    864                                     fprintf(stderr,  "  %03x: %02x->%02x", i, (uint8_t)i, s_abReadBack[i]);
    865                                     if ((cErrors % 5) == 4)
    866                                         fprintf(stderr, "\n");
    867                                     cErrors++;
    868                                     if (cErrors > 5 * 10)
    869                                         break;
    870                                 }
    871                             if ((cErrors % 5) != 0)
    872                                 fprintf(stderr, "\n");
    873                         }
    874                     }
    875 
    876                 }
    877             }
    878 
    879             /* restore */
    880             WriteSector(iSector, s_abSaved);
    881         }
    882     }
    883 
    884 
    885     return rc;
    886 }
    887 
Note: See TracChangeset for help on using the changeset viewer.