1/* 2 * ATA_media.c - 3 * 4 * Written by Eryk Vershen 5 */ 6 7/* 8 * Copyright 1997,1998 by Apple Computer, Inc. 9 * All Rights Reserved 10 * 11 * Permission to use, copy, modify, and distribute this software and 12 * its documentation for any purpose and without fee is hereby granted, 13 * provided that the above copyright notice appears in all copies and 14 * that both the copyright notice and this permission notice appear in 15 * supporting documentation. 16 * 17 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 * FOR A PARTICULAR PURPOSE. 20 * 21 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 22 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 23 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 24 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 25 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 26 */ 27 28 29// for printf() 30#include <stdio.h> 31// for malloc() & free() 32#include <stdlib.h> 33#include <ATA.h> 34// for SCSI command structures 35#include "MacSCSICommand.h" 36#include "ATA_media.h" 37#include "util.h" 38 39 40/* 41 * Defines 42 */ 43#define RESULT_OFFSET(type) \ 44 ((sizeof(type) == 1) ? 3 : ((sizeof(type) == 2) ? 1 : 0)) 45#define TBTrapTableAddress(trapNum) (((trapNum & 0x03FF) << 2) + 0xE00) 46#define SWAP_SHORTS(x) ((((x) & 0xFFFF) << 16) | (((x) >> 16) & 0xFFFF)) 47#define LBA_CAPABLE 0x0200 48 49 50/* 51 * Types 52 */ 53typedef struct ATA_info *ATA_INFO; 54 55struct ATA_info { 56 long lba; 57 long heads; 58 long sectors; 59}; 60 61typedef struct ATA_media *ATA_MEDIA; 62 63struct ATA_media { 64 struct media m; 65 long id; 66 struct ATA_info info; 67}; 68 69struct ATA_manager { 70 long exists; 71 long kind; 72 struct { 73 char major; 74 char minor; 75 } version; 76 short busCount; 77 long *bus_list; 78}; 79 80typedef struct ATA_media_iterator *ATA_MEDIA_ITERATOR; 81 82struct ATA_media_iterator { 83 struct media_iterator m; 84 long bus_index; 85 long bus; 86 long id; 87}; 88 89struct ATA_identify_drive_info { /* word */ 90 unsigned short config_bits; /* 0 */ 91 unsigned short num_cylinders; /* 1 */ 92 unsigned short reserved2; /* 2 */ 93 unsigned short num_heads; /* 3 */ 94 unsigned short bytes_per_track; /* 4 */ 95 unsigned short bytes_per_sector; /* 5 */ 96 unsigned short sectors_per_track; /* 6 */ 97 unsigned short vendor7[3]; /* 7-9 */ 98 char serial_number[20]; /* 10-19 */ 99 unsigned short buffer_type; /* 20 */ 100 unsigned short buffer_size; /* 21 */ 101 unsigned short num_of_ecc_bytes; /* 22 */ 102 char firmware_rev[8]; /* 23-26 */ 103 char model_number[40]; /* 27-46 */ 104 unsigned short word47; /* 47 */ 105 unsigned short double_word_io; /* 48 */ 106 unsigned short capabilities; /* 49 */ 107 unsigned short reserved50; /* 50 */ 108 unsigned short pio_timing; /* 51 */ 109 unsigned short dma_timing; /* 52 */ 110 unsigned short current_is_valid; /* 53 */ 111 unsigned short cur_cylinders; /* 54 */ 112 unsigned short cur_heads; /* 55 */ 113 unsigned short cur_sec_per_track; /* 56 */ 114 unsigned long total_sectors; /* 57-58 */ 115 unsigned short multiple_sectors; /* 59 */ 116 unsigned long lba_sectors; /* 60-61 */ 117 unsigned short singleword_dma; /* 62 */ 118 unsigned short multiword_dma; /* 63 */ 119 unsigned short reserved64[64]; /* 64-127 */ 120 unsigned short vendor128[32]; /* 128-159 */ 121 unsigned short reserved160[96]; /* 160-255 */ 122}; 123 124struct ATAPI_identify_drive_info { /* word */ 125 unsigned short config_bits; /* 0 */ 126 unsigned short retired1[9]; /* 1-9 */ 127 char serial_number[20]; /* 10-19 */ 128 unsigned short retired20[3]; /* 20-22 */ 129 char firmware_rev[8]; /* 23-26 */ 130 char model_number[40]; /* 27-46 */ 131 unsigned short retired47[2]; /* 47-48 */ 132 unsigned short capabilities; /* 49 */ 133 unsigned short reserved50; /* 50 */ 134 unsigned short pio_timing; /* 51 */ 135 unsigned short dma_timing; /* 52 */ 136 unsigned short current_is_valid; /* 53 */ 137 unsigned short retired54[8]; /* 54-61 */ 138 unsigned short singleword_dma; /* 62 */ 139 unsigned short multiword_dma; /* 63 */ 140 unsigned short pio_transfer; /* 64 */ 141 unsigned short min_cycle_time; /* 65 */ 142 unsigned short rec_cycle_time; /* 66 */ 143 unsigned short min_wo_flow; /* 67 */ 144 unsigned short min_with_flow; /* 68 */ 145 unsigned short reserved69[2]; /* 69-70 */ 146 unsigned short release_over; /* 71 */ 147 unsigned short release_service; /* 72 */ 148 unsigned short major_rev; /* 73 */ 149 unsigned short minor_rev; /* 74 */ 150 unsigned short reserved75[53]; /* 75-127 */ 151 unsigned short vendor128[32]; /* 128-159 */ 152 unsigned short reserved160[96]; /* 160-255 */ 153}; 154 155/* Identifies the bus protocol type. */ 156enum { 157 kDevUnknown = 0, 158 kDevATA = 1, 159 kDevATAPI = 2, 160 kDevPCMCIA = 3 161}; 162 163 164/* 165 * Global Constants 166 */ 167enum { 168 kNoDevice = 0x00FF, 169 kATAtimeout = 3000, 170 kATAcmdATAPIPacket = 0x00A0 /* ATAPI packet command */ 171}; 172 173 174/* 175 * Global Variables 176 */ 177static long ata_inited = 0; 178static struct ATA_manager ata_mgr; 179 180/* 181 * Forward declarations 182 */ 183int ATAManagerPresent(void); 184int ATAHardwarePresent(void); 185pascal SInt16 ataManager(ataPB *pb); 186void ata_init(void); 187ATA_MEDIA new_ata_media(void); 188long read_ata_media(MEDIA m, long long offset, unsigned long count, void *address); 189long write_ata_media(MEDIA m, long long offset, unsigned long count, void *address); 190long close_ata_media(MEDIA m); 191long os_reload_ata_media(MEDIA m); 192long compute_id(long bus, long device); 193pascal SInt16 ataManager(ataPB *pb); 194int ATA_ReadBlock(UInt32 deviceID, ATA_INFO info, UInt32 block_size, UInt32 block, UInt8 *address); 195int ATA_WriteBlock(UInt32 deviceID, ATA_INFO info, UInt32 block_size, UInt32 block, UInt8 *address); 196long get_info(long id, struct ATA_identify_drive_info *ip); 197long get_pi_info(long id, struct ATAPI_identify_drive_info *ip); 198long is_atapi(long id); 199long read_atapi_media(MEDIA m, long long offset, unsigned long count, void *address); 200long write_atapi_media(MEDIA m, long long offset, unsigned long count, void *address); 201int ATAPI_ReadBlock(UInt32 deviceID, UInt32 block_size, UInt32 block, UInt8 *address); 202int ATAPI_TestUnitReady(UInt32 deviceID); 203int ATAPI_ReadCapacity(UInt32 deviceID, unsigned long *block_size, unsigned long *blocks); 204ATA_MEDIA_ITERATOR new_ata_iterator(void); 205void reset_ata_iterator(MEDIA_ITERATOR m); 206char *step_ata_iterator(MEDIA_ITERATOR m); 207void delete_ata_iterator(MEDIA_ITERATOR m); 208int ata_bus_present(int num); 209 210 211/* 212 * Routines 213 */ 214#if GENERATINGPOWERPC 215pascal SInt16 216ataManager(ataPB *pb) 217{ 218 #ifdef applec 219 #if sizeof(SInt16) > 4 220 #error "Result types larger than 4 bytes are not supported." 221 #endif 222 #endif 223 long private_result; 224 225 private_result = CallUniversalProc( 226 *(UniversalProcPtr*)TBTrapTableAddress(0xAAF1), 227 kPascalStackBased 228 | RESULT_SIZE(SIZE_CODE(sizeof(SInt16))) 229 | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(pb))), 230 pb); 231 return *(((SInt16*)&private_result) + RESULT_OFFSET(SInt16)); 232} 233#endif 234 235 236int 237ATAHardwarePresent(void) 238{ 239 UInt16 configFlags; 240 241 // Hardware configuration flags 242 configFlags = LMGetHWCfgFlags(); 243 244 return ((configFlags & 0x0080) != 0); 245} 246 247 248int 249ATAManagerPresent(void) 250{ 251 if (ATAHardwarePresent()) { 252 return (TrapAvailable(kATATrap)); 253 } else { 254 return 0; 255 } 256} 257 258void 259ata_init(void) 260{ 261 ataMgrInquiry pb; 262 OSErr status; 263 int i; 264 int j; 265 266 if (ata_inited != 0) { 267 return; 268 } 269 ata_inited = 1; 270 271 if (ATAManagerPresent() == 0) { 272 ata_mgr.exists = 0; 273 return; 274 } 275 276 ata_mgr.exists = 1; 277 ata_mgr.kind = allocate_media_kind(); 278 279 clear_memory((void *)&pb, sizeof(pb)); 280 281 pb.ataPBFunctionCode = kATAMgrManagerInquiry; 282 pb.ataPBVers = kATAPBVers1; 283 284 status = ataManager((ataPB*) &pb ); 285 286 if (status != noErr) { 287 ata_mgr.exists = 0; 288 return; 289 } 290 ata_mgr.version.major = pb.ataMgrVersion.majorRev; 291 ata_mgr.version.minor = pb.ataMgrVersion.minorAndBugRev >> 4; 292 ata_mgr.busCount = pb.ataBusCnt; 293 294 ata_mgr.bus_list = (long *) calloc(ata_mgr.busCount, sizeof(long)); 295 if (ata_mgr.bus_list == 0) { 296 ata_mgr.busCount = 0; 297 } else { 298 for (i = 0, j = 0; j < ata_mgr.busCount; i++) { 299 if (ata_bus_present(i)) { 300 ata_mgr.bus_list[j] = i; 301 j++; 302 } 303 } 304 } 305} 306 307 308int 309ata_bus_present(int num) 310{ 311 ataBusInquiry pb; 312 OSErr status; 313 314 clear_memory((void *)&pb, sizeof(pb)); 315 316 pb.ataPBFunctionCode = kATAMgrBusInquiry; 317 pb.ataPBVers = kATAPBVers1; 318 pb.ataPBDeviceID = num; 319 320 status = ataManager((ataPB*) &pb ); 321 322 if (status == noErr) { 323 return 1; 324 } else { 325 //printf("status = %d\n", status); 326 return 0; 327 } 328} 329 330 331ATA_MEDIA 332new_ata_media(void) 333{ 334 return (ATA_MEDIA) new_media(sizeof(struct ATA_media)); 335} 336 337 338#pragma mark - 339 340 341long 342compute_id(long bus, long device) 343{ 344 long id; 345 int i; 346 347 id = -1; 348 for (i = 0; i < ata_mgr.busCount; i++) { 349 if (bus == ata_mgr.bus_list[i]) { 350 break; 351 } 352 } 353 if (i >= ata_mgr.busCount) { 354 /* bad bus id */ 355 } else if (ata_mgr.version.major < 3) { 356 if (device != 0) { 357 /* bad device id */ 358 } else { 359 id = bus & 0xFF; 360 } 361 } else { 362 if (device < 0 || device > 1) { 363 /* bad device id */ 364 } else { 365 id = ((device & 0xFF) << 8) | (bus & 0xFF); 366 } 367 } 368 return id; 369} 370 371 372static long 373get_info(long id, struct ATA_identify_drive_info *ip) 374{ 375 ataIdentify pb; 376 ataDevConfiguration pb2; 377 OSErr status; 378 long rtn_value; 379 long atapi; 380 381 if (sizeof(struct ATA_identify_drive_info) < 512) { 382 return 0; 383 } 384 clear_memory((void *)ip, sizeof(struct ATA_identify_drive_info)); 385 386 clear_memory((void *)&pb, sizeof(pb)); 387 pb.ataPBFunctionCode = kATAMgrDriveIdentify; 388 pb.ataPBVers = kATAPBVers1; 389 pb.ataPBDeviceID = id; 390 pb.ataPBFlags = mATAFlagIORead | mATAFlagByteSwap; 391 pb.ataPBTimeOut = kATAtimeout; 392 pb.ataPBBuffer = (void*) ip; 393 394 status = ataManager((ataPB*) &pb ); 395 396 if (status != noErr) { 397 //printf("get info status = %d\n", status); 398 rtn_value = 0; 399 } else { 400 ip->total_sectors = SWAP_SHORTS(ip->total_sectors); 401 ip->lba_sectors = SWAP_SHORTS(ip->lba_sectors); 402 rtn_value = 1; 403 } 404 return rtn_value; 405} 406 407 408static long 409is_atapi(long id) 410{ 411 ataDevConfiguration pb; 412 OSErr status; 413 long atapi; 414 415 atapi = 0; 416 if (ata_mgr.version.major >= 2) { 417 clear_memory((void *)&pb, sizeof(pb)); 418 pb.ataPBFunctionCode = kATAMgrGetDrvConfiguration; 419 pb.ataPBVers = kATAPBVers2; 420 pb.ataPBDeviceID = id; 421 pb.ataPBTimeOut = kATAtimeout; 422 423 status = ataManager((ataPB*) &pb ); 424 if (status != noErr) { 425 //printf("is atatpi status = %d\n", status); 426 } else if (pb.ataDeviceType == kDevATAPI) { 427 atapi = 1; 428 /* the drive can be asleep or something in which case this doesn't work */ 429 /* how do we do reads */ 430 } 431 } 432 return atapi; 433} 434 435 436MEDIA 437open_ata_as_media(long bus, long device) 438{ 439 ATA_MEDIA a; 440 long id; 441 struct ATA_identify_drive_info info; 442 unsigned char *buf; 443 unsigned long total; 444 445 if (ata_inited == 0) { 446 ata_init(); 447 } 448 449 if (ata_mgr.exists == 0) { 450 //printf("ATA manager does not exist\n"); 451 return 0; 452 } 453 454 id = compute_id(bus, device); 455 456 if (id < 0) { 457 return 0; 458 459 } else if (is_atapi(id)) { 460 a = (ATA_MEDIA) open_atapi_as_media(bus, device); 461 462 } else { 463 a = 0; 464 if (get_info(id, &info) != 0) { 465 a = new_ata_media(); 466 if (a != 0) { 467 a->m.kind = ata_mgr.kind; 468 if ((info.capabilities & LBA_CAPABLE) != 0) { 469 total = info.lba_sectors; 470 a->info.lba = 1; 471 a->info.heads = 0; 472 a->info.sectors = 0; 473 } else { 474 /* Only CHS - Cylinder Head Sector addressing */ 475 total = info.total_sectors; 476 a->info.lba = 0; 477 a->info.heads = info.cur_heads; 478 a->info.sectors = info.cur_sec_per_track; 479 } 480 { /* XXX this should be a loop in a subroutine */ 481 buf = malloc(2048); 482 if (ATA_ReadBlock(id, &a->info, 512, 0, buf)) { 483 a->m.grain = 512; 484 } else if (ATA_ReadBlock(id, &a->info, 1024, 0, buf)) { 485 a->m.grain = 1024; 486 } else if (ATA_ReadBlock(id, &a->info, 2048, 0, buf)) { 487 a->m.grain = 2048; 488 } else { 489 a->m.grain = 512; /* XXX should really return failure here */ 490 } 491 free(buf); 492 } 493 if (total == 0) { 494 a->m.size_in_bytes = ((long long)1000) * a->m.grain; /* XXX not right */ 495 } else { 496 a->m.size_in_bytes = ((long long)total) * a->m.grain; 497 } 498 a->m.do_read = read_ata_media; 499 a->m.do_write = write_ata_media; 500 a->m.do_close = close_ata_media; 501 a->m.do_os_reload = os_reload_ata_media; 502 a->id = id; 503 } 504 } else { 505 printf("ATA - couldn't get info\n"); 506 } 507 } 508 return (MEDIA) a; 509} 510 511 512long 513read_ata_media(MEDIA m, long long offset, unsigned long count, void *address) 514{ 515 ATA_MEDIA a; 516 ataIOPB pb; 517 OSErr status; 518 long rtn_value; 519 long block; 520 long block_count; 521 long block_size; 522 unsigned char *buffer; 523 int i; 524 525 a = (ATA_MEDIA) m; 526 rtn_value = 0; 527 if (a == 0) { 528 /* no media */ 529 } else if (a->m.kind != ata_mgr.kind) { 530 /* wrong kind - XXX need to error here - this is an internal problem */ 531 } else if (count <= 0 || count % a->m.grain != 0) { 532 /* can't handle size */ 533 } else if (offset < 0 || offset % a->m.grain != 0) { 534 /* can't handle offset */ 535 } else if (offset + count > a->m.size_in_bytes) { 536 /* check for offset (and offset+count) too large */ 537 } else { 538 /* do a read on the physical device */ 539 block_size = a->m.grain; 540 block = offset / block_size; 541 block_count = count / block_size; 542 buffer = address; 543 rtn_value = 1; 544 for (i = 0; i < block_count; i++) { 545 if (ATA_ReadBlock(a->id, &a->info, block_size, block, buffer) == 0) { 546 rtn_value = 0; 547 break; 548 } 549 buffer += block_size; 550 block += 1; 551 } 552 } 553 return rtn_value; 554} 555 556 557long 558write_ata_media(MEDIA m, long long offset, unsigned long count, void *address) 559{ 560 ATA_MEDIA a; 561 long rtn_value; 562 long block; 563 long block_count; 564 long block_size; 565 unsigned char *buffer; 566 int i; 567 568 a = (ATA_MEDIA) m; 569 rtn_value = 0; 570 if (a == 0) { 571 /* no media */ 572 } else if (a->m.kind != ata_mgr.kind) { 573 /* XXX need to error here - this is an internal problem */ 574 } else if (count <= 0 || count % a->m.grain != 0) { 575 /* can't handle size */ 576 } else if (offset < 0 || offset % a->m.grain != 0) { 577 /* can't handle offset */ 578 } else if (offset + count > a->m.size_in_bytes) { 579 /* check for offset (and offset+count) too large */ 580 } else { 581 /* do a write on the physical device */ 582 block_size = a->m.grain; 583 block = offset / block_size; 584 block_count = count / block_size; 585 buffer = address; 586 rtn_value = 1; 587 for (i = 0; i < block_count; i++) { 588 if (ATA_WriteBlock(a->id, &a->info, block_size, block, buffer) == 0) { 589 rtn_value = 0; 590 break; 591 } 592 buffer += block_size; 593 block += 1; 594 } 595 } 596 return rtn_value; 597} 598 599 600long 601close_ata_media(MEDIA m) 602{ 603 ATA_MEDIA a; 604 605 a = (ATA_MEDIA) m; 606 if (a == 0) { 607 return 0; 608 } else if (a->m.kind != ata_mgr.kind) { 609 /* XXX need to error here - this is an internal problem */ 610 return 0; 611 } 612 /* XXX nothing to do - I think? */ 613 return 1; 614} 615 616 617long 618os_reload_ata_media(MEDIA m) 619{ 620 printf("Reboot your system so the partition table will be reread.\n"); 621 return 1; 622} 623 624 625int 626ATA_ReadBlock(UInt32 deviceID, ATA_INFO info, UInt32 block_size, UInt32 block, UInt8 *address) 627{ 628 ataIOPB pb; 629 OSErr status; 630 long slave; 631 long lba, cyl, head, sector; 632 633 clear_memory((void *)&pb, sizeof(pb)); 634 pb.ataPBFunctionCode = kATAMgrExecIO; 635 pb.ataPBVers = kATAPBVers1; 636 pb.ataPBDeviceID = deviceID; 637 pb.ataPBFlags = mATAFlagTFRead | mATAFlagIORead ; 638 pb.ataPBTimeOut = kATAtimeout; 639 640 pb.ataPBLogicalBlockSize = block_size; 641 pb.ataPBBuffer = address; 642 pb.ataPBByteCount = block_size; 643 if (info->lba) { 644 lba = 0x40; 645 sector = block & 0xFF; 646 head = (block >> 24) & 0xF; 647 cyl = (block >> 8) & 0xFFFF; 648 } else { 649 lba = 0x00; 650 sector = (block % info->sectors) + 1; 651 cyl = block / info->sectors; 652 head = cyl % info->heads; 653 cyl = cyl / info->heads; 654 } 655 656 pb.ataPBTaskFile.ataTFCount = 1; 657 pb.ataPBTaskFile.ataTFSector = sector; 658 pb.ataPBTaskFile.ataTFCylinder = cyl; 659 if (deviceID & 0x0FF00) { 660 slave = 0x10; 661 } else { 662 slave = 0x0; 663 } 664 /* std | L/C | Drive | head */ 665 pb.ataPBTaskFile.ataTFSDH = 0xA0 | lba | slave | head; 666 pb.ataPBTaskFile.ataTFCommand = kATAcmdRead; 667 668 status = ataManager((ataPB*) &pb ); 669 if (status != noErr) { 670 /* failure */ 671 //printf(" ATA read status = %d\n", status); 672 return 0; 673 } else { 674 return 1; 675 } 676} 677 678 679int 680ATA_WriteBlock(UInt32 deviceID, ATA_INFO info, UInt32 block_size, UInt32 block, UInt8 *address) 681{ 682 ataIOPB pb; 683 OSErr status; 684 long slave; 685 long lba, cyl, head, sector; 686 687 clear_memory((void *)&pb, sizeof(pb)); 688 pb.ataPBFunctionCode = kATAMgrExecIO; 689 pb.ataPBVers = kATAPBVers1; 690 pb.ataPBDeviceID = deviceID; 691 pb.ataPBFlags = mATAFlagTFRead | mATAFlagIOWrite ; 692 pb.ataPBTimeOut = kATAtimeout; 693 694 pb.ataPBLogicalBlockSize = block_size; 695 pb.ataPBBuffer = address; 696 pb.ataPBByteCount = block_size; 697 if (info->lba) { 698 lba = 0x40; 699 sector = block & 0xFF; 700 head = (block >> 24) & 0xF; 701 cyl = (block >> 8) & 0xFFFF; 702 } else { 703 lba = 0x00; 704 sector = (block % info->sectors) + 1; 705 cyl = block / info->sectors; 706 head = cyl % info->heads; 707 cyl = cyl / info->heads; 708 } 709 pb.ataPBTaskFile.ataTFCount = 1; 710 pb.ataPBTaskFile.ataTFSector = sector; 711 pb.ataPBTaskFile.ataTFCylinder = cyl; 712 if (deviceID & 0x0FF00) { 713 slave = 0x10; 714 } else { 715 slave = 0x0; 716 } 717 /* std | L/C | Drive | head */ 718 pb.ataPBTaskFile.ataTFSDH = 0xA0 | lba | slave | head; 719 pb.ataPBTaskFile.ataTFCommand = kATAcmdWrite; 720 721 status = ataManager((ataPB*) &pb ); 722 if (status != noErr) { 723 /* failure */ 724 return 0; 725 } else { 726 return 1; 727 } 728} 729 730 731#pragma mark - 732 733 734/* 735 * ATAPI stuff 736 */ 737static long 738get_pi_info(long id, struct ATAPI_identify_drive_info *ip) 739{ 740 ataIdentify pb; 741 OSErr status; 742 long rtn_value; 743 744 if (sizeof(struct ATAPI_identify_drive_info) < 512) { 745 return 0; 746 } 747 clear_memory((void *)ip, sizeof(struct ATAPI_identify_drive_info)); 748 749 clear_memory((void *)&pb, sizeof(pb)); 750 pb.ataPBFunctionCode = kATAMgrDriveIdentify; 751 pb.ataPBVers = kATAPBVers1; 752 pb.ataPBDeviceID = id; 753 pb.ataPBFlags = mATAFlagIORead | mATAFlagByteSwap | mATAFlagProtocol1; 754 pb.ataPBTimeOut = kATAtimeout; 755 pb.ataPBBuffer = (void*) ip; 756 757 status = ataManager((ataPB*) &pb ); 758 759 if (status != noErr) { 760 //printf("get pi info status = %d\n", status); 761 rtn_value = 0; 762 } else { 763 rtn_value = 1; 764 } 765 return rtn_value; 766} 767 768 769MEDIA 770open_atapi_as_media(long bus, long device) 771{ 772 ATA_MEDIA a; 773 long id; 774 struct ATAPI_identify_drive_info info; 775 unsigned char *buf; 776 unsigned long block_size; 777 unsigned long blocks; 778 779 if (ata_inited == 0) { 780 ata_init(); 781 } 782 783 if (ata_mgr.exists == 0) { 784 return 0; 785 } 786 787 id = compute_id(bus, device); 788 789 if (!is_atapi(id)) { 790 a = 0; 791 792 } else { 793 a = 0; 794 if (get_pi_info(id, &info) != 0 795 && (info.capabilities & LBA_CAPABLE) != 0) { 796 if (ATAPI_TestUnitReady(id) != 0) { 797 a = new_ata_media(); 798 if (a != 0) { 799 a->m.kind = ata_mgr.kind; 800 if (ATAPI_ReadCapacity(id, &block_size, &blocks) == 0) { 801 block_size = 2048; 802 blocks = 1000; 803 } 804 a->m.grain = block_size; 805 a->m.size_in_bytes = ((long long)blocks) * a->m.grain; 806 a->m.do_read = read_atapi_media; 807 a->m.do_write = write_atapi_media; 808 a->m.do_close = close_ata_media; 809 a->m.do_os_reload = os_reload_ata_media; 810 a->id = id; 811 } 812 } else { 813 printf("ATAPI - unit not ready\n"); 814 } 815 } else { 816 printf("ATAPI - couldn't get info or not LBA capable\n"); 817 } 818 } 819 return (MEDIA) a; 820} 821 822 823long 824read_atapi_media(MEDIA m, long long offset, unsigned long count, void *address) 825{ 826 ATA_MEDIA a; 827 ataIOPB pb; 828 OSErr status; 829 long rtn_value; 830 long block; 831 long block_count; 832 long block_size; 833 unsigned char *buffer; 834 int i; 835 836 a = (ATA_MEDIA) m; 837 rtn_value = 0; 838 if (a == 0) { 839 /* no media */ 840 } else if (a->m.kind != ata_mgr.kind) { 841 /* wrong kind - XXX need to error here - this is an internal problem */ 842 } else if (count <= 0 || count % a->m.grain != 0) { 843 /* can't handle size */ 844 } else if (offset < 0 || offset % a->m.grain != 0) { 845 /* can't handle offset */ 846 } else if (offset + count > a->m.size_in_bytes) { 847 /* check for offset (and offset+count) too large */ 848 } else { 849 /* XXX do a read on the physical device */ 850 block_size = a->m.grain; 851 block = offset / block_size; 852 block_count = count / block_size; 853 buffer = address; 854 rtn_value = 1; 855 for (i = 0; i < block_count; i++) { 856 if (ATAPI_ReadBlock(a->id, block_size, block, buffer) == 0) { 857 rtn_value = 0; 858 break; 859 } 860 buffer += block_size; 861 block += 1; 862 } 863 } 864 return rtn_value; 865} 866 867 868long 869write_atapi_media(MEDIA m, long long offset, unsigned long count, void *address) 870{ 871 return 0; 872} 873 874 875int 876ATAPI_ReadBlock(UInt32 deviceID, UInt32 block_size, UInt32 block, UInt8 *address) 877{ 878 ataIOPB pb; 879 OSErr status; 880 long slave; 881 ATAPICmdPacket cmdPacket; 882 SCSI_10_Byte_Command *gRead; 883 long count; 884 885 clear_memory((void *)&pb, sizeof(pb)); 886 pb.ataPBFunctionCode = kATAMgrExecIO; 887 pb.ataPBVers = kATAPBVers1; 888 pb.ataPBDeviceID = deviceID; 889 pb.ataPBFlags = mATAFlagTFRead | mATAFlagIORead | mATAFlagProtocol1; 890 pb.ataPBTimeOut = kATAtimeout; 891 892 pb.ataPBBuffer = address; 893 pb.ataPBByteCount = block_size; 894 pb.ataPBTaskFile.ataTFCylinder = block_size; 895 if (deviceID & 0x0FF00) { 896 slave = 0x10; 897 } else { 898 slave = 0x0; 899 } 900 /* std | L/C | Drive | head */ 901 pb.ataPBTaskFile.ataTFSDH = 0xA0 | 0x40 | slave; 902 pb.ataPBTaskFile.ataTFCommand = kATAcmdATAPIPacket; 903 pb.ataPBPacketPtr = &cmdPacket; 904 905 cmdPacket.atapiPacketSize = 16; 906 clear_memory((void *)&cmdPacket.atapiCommandByte, 16); 907 gRead = (SCSI_10_Byte_Command *) &cmdPacket.atapiCommandByte[0]; 908 909 gRead->opcode = kScsiCmdRead10; 910 911 gRead->lbn4 = (block >> 24) & 0xFF; 912 gRead->lbn3 = (block >> 16) & 0xFF; 913 gRead->lbn2 = (block >> 8) & 0xFF; 914 gRead->lbn1 = block & 0xFF; 915 916 count = 1; 917 gRead->len2 = (count >> 8) & 0xFF; 918 gRead->len1 = count & 0xFF; 919 920 921 status = ataManager((ataPB*) &pb ); 922 if (status != noErr) { 923 /* failure */ 924 //printf("ATAPI read status = %d\n", status); 925 return 0; 926 } else { 927 return 1; 928 } 929} 930 931 932int 933ATAPI_TestUnitReady(UInt32 deviceID) 934{ 935 ataIOPB pb; 936 OSErr status; 937 long slave; 938 ATAPICmdPacket cmdPacket; 939 SCSI_10_Byte_Command *gTestUnit; 940 941 clear_memory((void *)&pb, sizeof(pb)); 942 pb.ataPBFunctionCode = kATAMgrExecIO; 943 pb.ataPBVers = kATAPBVers1; 944 pb.ataPBDeviceID = deviceID; 945 pb.ataPBFlags = mATAFlagTFRead | mATAFlagIORead | mATAFlagProtocol1; 946 pb.ataPBTimeOut = kATAtimeout; 947 948 if (deviceID & 0x0FF00) { 949 slave = 0x10; 950 } else { 951 slave = 0x0; 952 } 953 /* std | L/C | Drive | head */ 954 pb.ataPBTaskFile.ataTFSDH = 0xA0 | 0x40 | slave; 955 pb.ataPBTaskFile.ataTFCommand = kATAcmdATAPIPacket; 956 pb.ataPBPacketPtr = &cmdPacket; 957 958 cmdPacket.atapiPacketSize = 16; 959 clear_memory((void *)&cmdPacket.atapiCommandByte, 16); 960 gTestUnit = (SCSI_10_Byte_Command *) &cmdPacket.atapiCommandByte[0]; 961 962 gTestUnit->opcode = kScsiCmdTestUnitReady; 963 964 965 status = ataManager((ataPB*) &pb ); 966 if (status != noErr) { 967 /* failure */ 968 //printf("ATAPI test unit ready status = %d\n", status); 969 return 0; 970 } else { 971 return 1; 972 } 973} 974 975 976int 977ATAPI_ReadCapacity(UInt32 deviceID, unsigned long *block_size, unsigned long *blocks) 978{ 979 ataIOPB pb; 980 OSErr status; 981 long slave; 982 ATAPICmdPacket cmdPacket; 983 SCSI_10_Byte_Command *gReadCap; 984 struct read_cap_data { 985 long addr; 986 long size; 987 } rcd; 988 989 clear_memory((void *)&pb, sizeof(pb)); 990 pb.ataPBFunctionCode = kATAMgrExecIO; 991 pb.ataPBVers = kATAPBVers1; 992 pb.ataPBDeviceID = deviceID; 993 pb.ataPBFlags = mATAFlagTFRead | mATAFlagIORead | mATAFlagProtocol1; 994 pb.ataPBTimeOut = kATAtimeout; 995 996 pb.ataPBBuffer = (unsigned char *)&rcd; 997 pb.ataPBByteCount = 8; 998 pb.ataPBTaskFile.ataTFCylinder = 8; 999 if (deviceID & 0x0FF00) { 1000 slave = 0x10; 1001 } else { 1002 slave = 0x0; 1003 } 1004 /* std | L/C | Drive | head */ 1005 pb.ataPBTaskFile.ataTFSDH = 0xA0 | 0x40 | slave; 1006 pb.ataPBTaskFile.ataTFCommand = kATAcmdATAPIPacket; 1007 pb.ataPBPacketPtr = &cmdPacket; 1008 1009 cmdPacket.atapiPacketSize = 16; 1010 clear_memory((void *)&cmdPacket.atapiCommandByte, 16); 1011 gReadCap = (SCSI_10_Byte_Command *) &cmdPacket.atapiCommandByte[0]; 1012 1013 gReadCap->opcode = kScsiCmdReadCapacity; 1014 1015 1016 status = ataManager((ataPB*) &pb ); 1017 if (status != noErr) { 1018 /* failure */ 1019 //printf("ATAPI read capacity status = %d\n", status); 1020 return 0; 1021 } else { 1022 *blocks = rcd.addr; 1023 *block_size = rcd.size; 1024 return 1; 1025 } 1026} 1027 1028 1029MEDIA 1030ATA_FindDevice(long dRefNum) 1031{ 1032 ataDrvrRegister pb; 1033 OSErr status; 1034 1035 if (ATAManagerPresent()) { 1036 clear_memory((void *)&pb, sizeof(pb)); 1037 1038 pb.ataPBFunctionCode = kATAMgrFindDriverRefnum; 1039 pb.ataPBVers = kATAPBVers1; 1040 pb.ataPBDeviceID = 0xFFFF; 1041 pb.ataPBTimeOut = kATAtimeout; 1042 1043 pb.ataDeviceNextID = 1; 1044 do { 1045 status = ataManager((ataPB*) &pb); 1046 1047 if (status != noErr) { 1048 break; 1049 } else if (pb.ataDrvrRefNum == dRefNum 1050 && pb.ataPBDeviceID != kNoDevice) { 1051 return open_ata_as_media(pb.ataPBDeviceID & 0xFF, 1052 (pb.ataPBDeviceID >> 8) & 0xFF); 1053 } else { 1054 pb.ataPBDeviceID = pb.ataDeviceNextID; 1055 } 1056 } while (pb.ataPBDeviceID != kNoDevice); 1057 } 1058 return 0; 1059} 1060 1061 1062#pragma mark - 1063 1064 1065ATA_MEDIA_ITERATOR 1066new_ata_iterator(void) 1067{ 1068 return (ATA_MEDIA_ITERATOR) new_media_iterator(sizeof(struct ATA_media_iterator)); 1069} 1070 1071 1072MEDIA_ITERATOR 1073create_ata_iterator(void) 1074{ 1075 ATA_MEDIA_ITERATOR a; 1076 1077 if (ata_inited == 0) { 1078 ata_init(); 1079 } 1080 1081 if (ata_mgr.exists == 0) { 1082 return 0; 1083 } 1084 1085 a = new_ata_iterator(); 1086 if (a != 0) { 1087 a->m.kind = ata_mgr.kind; 1088 a->m.state = kInit; 1089 a->m.do_reset = reset_ata_iterator; 1090 a->m.do_step = step_ata_iterator; 1091 a->m.do_delete = delete_ata_iterator; 1092 a->bus_index = 0; 1093 a->bus = 0; 1094 a->id = 0; 1095 } 1096 1097 return (MEDIA_ITERATOR) a; 1098} 1099 1100 1101void 1102reset_ata_iterator(MEDIA_ITERATOR m) 1103{ 1104 ATA_MEDIA_ITERATOR a; 1105 1106 a = (ATA_MEDIA_ITERATOR) m; 1107 if (a == 0) { 1108 /* no media */ 1109 } else if (a->m.kind != ata_mgr.kind) { 1110 /* wrong kind - XXX need to error here - this is an internal problem */ 1111 } else if (a->m.state != kInit) { 1112 a->m.state = kReset; 1113 } 1114} 1115 1116 1117char * 1118step_ata_iterator(MEDIA_ITERATOR m) 1119{ 1120 ATA_MEDIA_ITERATOR a; 1121 char *result; 1122 1123 a = (ATA_MEDIA_ITERATOR) m; 1124 if (a == 0) { 1125 /* no media */ 1126 } else if (a->m.kind != ata_mgr.kind) { 1127 /* wrong kind - XXX need to error here - this is an internal problem */ 1128 } else { 1129 switch (a->m.state) { 1130 case kInit: 1131 /* find # of buses (done in ata_init) */ 1132 a->m.state = kReset; 1133 /* fall through to reset */ 1134 case kReset: 1135 a->bus_index = 0 /* low bus id */; 1136 a->bus = ata_mgr.bus_list[a->bus_index]; 1137 a->id = 0 /* low device id */; 1138 a->m.state = kIterating; 1139 /* fall through to iterate */ 1140 case kIterating: 1141 while (1) { 1142 if (a->bus_index >= ata_mgr.busCount/* max bus id */) { 1143 break; 1144 } 1145 if (a->id > 1 /*max id for bus */) { 1146 a->bus_index += 1; 1147 a->bus = ata_mgr.bus_list[a->bus_index]; 1148 a->id = 0 /* low device id */; 1149 continue; /* try again */ 1150 } 1151 if (a->bus > 9) { 1152 // insure that name creation works 1153 break; 1154 } 1155 /* generate result */ 1156 result = (char *) malloc(20); 1157 if (result != NULL) { 1158 snprintf(result, 20, "/dev/ata%c.%c", 1159 '0'+a->bus, '0'+a->id); 1160 } 1161 1162 a->id += 1; /* next id */ 1163 return result; 1164 } 1165 a->m.state = kEnd; 1166 /* fall through to end */ 1167 case kEnd: 1168 default: 1169 break; 1170 } 1171 } 1172 return 0 /* no entry */; 1173} 1174 1175 1176void 1177delete_ata_iterator(MEDIA_ITERATOR m) 1178{ 1179 return; 1180} 1181 1182 1183#pragma mark - 1184 1185 1186#ifdef notdef 1187MEDIA 1188open_linux_ata_as_media(long index) 1189{ 1190 long bus; 1191 long id; 1192 long i; 1193 1194 i = index / 2; 1195 if (i >= ata_mgr.busCount) { 1196 // set bogus id 1197 bus = 0; 1198 id = 2; 1199 } else { 1200 bus = ata_mgr.bus_list[index / 2]; 1201 id = index % 2; 1202 } 1203 1204 return open_ata_as_media(bus, id); 1205} 1206 1207#else 1208 1209MEDIA 1210open_linux_ata_as_media(long index) 1211{ 1212 long bus; 1213 long id; 1214 1215 bus = index / 2; 1216 id = index % 2; 1217 1218 return open_ata_as_media(bus, id); 1219} 1220#endif 1221 1222 1223char * 1224linux_ata_name(long bus, long id) 1225{ 1226 char *result; 1227 1228 if (bus >= 13) { 1229 // a bus >= 13 would be a bogus character 1230 return NULL; 1231 } 1232 result = (char *) malloc(20); 1233 if (result != NULL) { 1234 /* name is hda, hdb, hdc, hdd, ... 1235 * in order (0,0) (0,1) (1,0) (1,1) ... 1236 */ 1237 snprintf(result, 20, "/dev/hd%c", 'a' + (bus*2 + id)); 1238 } 1239 return result; 1240} 1241