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