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