4 * Written by Eryk Vershen
8 * Copyright 1997,1998 by Apple Computer, Inc.
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.
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.
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.
31 // for malloc() & free()
34 // for SCSI command structures
35 #include "MacSCSICommand.h"
36 #include "ATA_media.h"
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
53 typedef struct ATA_info
*ATA_INFO
;
61 typedef struct ATA_media
*ATA_MEDIA
;
80 typedef struct ATA_media_iterator
*ATA_MEDIA_ITERATOR
;
82 struct ATA_media_iterator
{
83 struct media_iterator m
;
89 struct 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 */
124 struct 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 */
155 /* Identifies the bus protocol type. */
170 kATAcmdATAPIPacket
= 0x00A0 /* ATAPI packet command */
177 static long ata_inited
= 0;
178 static struct ATA_manager ata_mgr
;
181 * Forward declarations
183 int ATAManagerPresent(void);
184 int ATAHardwarePresent(void);
185 pascal SInt16
ataManager(ataPB
*pb
);
187 ATA_MEDIA
new_ata_media(void);
188 long read_ata_media(MEDIA m
, long long offset
, unsigned long count
, void *address
);
189 long write_ata_media(MEDIA m
, long long offset
, unsigned long 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
, unsigned long count
, void *address
);
200 long write_atapi_media(MEDIA m
, long long offset
, unsigned long 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
, unsigned long *block_size
, unsigned long *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
);
214 #if GENERATINGPOWERPC
216 ataManager(ataPB
*pb
)
219 #if sizeof(SInt16) > 4
220 #error "Result types larger than 4 bytes are not supported."
225 private_result
= CallUniversalProc(
226 *(UniversalProcPtr
*)TBTrapTableAddress(0xAAF1),
228 | RESULT_SIZE(SIZE_CODE(sizeof(SInt16
)))
229 | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(pb
))),
231 return *(((SInt16
*)&private_result
) + RESULT_OFFSET(SInt16
));
237 ATAHardwarePresent(void)
241 // Hardware configuration flags
242 configFlags
= LMGetHWCfgFlags();
244 return ((configFlags
& 0x0080) != 0);
249 ATAManagerPresent(void)
251 if (ATAHardwarePresent()) {
252 return (TrapAvailable(kATATrap
));
266 if (ata_inited
!= 0) {
271 if (ATAManagerPresent() == 0) {
277 ata_mgr
.kind
= allocate_media_kind();
279 clear_memory((void *)&pb
, sizeof(pb
));
281 pb
.ataPBFunctionCode
= kATAMgrManagerInquiry
;
282 pb
.ataPBVers
= kATAPBVers1
;
284 status
= ataManager((ataPB
*) &pb
);
286 if (status
!= noErr
) {
290 ata_mgr
.version
.major
= pb
.ataMgrVersion
.majorRev
;
291 ata_mgr
.version
.minor
= pb
.ataMgrVersion
.minorAndBugRev
>> 4;
292 ata_mgr
.busCount
= pb
.ataBusCnt
;
294 ata_mgr
.bus_list
= (long *) calloc(ata_mgr
.busCount
, sizeof(long));
295 if (ata_mgr
.bus_list
== 0) {
296 ata_mgr
.busCount
= 0;
298 for (i
= 0, j
= 0; j
< ata_mgr
.busCount
; i
++) {
299 if (ata_bus_present(i
)) {
300 ata_mgr
.bus_list
[j
] = i
;
309 ata_bus_present(int num
)
314 clear_memory((void *)&pb
, sizeof(pb
));
316 pb
.ataPBFunctionCode
= kATAMgrBusInquiry
;
317 pb
.ataPBVers
= kATAPBVers1
;
318 pb
.ataPBDeviceID
= num
;
320 status
= ataManager((ataPB
*) &pb
);
322 if (status
== noErr
) {
325 //printf("status = %d\n", status);
334 return (ATA_MEDIA
) new_media(sizeof(struct ATA_media
));
342 compute_id(long bus
, long device
)
348 for (i
= 0; i
< ata_mgr
.busCount
; i
++) {
349 if (bus
== ata_mgr
.bus_list
[i
]) {
353 if (i
>= ata_mgr
.busCount
) {
355 } else if (ata_mgr
.version
.major
< 3) {
362 if (device
< 0 || device
> 1) {
365 id
= ((device
& 0xFF) << 8) | (bus
& 0xFF);
373 get_info(long id
, struct ATA_identify_drive_info
*ip
)
376 ataDevConfiguration pb2
;
381 if (sizeof(struct ATA_identify_drive_info
) < 512) {
384 clear_memory((void *)ip
, sizeof(struct ATA_identify_drive_info
));
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
;
394 status
= ataManager((ataPB
*) &pb
);
396 if (status
!= noErr
) {
397 //printf("get info status = %d\n", status);
400 ip
->total_sectors
= SWAP_SHORTS(ip
->total_sectors
);
401 ip
->lba_sectors
= SWAP_SHORTS(ip
->lba_sectors
);
411 ataDevConfiguration pb
;
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
;
423 status
= ataManager((ataPB
*) &pb
);
424 if (status
!= noErr
) {
425 //printf("is atatpi status = %d\n", status);
426 } else if (pb
.ataDeviceType
== kDevATAPI
) {
428 /* the drive can be asleep or something in which case this doesn't work */
429 /* how do we do reads */
437 open_ata_as_media(long bus
, long device
)
441 struct ATA_identify_drive_info info
;
445 if (ata_inited
== 0) {
449 if (ata_mgr
.exists
== 0) {
450 //printf("ATA manager does not exist\n");
454 id
= compute_id(bus
, device
);
459 } else if (is_atapi(id
)) {
460 a
= (ATA_MEDIA
) open_atapi_as_media(bus
, device
);
464 if (get_info(id
, &info
) != 0) {
467 a
->m
.kind
= ata_mgr
.kind
;
468 if ((info
.capabilities
& LBA_CAPABLE
) != 0) {
469 total
= info
.lba_sectors
;
474 /* Only CHS - Cylinder Head Sector addressing */
475 total
= info
.total_sectors
;
477 a
->info
.heads
= info
.cur_heads
;
478 a
->info
.sectors
= info
.cur_sec_per_track
;
480 { /* XXX this should be a loop in a subroutine */
482 if (ATA_ReadBlock(id
, &a
->info
, 512, 0, buf
)) {
484 } else if (ATA_ReadBlock(id
, &a
->info
, 1024, 0, buf
)) {
486 } else if (ATA_ReadBlock(id
, &a
->info
, 2048, 0, buf
)) {
489 a
->m
.grain
= 512; /* XXX should really return failure here */
494 a
->m
.size_in_bytes
= ((long long)1000) * a
->m
.grain
; /* XXX not right */
496 a
->m
.size_in_bytes
= ((long long)total
) * a
->m
.grain
;
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
;
505 printf("ATA - couldn't get info\n");
513 read_ata_media(MEDIA m
, long long offset
, unsigned long count
, void *address
)
522 unsigned char *buffer
;
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 */
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
;
544 for (i
= 0; i
< block_count
; i
++) {
545 if (ATA_ReadBlock(a
->id
, &a
->info
, block_size
, block
, buffer
) == 0) {
549 buffer
+= block_size
;
558 write_ata_media(MEDIA m
, long long offset
, unsigned long count
, void *address
)
565 unsigned char *buffer
;
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 */
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
;
587 for (i
= 0; i
< block_count
; i
++) {
588 if (ATA_WriteBlock(a
->id
, &a
->info
, block_size
, block
, buffer
) == 0) {
592 buffer
+= block_size
;
601 close_ata_media(MEDIA m
)
608 } else if (a
->m
.kind
!= ata_mgr
.kind
) {
609 /* XXX need to error here - this is an internal problem */
612 /* XXX nothing to do - I think? */
618 os_reload_ata_media(MEDIA m
)
620 printf("Reboot your system so the partition table will be reread.\n");
626 ATA_ReadBlock(UInt32 deviceID
, ATA_INFO info
, UInt32 block_size
, UInt32 block
, UInt8
*address
)
631 long lba
, cyl
, head
, sector
;
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
;
640 pb
.ataPBLogicalBlockSize
= block_size
;
641 pb
.ataPBBuffer
= address
;
642 pb
.ataPBByteCount
= block_size
;
645 sector
= block
& 0xFF;
646 head
= (block
>> 24) & 0xF;
647 cyl
= (block
>> 8) & 0xFFFF;
650 sector
= (block
% info
->sectors
) + 1;
651 cyl
= block
/ info
->sectors
;
652 head
= cyl
% info
->heads
;
653 cyl
= cyl
/ info
->heads
;
656 pb
.ataPBTaskFile
.ataTFCount
= 1;
657 pb
.ataPBTaskFile
.ataTFSector
= sector
;
658 pb
.ataPBTaskFile
.ataTFCylinder
= cyl
;
659 if (deviceID
& 0x0FF00) {
664 /* std | L/C | Drive | head */
665 pb
.ataPBTaskFile
.ataTFSDH
= 0xA0 | lba
| slave
| head
;
666 pb
.ataPBTaskFile
.ataTFCommand
= kATAcmdRead
;
668 status
= ataManager((ataPB
*) &pb
);
669 if (status
!= noErr
) {
671 //printf(" ATA read status = %d\n", status);
680 ATA_WriteBlock(UInt32 deviceID
, ATA_INFO info
, UInt32 block_size
, UInt32 block
, UInt8
*address
)
685 long lba
, cyl
, head
, sector
;
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
;
694 pb
.ataPBLogicalBlockSize
= block_size
;
695 pb
.ataPBBuffer
= address
;
696 pb
.ataPBByteCount
= block_size
;
699 sector
= block
& 0xFF;
700 head
= (block
>> 24) & 0xF;
701 cyl
= (block
>> 8) & 0xFFFF;
704 sector
= (block
% info
->sectors
) + 1;
705 cyl
= block
/ info
->sectors
;
706 head
= cyl
% info
->heads
;
707 cyl
= cyl
/ info
->heads
;
709 pb
.ataPBTaskFile
.ataTFCount
= 1;
710 pb
.ataPBTaskFile
.ataTFSector
= sector
;
711 pb
.ataPBTaskFile
.ataTFCylinder
= cyl
;
712 if (deviceID
& 0x0FF00) {
717 /* std | L/C | Drive | head */
718 pb
.ataPBTaskFile
.ataTFSDH
= 0xA0 | lba
| slave
| head
;
719 pb
.ataPBTaskFile
.ataTFCommand
= kATAcmdWrite
;
721 status
= ataManager((ataPB
*) &pb
);
722 if (status
!= noErr
) {
738 get_pi_info(long id
, struct ATAPI_identify_drive_info
*ip
)
744 if (sizeof(struct ATAPI_identify_drive_info
) < 512) {
747 clear_memory((void *)ip
, sizeof(struct ATAPI_identify_drive_info
));
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
;
757 status
= ataManager((ataPB
*) &pb
);
759 if (status
!= noErr
) {
760 //printf("get pi info status = %d\n", status);
770 open_atapi_as_media(long bus
, long device
)
774 struct ATAPI_identify_drive_info info
;
776 unsigned long block_size
;
777 unsigned long blocks
;
779 if (ata_inited
== 0) {
783 if (ata_mgr
.exists
== 0) {
787 id
= compute_id(bus
, device
);
794 if (get_pi_info(id
, &info
) != 0
795 && (info
.capabilities
& LBA_CAPABLE
) != 0) {
796 if (ATAPI_TestUnitReady(id
) != 0) {
799 a
->m
.kind
= ata_mgr
.kind
;
800 if (ATAPI_ReadCapacity(id
, &block_size
, &blocks
) == 0) {
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
;
813 printf("ATAPI - unit not ready\n");
816 printf("ATAPI - couldn't get info or not LBA capable\n");
824 read_atapi_media(MEDIA m
, long long offset
, unsigned long count
, void *address
)
833 unsigned char *buffer
;
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 */
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
;
855 for (i
= 0; i
< block_count
; i
++) {
856 if (ATAPI_ReadBlock(a
->id
, block_size
, block
, buffer
) == 0) {
860 buffer
+= block_size
;
869 write_atapi_media(MEDIA m
, long long offset
, unsigned long count
, void *address
)
876 ATAPI_ReadBlock(UInt32 deviceID
, UInt32 block_size
, UInt32 block
, UInt8
*address
)
881 ATAPICmdPacket cmdPacket
;
882 SCSI_10_Byte_Command
*gRead
;
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
;
892 pb
.ataPBBuffer
= address
;
893 pb
.ataPBByteCount
= block_size
;
894 pb
.ataPBTaskFile
.ataTFCylinder
= block_size
;
895 if (deviceID
& 0x0FF00) {
900 /* std | L/C | Drive | head */
901 pb
.ataPBTaskFile
.ataTFSDH
= 0xA0 | 0x40 | slave
;
902 pb
.ataPBTaskFile
.ataTFCommand
= kATAcmdATAPIPacket
;
903 pb
.ataPBPacketPtr
= &cmdPacket
;
905 cmdPacket
.atapiPacketSize
= 16;
906 clear_memory((void *)&cmdPacket
.atapiCommandByte
, 16);
907 gRead
= (SCSI_10_Byte_Command
*) &cmdPacket
.atapiCommandByte
[0];
909 gRead
->opcode
= kScsiCmdRead10
;
911 gRead
->lbn4
= (block
>> 24) & 0xFF;
912 gRead
->lbn3
= (block
>> 16) & 0xFF;
913 gRead
->lbn2
= (block
>> 8) & 0xFF;
914 gRead
->lbn1
= block
& 0xFF;
917 gRead
->len2
= (count
>> 8) & 0xFF;
918 gRead
->len1
= count
& 0xFF;
921 status
= ataManager((ataPB
*) &pb
);
922 if (status
!= noErr
) {
924 //printf("ATAPI read status = %d\n", status);
933 ATAPI_TestUnitReady(UInt32 deviceID
)
938 ATAPICmdPacket cmdPacket
;
939 SCSI_10_Byte_Command
*gTestUnit
;
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
;
948 if (deviceID
& 0x0FF00) {
953 /* std | L/C | Drive | head */
954 pb
.ataPBTaskFile
.ataTFSDH
= 0xA0 | 0x40 | slave
;
955 pb
.ataPBTaskFile
.ataTFCommand
= kATAcmdATAPIPacket
;
956 pb
.ataPBPacketPtr
= &cmdPacket
;
958 cmdPacket
.atapiPacketSize
= 16;
959 clear_memory((void *)&cmdPacket
.atapiCommandByte
, 16);
960 gTestUnit
= (SCSI_10_Byte_Command
*) &cmdPacket
.atapiCommandByte
[0];
962 gTestUnit
->opcode
= kScsiCmdTestUnitReady
;
965 status
= ataManager((ataPB
*) &pb
);
966 if (status
!= noErr
) {
968 //printf("ATAPI test unit ready status = %d\n", status);
977 ATAPI_ReadCapacity(UInt32 deviceID
, unsigned long *block_size
, unsigned long *blocks
)
982 ATAPICmdPacket cmdPacket
;
983 SCSI_10_Byte_Command
*gReadCap
;
984 struct read_cap_data
{
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
;
996 pb
.ataPBBuffer
= (unsigned char *)&rcd
;
997 pb
.ataPBByteCount
= 8;
998 pb
.ataPBTaskFile
.ataTFCylinder
= 8;
999 if (deviceID
& 0x0FF00) {
1004 /* std | L/C | Drive | head */
1005 pb
.ataPBTaskFile
.ataTFSDH
= 0xA0 | 0x40 | slave
;
1006 pb
.ataPBTaskFile
.ataTFCommand
= kATAcmdATAPIPacket
;
1007 pb
.ataPBPacketPtr
= &cmdPacket
;
1009 cmdPacket
.atapiPacketSize
= 16;
1010 clear_memory((void *)&cmdPacket
.atapiCommandByte
, 16);
1011 gReadCap
= (SCSI_10_Byte_Command
*) &cmdPacket
.atapiCommandByte
[0];
1013 gReadCap
->opcode
= kScsiCmdReadCapacity
;
1016 status
= ataManager((ataPB
*) &pb
);
1017 if (status
!= noErr
) {
1019 //printf("ATAPI read capacity status = %d\n", status);
1023 *block_size
= rcd
.size
;
1030 ATA_FindDevice(long dRefNum
)
1035 if (ATAManagerPresent()) {
1036 clear_memory((void *)&pb
, sizeof(pb
));
1038 pb
.ataPBFunctionCode
= kATAMgrFindDriverRefnum
;
1039 pb
.ataPBVers
= kATAPBVers1
;
1040 pb
.ataPBDeviceID
= 0xFFFF;
1041 pb
.ataPBTimeOut
= kATAtimeout
;
1043 pb
.ataDeviceNextID
= 1;
1045 status
= ataManager((ataPB
*) &pb
);
1047 if (status
!= noErr
) {
1049 } else if (pb
.ataDrvrRefNum
== dRefNum
1050 && pb
.ataPBDeviceID
!= kNoDevice
) {
1051 return open_ata_as_media(pb
.ataPBDeviceID
& 0xFF,
1052 (pb
.ataPBDeviceID
>> 8) & 0xFF);
1054 pb
.ataPBDeviceID
= pb
.ataDeviceNextID
;
1056 } while (pb
.ataPBDeviceID
!= kNoDevice
);
1066 new_ata_iterator(void)
1068 return (ATA_MEDIA_ITERATOR
) new_media_iterator(sizeof(struct ATA_media_iterator
));
1073 create_ata_iterator(void)
1075 ATA_MEDIA_ITERATOR a
;
1077 if (ata_inited
== 0) {
1081 if (ata_mgr
.exists
== 0) {
1085 a
= new_ata_iterator();
1087 a
->m
.kind
= ata_mgr
.kind
;
1089 a
->m
.do_reset
= reset_ata_iterator
;
1090 a
->m
.do_step
= step_ata_iterator
;
1091 a
->m
.do_delete
= delete_ata_iterator
;
1097 return (MEDIA_ITERATOR
) a
;
1102 reset_ata_iterator(MEDIA_ITERATOR m
)
1104 ATA_MEDIA_ITERATOR a
;
1106 a
= (ATA_MEDIA_ITERATOR
) m
;
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
;
1118 step_ata_iterator(MEDIA_ITERATOR m
)
1120 ATA_MEDIA_ITERATOR a
;
1123 a
= (ATA_MEDIA_ITERATOR
) m
;
1126 } else if (a
->m
.kind
!= ata_mgr
.kind
) {
1127 /* wrong kind - XXX need to error here - this is an internal problem */
1129 switch (a
->m
.state
) {
1131 /* find # of buses (done in ata_init) */
1132 a
->m
.state
= kReset
;
1133 /* fall through to reset */
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 */
1142 if (a
->bus_index
>= ata_mgr
.busCount
/* max bus id */) {
1145 if (a
->id
> 1 /*max id for bus */) {
1147 a
->bus
= ata_mgr
.bus_list
[a
->bus_index
];
1148 a
->id
= 0 /* low device id */;
1149 continue; /* try again */
1152 // insure that name creation works
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
);
1162 a
->id
+= 1; /* next id */
1166 /* fall through to end */
1172 return 0 /* no entry */;
1177 delete_ata_iterator(MEDIA_ITERATOR m
)
1188 open_linux_ata_as_media(long index
)
1195 if (i
>= ata_mgr
.busCount
) {
1200 bus
= ata_mgr
.bus_list
[index
/ 2];
1204 return open_ata_as_media(bus
, id
);
1210 open_linux_ata_as_media(long index
)
1218 return open_ata_as_media(bus
, id
);
1224 linux_ata_name(long bus
, long id
)
1229 // a bus >= 13 would be a bogus character
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) ...
1237 snprintf(result
, 20, "/dev/hd%c", 'a' + (bus
*2 + id
));