xref: /netbsd-src/external/bsd/pdisk/dist/ATA_media.c (revision 48a628ae0434c4247b560ad8f2eb1dc06d0dd070)
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