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 */
53 typedef struct ATA_info *ATA_INFO;
54
55 struct ATA_info {
56 long lba;
57 long heads;
58 long sectors;
59 };
60
61 typedef struct ATA_media *ATA_MEDIA;
62
63 struct ATA_media {
64 struct media m;
65 long id;
66 struct ATA_info info;
67 };
68
69 struct 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
80 typedef struct ATA_media_iterator *ATA_MEDIA_ITERATOR;
81
82 struct ATA_media_iterator {
83 struct media_iterator m;
84 long bus_index;
85 long bus;
86 long id;
87 };
88
89 struct ATA_identify_drive_info { /* word */
90 uint16_t config_bits; /* 0 */
91 uint16_t num_cylinders; /* 1 */
92 uint16_t reserved2; /* 2 */
93 uint16_t num_heads; /* 3 */
94 uint16_t bytes_per_track; /* 4 */
95 uint16_t bytes_per_sector; /* 5 */
96 uint16_t sectors_per_track; /* 6 */
97 uint16_t vendor7[3]; /* 7-9 */
98 char serial_number[20]; /* 10-19 */
99 uint16_t buffer_type; /* 20 */
100 uint16_t buffer_size; /* 21 */
101 uint16_t num_of_ecc_bytes; /* 22 */
102 char firmware_rev[8]; /* 23-26 */
103 char model_number[40]; /* 27-46 */
104 uint16_t word47; /* 47 */
105 uint16_t double_word_io; /* 48 */
106 uint16_t capabilities; /* 49 */
107 uint16_t reserved50; /* 50 */
108 uint16_t pio_timing; /* 51 */
109 uint16_t dma_timing; /* 52 */
110 uint16_t current_is_valid; /* 53 */
111 uint16_t cur_cylinders; /* 54 */
112 uint16_t cur_heads; /* 55 */
113 uint16_t cur_sec_per_track; /* 56 */
114 uint32_t total_sectors; /* 57-58 */
115 uint16_t multiple_sectors; /* 59 */
116 uint32_t lba_sectors; /* 60-61 */
117 uint16_t singleword_dma; /* 62 */
118 uint16_t multiword_dma; /* 63 */
119 uint16_t reserved64[64]; /* 64-127 */
120 uint16_t vendor128[32]; /* 128-159 */
121 uint16_t reserved160[96]; /* 160-255 */
122 };
123
124 struct ATAPI_identify_drive_info { /* word */
125 uint16_t config_bits; /* 0 */
126 uint16_t retired1[9]; /* 1-9 */
127 char serial_number[20]; /* 10-19 */
128 uint16_t retired20[3]; /* 20-22 */
129 char firmware_rev[8]; /* 23-26 */
130 char model_number[40]; /* 27-46 */
131 uint16_t retired47[2]; /* 47-48 */
132 uint16_t capabilities; /* 49 */
133 uint16_t reserved50; /* 50 */
134 uint16_t pio_timing; /* 51 */
135 uint16_t dma_timing; /* 52 */
136 uint16_t current_is_valid; /* 53 */
137 uint16_t retired54[8]; /* 54-61 */
138 uint16_t singleword_dma; /* 62 */
139 uint16_t multiword_dma; /* 63 */
140 uint16_t pio_transfer; /* 64 */
141 uint16_t min_cycle_time; /* 65 */
142 uint16_t rec_cycle_time; /* 66 */
143 uint16_t min_wo_flow; /* 67 */
144 uint16_t min_with_flow; /* 68 */
145 uint16_t reserved69[2]; /* 69-70 */
146 uint16_t release_over; /* 71 */
147 uint16_t release_service; /* 72 */
148 uint16_t major_rev; /* 73 */
149 uint16_t minor_rev; /* 74 */
150 uint16_t reserved75[53]; /* 75-127 */
151 uint16_t vendor128[32]; /* 128-159 */
152 uint16_t reserved160[96]; /* 160-255 */
153 };
154
155 /* Identifies the bus protocol type. */
156 enum {
157 kDevUnknown = 0,
158 kDevATA = 1,
159 kDevATAPI = 2,
160 kDevPCMCIA = 3
161 };
162
163
164 /*
165 * Global Constants
166 */
167 enum {
168 kNoDevice = 0x00FF,
169 kATAtimeout = 3000,
170 kATAcmdATAPIPacket = 0x00A0 /* ATAPI packet command */
171 };
172
173
174 /*
175 * Global Variables
176 */
177 static long ata_inited = 0;
178 static struct ATA_manager ata_mgr;
179
180 /*
181 * Forward declarations
182 */
183 int ATAManagerPresent(void);
184 int ATAHardwarePresent(void);
185 pascal SInt16 ataManager(ataPB *pb);
186 void ata_init(void);
187 ATA_MEDIA new_ata_media(void);
188 long read_ata_media(MEDIA m, long long offset, uint32_t count, void *address);
189 long write_ata_media(MEDIA m, long long offset, uint32_t count, void *address);
190 long close_ata_media(MEDIA m);
191 long os_reload_ata_media(MEDIA m);
192 long compute_id(long bus, long device);
193 pascal SInt16 ataManager(ataPB *pb);
194 int ATA_ReadBlock(UInt32 deviceID, ATA_INFO info, UInt32 block_size, UInt32 block, UInt8 *address);
195 int ATA_WriteBlock(UInt32 deviceID, ATA_INFO info, UInt32 block_size, UInt32 block, UInt8 *address);
196 long get_info(long id, struct ATA_identify_drive_info *ip);
197 long get_pi_info(long id, struct ATAPI_identify_drive_info *ip);
198 long is_atapi(long id);
199 long read_atapi_media(MEDIA m, long long offset, uint32_t count, void *address);
200 long write_atapi_media(MEDIA m, long long offset, uint32_t count, void *address);
201 int ATAPI_ReadBlock(UInt32 deviceID, UInt32 block_size, UInt32 block, UInt8 *address);
202 int ATAPI_TestUnitReady(UInt32 deviceID);
203 int ATAPI_ReadCapacity(UInt32 deviceID, uint32_t *block_size, uint32_t *blocks);
204 ATA_MEDIA_ITERATOR new_ata_iterator(void);
205 void reset_ata_iterator(MEDIA_ITERATOR m);
206 char *step_ata_iterator(MEDIA_ITERATOR m);
207 void delete_ata_iterator(MEDIA_ITERATOR m);
208 int ata_bus_present(int num);
209
210
211 /*
212 * Routines
213 */
214 #if GENERATINGPOWERPC
215 pascal SInt16
ataManager(ataPB * pb)216 ataManager(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
236 int
ATAHardwarePresent(void)237 ATAHardwarePresent(void)
238 {
239 UInt16 configFlags;
240
241 // Hardware configuration flags
242 configFlags = LMGetHWCfgFlags();
243
244 return ((configFlags & 0x0080) != 0);
245 }
246
247
248 int
ATAManagerPresent(void)249 ATAManagerPresent(void)
250 {
251 if (ATAHardwarePresent()) {
252 return (TrapAvailable(kATATrap));
253 } else {
254 return 0;
255 }
256 }
257
258 void
ata_init(void)259 ata_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
308 int
ata_bus_present(int num)309 ata_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
331 ATA_MEDIA
new_ata_media(void)332 new_ata_media(void)
333 {
334 return (ATA_MEDIA) new_media(sizeof(struct ATA_media));
335 }
336
337
338 #pragma mark -
339
340
341 long
compute_id(long bus,long device)342 compute_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
372 static long
get_info(long id,struct ATA_identify_drive_info * ip)373 get_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
408 static long
is_atapi(long id)409 is_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
436 MEDIA
open_ata_as_media(long bus,long device)437 open_ata_as_media(long bus, long device)
438 {
439 ATA_MEDIA a;
440 long id;
441 struct ATA_identify_drive_info info;
442 uint8_t *buf;
443 uint32_t 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
512 long
read_ata_media(MEDIA m,long long offset,uint32_t count,void * address)513 read_ata_media(MEDIA m, long long offset, uint32_t 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 uint8_t *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
557 long
write_ata_media(MEDIA m,long long offset,uint32_t count,void * address)558 write_ata_media(MEDIA m, long long offset, uint32_t count, void *address)
559 {
560 ATA_MEDIA a;
561 long rtn_value;
562 long block;
563 long block_count;
564 long block_size;
565 uint8_t *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
600 long
close_ata_media(MEDIA m)601 close_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
617 long
os_reload_ata_media(MEDIA m)618 os_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
625 int
ATA_ReadBlock(UInt32 deviceID,ATA_INFO info,UInt32 block_size,UInt32 block,UInt8 * address)626 ATA_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
679 int
ATA_WriteBlock(UInt32 deviceID,ATA_INFO info,UInt32 block_size,UInt32 block,UInt8 * address)680 ATA_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 */
737 static long
get_pi_info(long id,struct ATAPI_identify_drive_info * ip)738 get_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
769 MEDIA
open_atapi_as_media(long bus,long device)770 open_atapi_as_media(long bus, long device)
771 {
772 ATA_MEDIA a;
773 long id;
774 struct ATAPI_identify_drive_info info;
775 uint8_t *buf;
776 uint32_t block_size;
777 uint32_t 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
823 long
read_atapi_media(MEDIA m,long long offset,uint32_t count,void * address)824 read_atapi_media(MEDIA m, long long offset, uint32_t 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 uint8_t *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
868 long
write_atapi_media(MEDIA m,long long offset,uint32_t count,void * address)869 write_atapi_media(MEDIA m, long long offset, uint32_t count, void *address)
870 {
871 return 0;
872 }
873
874
875 int
ATAPI_ReadBlock(UInt32 deviceID,UInt32 block_size,UInt32 block,UInt8 * address)876 ATAPI_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
932 int
ATAPI_TestUnitReady(UInt32 deviceID)933 ATAPI_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
976 int
ATAPI_ReadCapacity(UInt32 deviceID,uint32_t * block_size,uint32_t * blocks)977 ATAPI_ReadCapacity(UInt32 deviceID, uint32_t *block_size, uint32_t *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 = (uint8_t *)&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
1029 MEDIA
ATA_FindDevice(long dRefNum)1030 ATA_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
1065 ATA_MEDIA_ITERATOR
new_ata_iterator(void)1066 new_ata_iterator(void)
1067 {
1068 return (ATA_MEDIA_ITERATOR) new_media_iterator(sizeof(struct ATA_media_iterator));
1069 }
1070
1071
1072 MEDIA_ITERATOR
create_ata_iterator(void)1073 create_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
1101 void
reset_ata_iterator(MEDIA_ITERATOR m)1102 reset_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
1117 char *
step_ata_iterator(MEDIA_ITERATOR m)1118 step_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
1176 void
delete_ata_iterator(MEDIA_ITERATOR m)1177 delete_ata_iterator(MEDIA_ITERATOR m)
1178 {
1179 return;
1180 }
1181
1182
1183 #pragma mark -
1184
1185
1186 #ifdef notdef
1187 MEDIA
open_linux_ata_as_media(long index)1188 open_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
1209 MEDIA
open_linux_ata_as_media(long index)1210 open_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
1223 char *
linux_ata_name(long bus,long id)1224 linux_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