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