Changeset 73 in kStuff
- Timestamp:
- Dec 20, 2015 9:17:34 PM (9 years ago)
- Location:
- hacks/xtide
- Files:
-
- 3 added
- 1 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
hacks/xtide/atalib.c
r72 r73 33 33 #include <io.h> 34 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 53 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 35 #include "atalib.h" 36 37 #define STR_TUPLE(a_szStr) a_szStr, sizeof(a_szStr) - 1 132 38 133 39 … … 135 41 * Global Variables * 136 42 *********************************************************************************************************************************/ 137 uint16_t g_uBasePort = 0x300; 138 uint16_t g_uPortShift = 1; 43 uint16_t g_uBasePort; 44 uint16_t g_uCtrlPort; 45 uint16_t g_uPortShift; 46 uint8_t g_bDevice; 139 47 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; 143 48 uint8_t g_f8BitData; 49 uint8_t g_fSupportsSetFeature8BitData; 50 uint8_t g_fSupportsSetFeatureWriteCache; 51 uint8_t g_fSupportsSetFeatureXferMode; 52 int8_t g_fSupportsReadBuffer = -1; 53 int8_t g_fSupportsWriteBuffer = -1; 144 54 145 55 uint16_t g_cHeads; … … 307 217 } 308 218 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 //// do316 //// {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 219 void AtaWriteData(void const *pvBuf, size_t cb, uint8_t f8BitData) 342 220 { 343 // uint16_t uAltStsPort = ATA_REG_ALT_STATUS(g_uBasePort);344 221 uint16_t register uDataPort = ATA_REG_DATA(g_uBasePort); 345 222 uint16_t const *pu16 = (uint16_t const *)pvBuf; 223 224 cb >>= 1; 346 225 if (f8BitData) 347 226 { 348 #if 0349 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 // else375 // printf("bSts1=%#x bSts2=%#x\n", bSts1, bSts2);376 //}377 }378 inp(0x21);379 #else380 uint16_t const *pu16 = (uint16_t const *)pvBuf;381 cb >>= 1;382 227 while (cb-- > 0) 383 228 { … … 386 231 outp(uDataPort, (uint8_t)(u16 >> 8)); 387 232 } 388 #endif389 233 } 390 234 else 391 {392 uint16_t const *pu16 = (uint16_t const *)pvBuf;393 cb >>= 1;394 235 while (cb-- > 0) 395 outp(uDataPort, *pu16++); 396 } 236 outpw(uDataPort, *pu16++); 397 237 } 398 238 … … 403 243 return AtaError(bSts, "Prepping for reading sector %lu", iSector); 404 244 405 printf("AtaReadSector #2\n");406 245 bSts = AtaSelectDevice(g_bDevice); 407 246 if (bSts & ATA_STS_ERR) 408 247 return AtaError(bSts, "Selecting device for reading sector %lu", iSector); 409 248 410 //printf("AtaReadSector #3\n");411 249 outp(ATA_REG_FEATURES(g_uBasePort), 0x0); 412 250 outp(ATA_REG_SECTOR_COUNT(g_uBasePort), 1); 413 251 AtaSetSectorAddress(iSector, g_bDevice); 414 252 415 //printf("AtaReadSector #4\n");416 253 bSts = AtaSubmitCommandAndWaitForData(ATA_CMD_READ_SECTORS); 417 254 if (bSts & ATA_STS_ERR) … … 421 258 return AtaError(bSts, "DRQ not set after reading sector %lu", iSector); 422 259 423 424 //printf("AtaReadSector #5\n");425 260 AtaReadData(pvBuf, 512, g_f8BitData); 426 //printf("AtaReadSector #6: bSts=%#x\n", inp(ATA_REG_ALT_STATUS(g_uBasePort)));427 261 bSts = inp(ATA_REG_STATUS(g_uBasePort)); 428 if ( (bSts & ATA_STS_DRQ))262 if (bSts & ATA_STS_DRQ) 429 263 return AtaError(bSts, "DRQ is still set after reading sector %lu", iSector); 430 if ( (bSts & ATA_STS_ERR))264 if (bSts & ATA_STS_ERR) 431 265 return AtaError(bSts, "ERR is set after reading sector %lu (#2)", iSector); 432 266 return 0; … … 435 269 int AtaWriteSector(uint32_t iSector, void const *pvBuf) 436 270 { 437 //int x = printf("AtaWriteSector #1\n");438 271 uint8_t bSts = AtaWaitBusy(); 439 272 if (bSts & ATA_STS_ERR) 440 273 return AtaError(bSts, "Prepping for writing sector %lu", iSector); 441 printf("AtaWriteSector #2\n");442 274 443 275 bSts = AtaSelectDevice(g_bDevice); … … 449 281 AtaSetSectorAddress(iSector, g_bDevice); 450 282 451 //printf("AtaWriteSector #3\n");452 283 bSts = AtaSubmitCommandAndWaitForData(ATA_CMD_WRITE_SECTORS); 453 284 if (bSts & ATA_STS_ERR) … … 456 287 return AtaError(bSts, "DRQ not set after writing sector (#1) %lu", iSector); 457 288 458 //printf("AtaWriteSector #4\n");459 289 AtaWriteData(pvBuf, 512, g_f8BitData); 460 //printf("AtaWriteSector #5\n");461 290 ATA_DELAY_400NS(); 462 291 bSts = AtaWaitBusy(); 463 //printf("AtaWriteSector #6\n");464 292 if (bSts & ATA_STS_ERR) 465 293 return AtaError(bSts, "writing sector (#2) %lu", iSector); 466 294 if (bSts & ATA_STS_DRQ) 467 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 */ 304 int 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 344 int 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)"); 468 381 469 382 return 0; … … 571 484 } 572 485 573 574 int AtaInit(void) 575 { 576 uint8_t bSts = inp(ATA_REG_ALT_STATUS(g_uBasePort)); 577 printf("alt status="); 486 int 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 523 int 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="); 578 554 AtaPrintStatus(stdout, bSts); 579 555 printf("\n"); 580 556 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(); 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 635 int 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 668 int 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; 752 676 #else 753 return AtaInit(); 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; 754 681 #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++) 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) 842 695 { 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 } 696 fprintf(stderr, "error: Invalid port number %#lx for %s (valid range 0x010..0x3ff)\n", uTmp, pszArg); 697 return -1; 877 698 } 878 879 /* restore */ 880 WriteSector(iSector, s_abSaved); 881 } 882 } 883 884 885 return rc; 886 } 887 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 -
hacks/xtide/atalib.h
r72 r73 23 23 24 24 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 32 28 #include <stdint.h> 33 #include <io.h>34 #include <conio.h>35 36 /*********************************************************************************************************************************37 * Structures and Typedefs *38 *********************************************************************************************************************************/39 typedef struct REGS1640 {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 153 29 54 30 /* The necessary I/O ports, indexed by "bus". */ 55 31 #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)) 59 35 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)) 64 40 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. */ 70 46 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)) 73 49 74 50 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) 85 61 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) 95 71 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 */ 99 75 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) 112 90 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. */ 113 93 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) 122 99 #define ATA_FV_XFERMODE_PIO_MODE_DEFAULT UINT8_C(0x00) 123 100 #define ATA_FV_XFERMODE_PIO_MODE_DEFAULT_NO_IORDY UINT8_C(0x01) … … 130 107 #define ATA_DELAY_400NS() do { inp(0x21); } while (0) 131 108 109 extern uint16_t g_cHeads; 110 extern uint8_t g_cSectorsPerTrack; 111 extern uint16_t g_cCylinders; 112 extern uint16_t g_cSectorsPerCylinder; 113 extern uint16_t g_awIdentify[256]; 132 114 115 int AtaInit(uint16_t uBasePort, uint16_t uCtrlPort, uint8_t uPortShift, uint8_t bDevice, uint8_t f8BitData); 116 int AtaInitFromArgv(int iArg, int cArgs, char **papszArgs); 117 int AtaReInit(void); 118 int AtaReset(void); 119 int AtaIdentifyDevice(uint8_t bDevice, void *pvBuf); 120 int AtaInitDeviceParams(uint8_t bDevice, uint8_t cSectorsPerTrack, uint8_t cHeads); 121 int AtaSetFeature(uint8_t bDevice, uint8_t bFeature, uint8_t bValue); 122 int AtaWriteSector(uint32_t iSector, void const *pvBuf); 123 int AtaReadSector(uint32_t iSector, void *pvBuf); 124 int AtaWriteBuffer(void const *pvBuf, uint8_t fExtraChecks); 125 int AtaReadBuffer(void *pvBuf, uint8_t fExtraChecks); 126 void AtaWriteData(void const *pvBuf, size_t cb, uint8_t f8BitData); 127 void AtaReadData(void *pvBuf, size_t cb, uint8_t f8BitData); 133 128 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 143 130 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 do205 {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 do218 {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_DRDY223 && !(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 do232 {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_DRQ237 && !(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 else274 {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 else303 {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 //// do316 //// {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 0349 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 // else375 // printf("bSts1=%#x bSts2=%#x\n", bSts1, bSts2);376 //}377 }378 inp(0x21);379 #else380 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 #endif389 }390 else391 {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 methods618 * INT13h access methods619 * INT13h access methods620 */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_INT13H751 return Int13hInit();752 #else753 return AtaInit();754 #endif755 }756 757 int ReadSector(uint32_t iSector, void *pvBuf)758 {759 #ifdef USE_INT13H760 return Int13hReadSector(iSector, pvBuf);761 #else762 return AtaReadSector(iSector, pvBuf);763 #endif764 }765 766 int WriteSector(uint32_t iSector, void const *pvBuf)767 {768 #ifdef USE_INT13H769 return Int13hWriteSector(iSector, pvBuf);770 #else771 return AtaWriteSector(iSector, pvBuf);772 #endif773 }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 == 0805 || (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 -
hacks/xtide/writeatatest.c
r72 r73 33 33 #include <io.h> 34 34 #include <conio.h> 35 #include "atalib.h" 36 35 37 36 38 /********************************************************************************************************************************* … … 52 54 #define X86_EFL_CF 1 53 55 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 133 56 134 57 /********************************************************************************************************************************* 135 58 * Global Variables * 136 59 *********************************************************************************************************************************/ 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 60 uint8_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 do205 {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 do218 {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_DRDY223 && !(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 do232 {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_DRQ237 && !(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 else274 {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 else303 {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 //// do316 //// {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 0349 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 // else375 // printf("bSts1=%#x bSts2=%#x\n", bSts1, bSts2);376 //}377 }378 inp(0x21);379 #else380 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 #endif389 }390 else391 {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 61 615 62 … … 746 193 747 194 748 int GetDriveParams( void)195 int GetDriveParams(uint8_t bDevice) 749 196 { 750 197 #ifdef USE_INT13H 751 198 return Int13hInit(); 752 199 #else 753 return AtaInit();200 return 0; 754 201 #endif 755 202 } … … 791 238 */ 792 239 uint32_t iSector = 3; 240 uint8_t bDevice = ATA_DEV_MASTER; 793 241 g_bDrv = 0x80; 794 g_bDevice = ATA_DEV_MASTER;795 242 796 243 if (argc > 3) … … 812 259 if (argc > 2) 813 260 { 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) 818 262 return usage(); 819 }820 g_bDrv = (uint8_t)uTmp;821 g_bDevice = g_bDrv == 0x80 ? ATA_DEV_MASTER : ATA_DEV_SLAVE; /* simplified */822 263 } 823 264 … … 825 266 * Detect drive parameters. 826 267 */ 827 if (GetDriveParams( ) == 0)268 if (GetDriveParams(bDevice) == 0) 828 269 { 829 270 static uint8_t s_abSaved[512];
Note:
See TracChangeset
for help on using the changeset viewer.