#include <stdio.h>
#include <stdlib.h>
#include <ATA.h>
#include "MacSCSICommand.h"
#include "ATA_media.h"
#include "util.h"
#define RESULT_OFFSET(type) \
((sizeof(type) == 1) ? 3 : ((sizeof(type) == 2) ? 1 : 0))
#define TBTrapTableAddress(trapNum) (((trapNum & 0x03FF) << 2) + 0xE00)
#define SWAP_SHORTS(x) ((((x) & 0xFFFF) << 16) | (((x) >> 16) & 0xFFFF))
#define LBA_CAPABLE 0x0200
typedef struct ATA_info *ATA_INFO;
struct ATA_info {
long lba;
long heads;
long sectors;
};
typedef struct ATA_media *ATA_MEDIA;
struct ATA_media {
struct media m;
long id;
struct ATA_info info;
};
struct ATA_manager {
long exists;
long kind;
struct {
char major;
char minor;
} version;
short busCount;
long *bus_list;
};
typedef struct ATA_media_iterator *ATA_MEDIA_ITERATOR;
struct ATA_media_iterator {
struct media_iterator m;
long bus_index;
long bus;
long id;
};
struct ATA_identify_drive_info {
unsigned short config_bits;
unsigned short num_cylinders;
unsigned short reserved2;
unsigned short num_heads;
unsigned short bytes_per_track;
unsigned short bytes_per_sector;
unsigned short sectors_per_track;
unsigned short vendor7[3];
char serial_number[20];
unsigned short buffer_type;
unsigned short buffer_size;
unsigned short num_of_ecc_bytes;
char firmware_rev[8];
char model_number[40];
unsigned short word47;
unsigned short double_word_io;
unsigned short capabilities;
unsigned short reserved50;
unsigned short pio_timing;
unsigned short dma_timing;
unsigned short current_is_valid;
unsigned short cur_cylinders;
unsigned short cur_heads;
unsigned short cur_sec_per_track;
unsigned long total_sectors;
unsigned short multiple_sectors;
unsigned long lba_sectors;
unsigned short singleword_dma;
unsigned short multiword_dma;
unsigned short reserved64[64];
unsigned short vendor128[32];
unsigned short reserved160[96];
};
struct ATAPI_identify_drive_info {
unsigned short config_bits;
unsigned short retired1[9];
char serial_number[20];
unsigned short retired20[3];
char firmware_rev[8];
char model_number[40];
unsigned short retired47[2];
unsigned short capabilities;
unsigned short reserved50;
unsigned short pio_timing;
unsigned short dma_timing;
unsigned short current_is_valid;
unsigned short retired54[8];
unsigned short singleword_dma;
unsigned short multiword_dma;
unsigned short pio_transfer;
unsigned short min_cycle_time;
unsigned short rec_cycle_time;
unsigned short min_wo_flow;
unsigned short min_with_flow;
unsigned short reserved69[2];
unsigned short release_over;
unsigned short release_service;
unsigned short major_rev;
unsigned short minor_rev;
unsigned short reserved75[53];
unsigned short vendor128[32];
unsigned short reserved160[96];
};
enum {
kDevUnknown = 0,
kDevATA = 1,
kDevATAPI = 2,
kDevPCMCIA = 3
};
enum {
kNoDevice = 0x00FF,
kATAtimeout = 3000,
kATAcmdATAPIPacket = 0x00A0
};
static long ata_inited = 0;
static struct ATA_manager ata_mgr;
int ATAManagerPresent(void);
int ATAHardwarePresent(void);
pascal SInt16 ataManager(ataPB *pb);
void ata_init(void);
ATA_MEDIA new_ata_media(void);
long read_ata_media(MEDIA m, long long offset, unsigned long count, void *address);
long write_ata_media(MEDIA m, long long offset, unsigned long count, void *address);
long close_ata_media(MEDIA m);
long os_reload_ata_media(MEDIA m);
long compute_id(long bus, long device);
pascal SInt16 ataManager(ataPB *pb);
int ATA_ReadBlock(UInt32 deviceID, ATA_INFO info, UInt32 block_size, UInt32 block, UInt8 *address);
int ATA_WriteBlock(UInt32 deviceID, ATA_INFO info, UInt32 block_size, UInt32 block, UInt8 *address);
long get_info(long id, struct ATA_identify_drive_info *ip);
long get_pi_info(long id, struct ATAPI_identify_drive_info *ip);
long is_atapi(long id);
long read_atapi_media(MEDIA m, long long offset, unsigned long count, void *address);
long write_atapi_media(MEDIA m, long long offset, unsigned long count, void *address);
int ATAPI_ReadBlock(UInt32 deviceID, UInt32 block_size, UInt32 block, UInt8 *address);
int ATAPI_TestUnitReady(UInt32 deviceID);
int ATAPI_ReadCapacity(UInt32 deviceID, unsigned long *block_size, unsigned long *blocks);
ATA_MEDIA_ITERATOR new_ata_iterator(void);
void reset_ata_iterator(MEDIA_ITERATOR m);
char *step_ata_iterator(MEDIA_ITERATOR m);
void delete_ata_iterator(MEDIA_ITERATOR m);
int ata_bus_present(int num);
#if GENERATINGPOWERPC
pascal SInt16
ataManager(ataPB *pb)
{
#ifdef applec
#if sizeof(SInt16) > 4
#error "Result types larger than 4 bytes are not supported."
#endif
#endif
long private_result;
private_result = CallUniversalProc(
*(UniversalProcPtr*)TBTrapTableAddress(0xAAF1),
kPascalStackBased
| RESULT_SIZE(SIZE_CODE(sizeof(SInt16)))
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(pb))),
pb);
return *(((SInt16*)&private_result) + RESULT_OFFSET(SInt16));
}
#endif
int
ATAHardwarePresent(void)
{
UInt16 configFlags;
configFlags = LMGetHWCfgFlags();
return ((configFlags & 0x0080) != 0);
}
int
ATAManagerPresent(void)
{
if (ATAHardwarePresent()) {
return (TrapAvailable(kATATrap));
} else {
return 0;
}
}
void
ata_init(void)
{
ataMgrInquiry pb;
OSErr status;
int i;
int j;
if (ata_inited != 0) {
return;
}
ata_inited = 1;
if (ATAManagerPresent() == 0) {
ata_mgr.exists = 0;
return;
}
ata_mgr.exists = 1;
ata_mgr.kind = allocate_media_kind();
clear_memory((void *)&pb, sizeof(pb));
pb.ataPBFunctionCode = kATAMgrManagerInquiry;
pb.ataPBVers = kATAPBVers1;
status = ataManager((ataPB*) &pb );
if (status != noErr) {
ata_mgr.exists = 0;
return;
}
ata_mgr.version.major = pb.ataMgrVersion.majorRev;
ata_mgr.version.minor = pb.ataMgrVersion.minorAndBugRev >> 4;
ata_mgr.busCount = pb.ataBusCnt;
ata_mgr.bus_list = (long *) calloc(ata_mgr.busCount, sizeof(long));
if (ata_mgr.bus_list == 0) {
ata_mgr.busCount = 0;
} else {
for (i = 0, j = 0; j < ata_mgr.busCount; i++) {
if (ata_bus_present(i)) {
ata_mgr.bus_list[j] = i;
j++;
}
}
}
}
int
ata_bus_present(int num)
{
ataBusInquiry pb;
OSErr status;
clear_memory((void *)&pb, sizeof(pb));
pb.ataPBFunctionCode = kATAMgrBusInquiry;
pb.ataPBVers = kATAPBVers1;
pb.ataPBDeviceID = num;
status = ataManager((ataPB*) &pb );
if (status == noErr) {
return 1;
} else {
return 0;
}
}
ATA_MEDIA
new_ata_media(void)
{
return (ATA_MEDIA) new_media(sizeof(struct ATA_media));
}
#pragma mark -
long
compute_id(long bus, long device)
{
long id;
int i;
id = -1;
for (i = 0; i < ata_mgr.busCount; i++) {
if (bus == ata_mgr.bus_list[i]) {
break;
}
}
if (i >= ata_mgr.busCount) {
} else if (ata_mgr.version.major < 3) {
if (device != 0) {
} else {
id = bus & 0xFF;
}
} else {
if (device < 0 || device > 1) {
} else {
id = ((device & 0xFF) << 8) | (bus & 0xFF);
}
}
return id;
}
static long
get_info(long id, struct ATA_identify_drive_info *ip)
{
ataIdentify pb;
ataDevConfiguration pb2;
OSErr status;
long rtn_value;
long atapi;
if (sizeof(struct ATA_identify_drive_info) < 512) {
return 0;
}
clear_memory((void *)ip, sizeof(struct ATA_identify_drive_info));
clear_memory((void *)&pb, sizeof(pb));
pb.ataPBFunctionCode = kATAMgrDriveIdentify;
pb.ataPBVers = kATAPBVers1;
pb.ataPBDeviceID = id;
pb.ataPBFlags = mATAFlagIORead | mATAFlagByteSwap;
pb.ataPBTimeOut = kATAtimeout;
pb.ataPBBuffer = (void*) ip;
status = ataManager((ataPB*) &pb );
if (status != noErr) {
rtn_value = 0;
} else {
ip->total_sectors = SWAP_SHORTS(ip->total_sectors);
ip->lba_sectors = SWAP_SHORTS(ip->lba_sectors);
rtn_value = 1;
}
return rtn_value;
}
static long
is_atapi(long id)
{
ataDevConfiguration pb;
OSErr status;
long atapi;
atapi = 0;
if (ata_mgr.version.major >= 2) {
clear_memory((void *)&pb, sizeof(pb));
pb.ataPBFunctionCode = kATAMgrGetDrvConfiguration;
pb.ataPBVers = kATAPBVers2;
pb.ataPBDeviceID = id;
pb.ataPBTimeOut = kATAtimeout;
status = ataManager((ataPB*) &pb );
if (status != noErr) {
} else if (pb.ataDeviceType == kDevATAPI) {
atapi = 1;
}
}
return atapi;
}
MEDIA
open_ata_as_media(long bus, long device)
{
ATA_MEDIA a;
long id;
struct ATA_identify_drive_info info;
unsigned char *buf;
unsigned long total;
if (ata_inited == 0) {
ata_init();
}
if (ata_mgr.exists == 0) {
return 0;
}
id = compute_id(bus, device);
if (id < 0) {
return 0;
} else if (is_atapi(id)) {
a = (ATA_MEDIA) open_atapi_as_media(bus, device);
} else {
a = 0;
if (get_info(id, &info) != 0) {
a = new_ata_media();
if (a != 0) {
a->m.kind = ata_mgr.kind;
if ((info.capabilities & LBA_CAPABLE) != 0) {
total = info.lba_sectors;
a->info.lba = 1;
a->info.heads = 0;
a->info.sectors = 0;
} else {
total = info.total_sectors;
a->info.lba = 0;
a->info.heads = info.cur_heads;
a->info.sectors = info.cur_sec_per_track;
}
{
buf = malloc(2048);
if (ATA_ReadBlock(id, &a->info, 512, 0, buf)) {
a->m.grain = 512;
} else if (ATA_ReadBlock(id, &a->info, 1024, 0, buf)) {
a->m.grain = 1024;
} else if (ATA_ReadBlock(id, &a->info, 2048, 0, buf)) {
a->m.grain = 2048;
} else {
a->m.grain = 512;
}
free(buf);
}
if (total == 0) {
a->m.size_in_bytes = ((long long)1000) * a->m.grain;
} else {
a->m.size_in_bytes = ((long long)total) * a->m.grain;
}
a->m.do_read = read_ata_media;
a->m.do_write = write_ata_media;
a->m.do_close = close_ata_media;
a->m.do_os_reload = os_reload_ata_media;
a->id = id;
}
} else {
printf("ATA - couldn't get info\n");
}
}
return (MEDIA) a;
}
long
read_ata_media(MEDIA m, long long offset, unsigned long count, void *address)
{
ATA_MEDIA a;
ataIOPB pb;
OSErr status;
long rtn_value;
long block;
long block_count;
long block_size;
unsigned char *buffer;
int i;
a = (ATA_MEDIA) m;
rtn_value = 0;
if (a == 0) {
} else if (a->m.kind != ata_mgr.kind) {
} else if (count <= 0 || count % a->m.grain != 0) {
} else if (offset < 0 || offset % a->m.grain != 0) {
} else if (offset + count > a->m.size_in_bytes) {
} else {
block_size = a->m.grain;
block = offset / block_size;
block_count = count / block_size;
buffer = address;
rtn_value = 1;
for (i = 0; i < block_count; i++) {
if (ATA_ReadBlock(a->id, &a->info, block_size, block, buffer) == 0) {
rtn_value = 0;
break;
}
buffer += block_size;
block += 1;
}
}
return rtn_value;
}
long
write_ata_media(MEDIA m, long long offset, unsigned long count, void *address)
{
ATA_MEDIA a;
long rtn_value;
long block;
long block_count;
long block_size;
unsigned char *buffer;
int i;
a = (ATA_MEDIA) m;
rtn_value = 0;
if (a == 0) {
} else if (a->m.kind != ata_mgr.kind) {
} else if (count <= 0 || count % a->m.grain != 0) {
} else if (offset < 0 || offset % a->m.grain != 0) {
} else if (offset + count > a->m.size_in_bytes) {
} else {
block_size = a->m.grain;
block = offset / block_size;
block_count = count / block_size;
buffer = address;
rtn_value = 1;
for (i = 0; i < block_count; i++) {
if (ATA_WriteBlock(a->id, &a->info, block_size, block, buffer) == 0) {
rtn_value = 0;
break;
}
buffer += block_size;
block += 1;
}
}
return rtn_value;
}
long
close_ata_media(MEDIA m)
{
ATA_MEDIA a;
a = (ATA_MEDIA) m;
if (a == 0) {
return 0;
} else if (a->m.kind != ata_mgr.kind) {
return 0;
}
return 1;
}
long
os_reload_ata_media(MEDIA m)
{
printf("Reboot your system so the partition table will be reread.\n");
return 1;
}
int
ATA_ReadBlock(UInt32 deviceID, ATA_INFO info, UInt32 block_size, UInt32 block, UInt8 *address)
{
ataIOPB pb;
OSErr status;
long slave;
long lba, cyl, head, sector;
clear_memory((void *)&pb, sizeof(pb));
pb.ataPBFunctionCode = kATAMgrExecIO;
pb.ataPBVers = kATAPBVers1;
pb.ataPBDeviceID = deviceID;
pb.ataPBFlags = mATAFlagTFRead | mATAFlagIORead ;
pb.ataPBTimeOut = kATAtimeout;
pb.ataPBLogicalBlockSize = block_size;
pb.ataPBBuffer = address;
pb.ataPBByteCount = block_size;
if (info->lba) {
lba = 0x40;
sector = block & 0xFF;
head = (block >> 24) & 0xF;
cyl = (block >> 8) & 0xFFFF;
} else {
lba = 0x00;
sector = (block % info->sectors) + 1;
cyl = block / info->sectors;
head = cyl % info->heads;
cyl = cyl / info->heads;
}
pb.ataPBTaskFile.ataTFCount = 1;
pb.ataPBTaskFile.ataTFSector = sector;
pb.ataPBTaskFile.ataTFCylinder = cyl;
if (deviceID & 0x0FF00) {
slave = 0x10;
} else {
slave = 0x0;
}
pb.ataPBTaskFile.ataTFSDH = 0xA0 | lba | slave | head;
pb.ataPBTaskFile.ataTFCommand = kATAcmdRead;
status = ataManager((ataPB*) &pb );
if (status != noErr) {
return 0;
} else {
return 1;
}
}
int
ATA_WriteBlock(UInt32 deviceID, ATA_INFO info, UInt32 block_size, UInt32 block, UInt8 *address)
{
ataIOPB pb;
OSErr status;
long slave;
long lba, cyl, head, sector;
clear_memory((void *)&pb, sizeof(pb));
pb.ataPBFunctionCode = kATAMgrExecIO;
pb.ataPBVers = kATAPBVers1;
pb.ataPBDeviceID = deviceID;
pb.ataPBFlags = mATAFlagTFRead | mATAFlagIOWrite ;
pb.ataPBTimeOut = kATAtimeout;
pb.ataPBLogicalBlockSize = block_size;
pb.ataPBBuffer = address;
pb.ataPBByteCount = block_size;
if (info->lba) {
lba = 0x40;
sector = block & 0xFF;
head = (block >> 24) & 0xF;
cyl = (block >> 8) & 0xFFFF;
} else {
lba = 0x00;
sector = (block % info->sectors) + 1;
cyl = block / info->sectors;
head = cyl % info->heads;
cyl = cyl / info->heads;
}
pb.ataPBTaskFile.ataTFCount = 1;
pb.ataPBTaskFile.ataTFSector = sector;
pb.ataPBTaskFile.ataTFCylinder = cyl;
if (deviceID & 0x0FF00) {
slave = 0x10;
} else {
slave = 0x0;
}
pb.ataPBTaskFile.ataTFSDH = 0xA0 | lba | slave | head;
pb.ataPBTaskFile.ataTFCommand = kATAcmdWrite;
status = ataManager((ataPB*) &pb );
if (status != noErr) {
return 0;
} else {
return 1;
}
}
#pragma mark -
static long
get_pi_info(long id, struct ATAPI_identify_drive_info *ip)
{
ataIdentify pb;
OSErr status;
long rtn_value;
if (sizeof(struct ATAPI_identify_drive_info) < 512) {
return 0;
}
clear_memory((void *)ip, sizeof(struct ATAPI_identify_drive_info));
clear_memory((void *)&pb, sizeof(pb));
pb.ataPBFunctionCode = kATAMgrDriveIdentify;
pb.ataPBVers = kATAPBVers1;
pb.ataPBDeviceID = id;
pb.ataPBFlags = mATAFlagIORead | mATAFlagByteSwap | mATAFlagProtocol1;
pb.ataPBTimeOut = kATAtimeout;
pb.ataPBBuffer = (void*) ip;
status = ataManager((ataPB*) &pb );
if (status != noErr) {
rtn_value = 0;
} else {
rtn_value = 1;
}
return rtn_value;
}
MEDIA
open_atapi_as_media(long bus, long device)
{
ATA_MEDIA a;
long id;
struct ATAPI_identify_drive_info info;
unsigned char *buf;
unsigned long block_size;
unsigned long blocks;
if (ata_inited == 0) {
ata_init();
}
if (ata_mgr.exists == 0) {
return 0;
}
id = compute_id(bus, device);
if (!is_atapi(id)) {
a = 0;
} else {
a = 0;
if (get_pi_info(id, &info) != 0
&& (info.capabilities & LBA_CAPABLE) != 0) {
if (ATAPI_TestUnitReady(id) != 0) {
a = new_ata_media();
if (a != 0) {
a->m.kind = ata_mgr.kind;
if (ATAPI_ReadCapacity(id, &block_size, &blocks) == 0) {
block_size = 2048;
blocks = 1000;
}
a->m.grain = block_size;
a->m.size_in_bytes = ((long long)blocks) * a->m.grain;
a->m.do_read = read_atapi_media;
a->m.do_write = write_atapi_media;
a->m.do_close = close_ata_media;
a->m.do_os_reload = os_reload_ata_media;
a->id = id;
}
} else {
printf("ATAPI - unit not ready\n");
}
} else {
printf("ATAPI - couldn't get info or not LBA capable\n");
}
}
return (MEDIA) a;
}
long
read_atapi_media(MEDIA m, long long offset, unsigned long count, void *address)
{
ATA_MEDIA a;
ataIOPB pb;
OSErr status;
long rtn_value;
long block;
long block_count;
long block_size;
unsigned char *buffer;
int i;
a = (ATA_MEDIA) m;
rtn_value = 0;
if (a == 0) {
} else if (a->m.kind != ata_mgr.kind) {
} else if (count <= 0 || count % a->m.grain != 0) {
} else if (offset < 0 || offset % a->m.grain != 0) {
} else if (offset + count > a->m.size_in_bytes) {
} else {
block_size = a->m.grain;
block = offset / block_size;
block_count = count / block_size;
buffer = address;
rtn_value = 1;
for (i = 0; i < block_count; i++) {
if (ATAPI_ReadBlock(a->id, block_size, block, buffer) == 0) {
rtn_value = 0;
break;
}
buffer += block_size;
block += 1;
}
}
return rtn_value;
}
long
write_atapi_media(MEDIA m, long long offset, unsigned long count, void *address)
{
return 0;
}
int
ATAPI_ReadBlock(UInt32 deviceID, UInt32 block_size, UInt32 block, UInt8 *address)
{
ataIOPB pb;
OSErr status;
long slave;
ATAPICmdPacket cmdPacket;
SCSI_10_Byte_Command *gRead;
long count;
clear_memory((void *)&pb, sizeof(pb));
pb.ataPBFunctionCode = kATAMgrExecIO;
pb.ataPBVers = kATAPBVers1;
pb.ataPBDeviceID = deviceID;
pb.ataPBFlags = mATAFlagTFRead | mATAFlagIORead | mATAFlagProtocol1;
pb.ataPBTimeOut = kATAtimeout;
pb.ataPBBuffer = address;
pb.ataPBByteCount = block_size;
pb.ataPBTaskFile.ataTFCylinder = block_size;
if (deviceID & 0x0FF00) {
slave = 0x10;
} else {
slave = 0x0;
}
pb.ataPBTaskFile.ataTFSDH = 0xA0 | 0x40 | slave;
pb.ataPBTaskFile.ataTFCommand = kATAcmdATAPIPacket;
pb.ataPBPacketPtr = &cmdPacket;
cmdPacket.atapiPacketSize = 16;
clear_memory((void *)&cmdPacket.atapiCommandByte, 16);
gRead = (SCSI_10_Byte_Command *) &cmdPacket.atapiCommandByte[0];
gRead->opcode = kScsiCmdRead10;
gRead->lbn4 = (block >> 24) & 0xFF;
gRead->lbn3 = (block >> 16) & 0xFF;
gRead->lbn2 = (block >> 8) & 0xFF;
gRead->lbn1 = block & 0xFF;
count = 1;
gRead->len2 = (count >> 8) & 0xFF;
gRead->len1 = count & 0xFF;
status = ataManager((ataPB*) &pb );
if (status != noErr) {
return 0;
} else {
return 1;
}
}
int
ATAPI_TestUnitReady(UInt32 deviceID)
{
ataIOPB pb;
OSErr status;
long slave;
ATAPICmdPacket cmdPacket;
SCSI_10_Byte_Command *gTestUnit;
clear_memory((void *)&pb, sizeof(pb));
pb.ataPBFunctionCode = kATAMgrExecIO;
pb.ataPBVers = kATAPBVers1;
pb.ataPBDeviceID = deviceID;
pb.ataPBFlags = mATAFlagTFRead | mATAFlagIORead | mATAFlagProtocol1;
pb.ataPBTimeOut = kATAtimeout;
if (deviceID & 0x0FF00) {
slave = 0x10;
} else {
slave = 0x0;
}
pb.ataPBTaskFile.ataTFSDH = 0xA0 | 0x40 | slave;
pb.ataPBTaskFile.ataTFCommand = kATAcmdATAPIPacket;
pb.ataPBPacketPtr = &cmdPacket;
cmdPacket.atapiPacketSize = 16;
clear_memory((void *)&cmdPacket.atapiCommandByte, 16);
gTestUnit = (SCSI_10_Byte_Command *) &cmdPacket.atapiCommandByte[0];
gTestUnit->opcode = kScsiCmdTestUnitReady;
status = ataManager((ataPB*) &pb );
if (status != noErr) {
return 0;
} else {
return 1;
}
}
int
ATAPI_ReadCapacity(UInt32 deviceID, unsigned long *block_size, unsigned long *blocks)
{
ataIOPB pb;
OSErr status;
long slave;
ATAPICmdPacket cmdPacket;
SCSI_10_Byte_Command *gReadCap;
struct read_cap_data {
long addr;
long size;
} rcd;
clear_memory((void *)&pb, sizeof(pb));
pb.ataPBFunctionCode = kATAMgrExecIO;
pb.ataPBVers = kATAPBVers1;
pb.ataPBDeviceID = deviceID;
pb.ataPBFlags = mATAFlagTFRead | mATAFlagIORead | mATAFlagProtocol1;
pb.ataPBTimeOut = kATAtimeout;
pb.ataPBBuffer = (unsigned char *)&rcd;
pb.ataPBByteCount = 8;
pb.ataPBTaskFile.ataTFCylinder = 8;
if (deviceID & 0x0FF00) {
slave = 0x10;
} else {
slave = 0x0;
}
pb.ataPBTaskFile.ataTFSDH = 0xA0 | 0x40 | slave;
pb.ataPBTaskFile.ataTFCommand = kATAcmdATAPIPacket;
pb.ataPBPacketPtr = &cmdPacket;
cmdPacket.atapiPacketSize = 16;
clear_memory((void *)&cmdPacket.atapiCommandByte, 16);
gReadCap = (SCSI_10_Byte_Command *) &cmdPacket.atapiCommandByte[0];
gReadCap->opcode = kScsiCmdReadCapacity;
status = ataManager((ataPB*) &pb );
if (status != noErr) {
return 0;
} else {
*blocks = rcd.addr;
*block_size = rcd.size;
return 1;
}
}
MEDIA
ATA_FindDevice(long dRefNum)
{
ataDrvrRegister pb;
OSErr status;
if (ATAManagerPresent()) {
clear_memory((void *)&pb, sizeof(pb));
pb.ataPBFunctionCode = kATAMgrFindDriverRefnum;
pb.ataPBVers = kATAPBVers1;
pb.ataPBDeviceID = 0xFFFF;
pb.ataPBTimeOut = kATAtimeout;
pb.ataDeviceNextID = 1;
do {
status = ataManager((ataPB*) &pb);
if (status != noErr) {
break;
} else if (pb.ataDrvrRefNum == dRefNum
&& pb.ataPBDeviceID != kNoDevice) {
return open_ata_as_media(pb.ataPBDeviceID & 0xFF,
(pb.ataPBDeviceID >> 8) & 0xFF);
} else {
pb.ataPBDeviceID = pb.ataDeviceNextID;
}
} while (pb.ataPBDeviceID != kNoDevice);
}
return 0;
}
#pragma mark -
ATA_MEDIA_ITERATOR
new_ata_iterator(void)
{
return (ATA_MEDIA_ITERATOR) new_media_iterator(sizeof(struct ATA_media_iterator));
}
MEDIA_ITERATOR
create_ata_iterator(void)
{
ATA_MEDIA_ITERATOR a;
if (ata_inited == 0) {
ata_init();
}
if (ata_mgr.exists == 0) {
return 0;
}
a = new_ata_iterator();
if (a != 0) {
a->m.kind = ata_mgr.kind;
a->m.state = kInit;
a->m.do_reset = reset_ata_iterator;
a->m.do_step = step_ata_iterator;
a->m.do_delete = delete_ata_iterator;
a->bus_index = 0;
a->bus = 0;
a->id = 0;
}
return (MEDIA_ITERATOR) a;
}
void
reset_ata_iterator(MEDIA_ITERATOR m)
{
ATA_MEDIA_ITERATOR a;
a = (ATA_MEDIA_ITERATOR) m;
if (a == 0) {
} else if (a->m.kind != ata_mgr.kind) {
} else if (a->m.state != kInit) {
a->m.state = kReset;
}
}
char *
step_ata_iterator(MEDIA_ITERATOR m)
{
ATA_MEDIA_ITERATOR a;
char *result;
a = (ATA_MEDIA_ITERATOR) m;
if (a == 0) {
} else if (a->m.kind != ata_mgr.kind) {
} else {
switch (a->m.state) {
case kInit:
a->m.state = kReset;
case kReset:
a->bus_index = 0 ;
a->bus = ata_mgr.bus_list[a->bus_index];
a->id = 0 ;
a->m.state = kIterating;
case kIterating:
while (1) {
if (a->bus_index >= ata_mgr.busCount) {
break;
}
if (a->id > 1 ) {
a->bus_index += 1;
a->bus = ata_mgr.bus_list[a->bus_index];
a->id = 0 ;
continue;
}
if (a->bus > 9) {
break;
}
result = (char *) malloc(20);
if (result != NULL) {
snprintf(result, 20, "/dev/ata%c.%c",
'0'+a->bus, '0'+a->id);
}
a->id += 1;
return result;
}
a->m.state = kEnd;
case kEnd:
default:
break;
}
}
return 0 ;
}
void
delete_ata_iterator(MEDIA_ITERATOR m)
{
return;
}
#pragma mark -
#ifdef notdef
MEDIA
open_linux_ata_as_media(long index)
{
long bus;
long id;
long i;
i = index / 2;
if (i >= ata_mgr.busCount) {
bus = 0;
id = 2;
} else {
bus = ata_mgr.bus_list[index / 2];
id = index % 2;
}
return open_ata_as_media(bus, id);
}
#else
MEDIA
open_linux_ata_as_media(long index)
{
long bus;
long id;
bus = index / 2;
id = index % 2;
return open_ata_as_media(bus, id);
}
#endif
char *
linux_ata_name(long bus, long id)
{
char *result;
if (bus >= 13) {
return NULL;
}
result = (char *) malloc(20);
if (result != NULL) {
snprintf(result, 20, "/dev/hd%c", 'a' + (bus*2 + id));
}
return result;
}