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