SCSI_media.c revision 1.2.10.2 1 1.2.10.2 yamt /*
2 1.2.10.2 yamt * SCSI_media.c -
3 1.2.10.2 yamt *
4 1.2.10.2 yamt * Written by Eryk Vershen
5 1.2.10.2 yamt */
6 1.2.10.2 yamt
7 1.2.10.2 yamt /*
8 1.2.10.2 yamt * Copyright 1997,1998 by Apple Computer, Inc.
9 1.2.10.2 yamt * All Rights Reserved
10 1.2.10.2 yamt *
11 1.2.10.2 yamt * Permission to use, copy, modify, and distribute this software and
12 1.2.10.2 yamt * its documentation for any purpose and without fee is hereby granted,
13 1.2.10.2 yamt * provided that the above copyright notice appears in all copies and
14 1.2.10.2 yamt * that both the copyright notice and this permission notice appear in
15 1.2.10.2 yamt * supporting documentation.
16 1.2.10.2 yamt *
17 1.2.10.2 yamt * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
18 1.2.10.2 yamt * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 1.2.10.2 yamt * FOR A PARTICULAR PURPOSE.
20 1.2.10.2 yamt *
21 1.2.10.2 yamt * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
22 1.2.10.2 yamt * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
23 1.2.10.2 yamt * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
24 1.2.10.2 yamt * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
25 1.2.10.2 yamt * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 1.2.10.2 yamt */
27 1.2.10.2 yamt
28 1.2.10.2 yamt
29 1.2.10.2 yamt // for printf() & sprintf()
30 1.2.10.2 yamt #include <stdio.h>
31 1.2.10.2 yamt // for malloc() & free()
32 1.2.10.2 yamt #include <stdlib.h>
33 1.2.10.2 yamt #include "DoSCSICommand.h"
34 1.2.10.2 yamt #include "SCSI_media.h"
35 1.2.10.2 yamt #include "util.h"
36 1.2.10.2 yamt
37 1.2.10.2 yamt
38 1.2.10.2 yamt /*
39 1.2.10.2 yamt * Defines
40 1.2.10.2 yamt */
41 1.2.10.2 yamt #define DriverRefNumToSCSI(x) ((int16_t) (~(x) - 32))
42 1.2.10.2 yamt
43 1.2.10.2 yamt
44 1.2.10.2 yamt /*
45 1.2.10.2 yamt * Types
46 1.2.10.2 yamt */
47 1.2.10.2 yamt typedef struct SCSI_media *SCSI_MEDIA;
48 1.2.10.2 yamt
49 1.2.10.2 yamt struct SCSI_media {
50 1.2.10.2 yamt struct media m;
51 1.2.10.2 yamt long bus;
52 1.2.10.2 yamt long id;
53 1.2.10.2 yamt };
54 1.2.10.2 yamt
55 1.2.10.2 yamt struct bus_entry {
56 1.2.10.2 yamt long bus;
57 1.2.10.2 yamt long sort_value;
58 1.2.10.2 yamt long max_id;
59 1.2.10.2 yamt long master_id;
60 1.2.10.2 yamt };
61 1.2.10.2 yamt
62 1.2.10.2 yamt struct SCSI_manager {
63 1.2.10.2 yamt long exists;
64 1.2.10.2 yamt long kind;
65 1.2.10.2 yamt long bus_count;
66 1.2.10.2 yamt struct bus_entry *bus_list;
67 1.2.10.2 yamt };
68 1.2.10.2 yamt
69 1.2.10.2 yamt typedef struct SCSI_media_iterator *SCSI_MEDIA_ITERATOR;
70 1.2.10.2 yamt
71 1.2.10.2 yamt struct SCSI_media_iterator {
72 1.2.10.2 yamt struct media_iterator m;
73 1.2.10.2 yamt long bus_index;
74 1.2.10.2 yamt long bus;
75 1.2.10.2 yamt long id;
76 1.2.10.2 yamt };
77 1.2.10.2 yamt
78 1.2.10.2 yamt struct linux_order_cache {
79 1.2.10.2 yamt struct cache_item *first;
80 1.2.10.2 yamt struct cache_item *last;
81 1.2.10.2 yamt long next_disk;
82 1.2.10.2 yamt long next_cdrom;
83 1.2.10.2 yamt long loaded;
84 1.2.10.2 yamt };
85 1.2.10.2 yamt
86 1.2.10.2 yamt struct cache_item {
87 1.2.10.2 yamt struct cache_item *next;
88 1.2.10.2 yamt long bus;
89 1.2.10.2 yamt long id;
90 1.2.10.2 yamt long value;
91 1.2.10.2 yamt long is_cdrom;
92 1.2.10.2 yamt long unsure;
93 1.2.10.2 yamt };
94 1.2.10.2 yamt
95 1.2.10.2 yamt
96 1.2.10.2 yamt /*
97 1.2.10.2 yamt * Global Constants
98 1.2.10.2 yamt */
99 1.2.10.2 yamt enum {
100 1.2.10.2 yamt kNoDevice = 0x00FF
101 1.2.10.2 yamt };
102 1.2.10.2 yamt
103 1.2.10.2 yamt enum {
104 1.2.10.2 yamt kRequiredSCSIinquiryLength = 36
105 1.2.10.2 yamt };
106 1.2.10.2 yamt
107 1.2.10.2 yamt
108 1.2.10.2 yamt /*
109 1.2.10.2 yamt * Global Variables
110 1.2.10.2 yamt */
111 1.2.10.2 yamt static long scsi_inited = 0;
112 1.2.10.2 yamt static struct SCSI_manager scsi_mgr;
113 1.2.10.2 yamt static struct linux_order_cache linux_order;
114 1.2.10.2 yamt
115 1.2.10.2 yamt
116 1.2.10.2 yamt /*
117 1.2.10.2 yamt * Forward declarations
118 1.2.10.2 yamt */
119 1.2.10.2 yamt int AsyncSCSIPresent(void);
120 1.2.10.2 yamt void scsi_init(void);
121 1.2.10.2 yamt SCSI_MEDIA new_scsi_media(void);
122 1.2.10.2 yamt long read_scsi_media(MEDIA m, long long offset, uint32_t count, void *address);
123 1.2.10.2 yamt long write_scsi_media(MEDIA m, long long offset, uint32_t count, void *address);
124 1.2.10.2 yamt long close_scsi_media(MEDIA m);
125 1.2.10.2 yamt long os_reload_scsi_media(MEDIA m);
126 1.2.10.2 yamt long compute_id(long bus, long device);
127 1.2.10.2 yamt int SCSI_ReadBlock(UInt32 id, UInt32 bus, UInt32 block_size, UInt32 block, UInt8 *address);
128 1.2.10.2 yamt int SCSI_WriteBlock(UInt32 id, UInt32 bus, UInt32 block_size, UInt32 block, UInt8 *address);
129 1.2.10.2 yamt int DoTestUnitReady(UInt8 targetID, int bus);
130 1.2.10.2 yamt int DoReadCapacity(UInt32 id, UInt32 bus, UInt32 *blockCount, UInt32 *blockSize);
131 1.2.10.2 yamt SCSI_MEDIA_ITERATOR new_scsi_iterator(void);
132 1.2.10.2 yamt void reset_scsi_iterator(MEDIA_ITERATOR m);
133 1.2.10.2 yamt char *step_scsi_iterator(MEDIA_ITERATOR m);
134 1.2.10.2 yamt void delete_scsi_iterator(MEDIA_ITERATOR m);
135 1.2.10.2 yamt void fill_bus_entry(struct bus_entry *entry, long bus);
136 1.2.10.2 yamt /*long get_bus_sort_value(long bus);*/
137 1.2.10.2 yamt int bus_entry_compare(const void* a, const void* b);
138 1.2.10.2 yamt int DoInquiry(UInt32 id, UInt32 bus, UInt32 *devType);
139 1.2.10.2 yamt void probe_all(void);
140 1.2.10.2 yamt void probe_scsi_device(long bus, long id, int unsure);
141 1.2.10.2 yamt long lookup_scsi_device(long bus, long id, int *is_cdrom, int *unsure);
142 1.2.10.2 yamt long lookup_scsi_index(long index, int is_cdrom, long *bus, long *id);
143 1.2.10.2 yamt void add_to_cache(long bus, long id, int is_cdrom, int unsure);
144 1.2.10.2 yamt void init_linux_cache(void);
145 1.2.10.2 yamt void clear_linux_cache(void);
146 1.2.10.2 yamt void mark_linux_cache_loaded(void);
147 1.2.10.2 yamt int linux_cache_loaded(void);
148 1.2.10.2 yamt
149 1.2.10.2 yamt
150 1.2.10.2 yamt /*
151 1.2.10.2 yamt * Routines
152 1.2.10.2 yamt */
153 1.2.10.2 yamt int
154 1.2.10.2 yamt AsyncSCSIPresent(void)
155 1.2.10.2 yamt {
156 1.2.10.2 yamt return (TrapAvailable(_SCSIAtomic));
157 1.2.10.2 yamt }
158 1.2.10.2 yamt
159 1.2.10.2 yamt
160 1.2.10.2 yamt void
161 1.2.10.2 yamt scsi_init(void)
162 1.2.10.2 yamt {
163 1.2.10.2 yamt int i;
164 1.2.10.2 yamt int old_scsi;
165 1.2.10.2 yamt
166 1.2.10.2 yamt if (scsi_inited != 0) {
167 1.2.10.2 yamt return;
168 1.2.10.2 yamt }
169 1.2.10.2 yamt scsi_inited = 1;
170 1.2.10.2 yamt
171 1.2.10.2 yamt scsi_mgr.exists = 1;
172 1.2.10.2 yamt scsi_mgr.kind = allocate_media_kind();
173 1.2.10.2 yamt
174 1.2.10.2 yamt if (AsyncSCSIPresent()) {
175 1.2.10.2 yamt AllocatePB();
176 1.2.10.2 yamt
177 1.2.10.2 yamt scsi_mgr.bus_count = gSCSIHiBusID + 1;
178 1.2.10.2 yamt old_scsi = 0;
179 1.2.10.2 yamt } else {
180 1.2.10.2 yamt scsi_mgr.bus_count = 1;
181 1.2.10.2 yamt old_scsi = 1;
182 1.2.10.2 yamt }
183 1.2.10.2 yamt
184 1.2.10.2 yamt scsi_mgr.bus_list = (struct bus_entry *)
185 1.2.10.2 yamt calloc(scsi_mgr.bus_count, sizeof(struct bus_entry));
186 1.2.10.2 yamt
187 1.2.10.2 yamt if (scsi_mgr.bus_list == 0) {
188 1.2.10.2 yamt scsi_mgr.bus_count = 0;
189 1.2.10.2 yamt } else {
190 1.2.10.2 yamt for (i = 0; i < scsi_mgr.bus_count; i++) {
191 1.2.10.2 yamt if (old_scsi) {
192 1.2.10.2 yamt scsi_mgr.bus_list[i].bus = 0xFF;
193 1.2.10.2 yamt } else {
194 1.2.10.2 yamt scsi_mgr.bus_list[i].bus = i;
195 1.2.10.2 yamt }
196 1.2.10.2 yamt fill_bus_entry(&scsi_mgr.bus_list[i], i);
197 1.2.10.2 yamt }
198 1.2.10.2 yamt qsort((void *)scsi_mgr.bus_list, /* address of array */
199 1.2.10.2 yamt scsi_mgr.bus_count, /* number of elements */
200 1.2.10.2 yamt sizeof(struct bus_entry), /* size of element */
201 1.2.10.2 yamt bus_entry_compare); /* element comparison routine */
202 1.2.10.2 yamt }
203 1.2.10.2 yamt
204 1.2.10.2 yamt init_linux_cache();
205 1.2.10.2 yamt }
206 1.2.10.2 yamt
207 1.2.10.2 yamt void
208 1.2.10.2 yamt fill_bus_entry(struct bus_entry *entry, long bus)
209 1.2.10.2 yamt {
210 1.2.10.2 yamt OSErr status;
211 1.2.10.2 yamt SCSIBusInquiryPB pb;
212 1.2.10.2 yamt long len;
213 1.2.10.2 yamt long result;
214 1.2.10.2 yamt long x, y;
215 1.2.10.2 yamt
216 1.2.10.2 yamt if (!AsyncSCSIPresent()) {
217 1.2.10.2 yamt entry->sort_value = 0;
218 1.2.10.2 yamt entry->max_id = 7;
219 1.2.10.2 yamt entry->master_id = 7;
220 1.2.10.2 yamt return;
221 1.2.10.2 yamt }
222 1.2.10.2 yamt len = sizeof(SCSIBusInquiryPB);
223 1.2.10.2 yamt clear_memory((Ptr) &pb, len);
224 1.2.10.2 yamt pb.scsiPBLength = len;
225 1.2.10.2 yamt pb.scsiFunctionCode = SCSIBusInquiry;
226 1.2.10.2 yamt pb.scsiDevice.bus = bus;
227 1.2.10.2 yamt status = SCSIAction((SCSI_PB *) &pb);
228 1.2.10.2 yamt if (status != noErr) {
229 1.2.10.2 yamt result = 6;
230 1.2.10.2 yamt } else {
231 1.2.10.2 yamt switch (pb.scsiHBAslotType) {
232 1.2.10.2 yamt case scsiMotherboardBus: x = 0; break;
233 1.2.10.2 yamt case scsiPDSBus: x = 1; break;
234 1.2.10.2 yamt case scsiNuBus: x = 2; break;
235 1.2.10.2 yamt case scsiPCIBus: x = 3; break;
236 1.2.10.2 yamt case scsiFireWireBridgeBus: x = 4; break;
237 1.2.10.2 yamt case scsiPCMCIABus: x = 5; break;
238 1.2.10.2 yamt default: x = 7 + pb.scsiHBAslotType; break;
239 1.2.10.2 yamt };
240 1.2.10.2 yamt
241 1.2.10.2 yamt switch (pb.scsiFeatureFlags & scsiBusInternalExternalMask) {
242 1.2.10.2 yamt case scsiBusInternal: y = 0; break;
243 1.2.10.2 yamt case scsiBusInternalExternal: y = 1; break;
244 1.2.10.2 yamt case scsiBusExternal: y = 2; break;
245 1.2.10.2 yamt default:
246 1.2.10.2 yamt case scsiBusInternalExternalUnknown: y = 3; break;
247 1.2.10.2 yamt };
248 1.2.10.2 yamt result = x * 4 + y;
249 1.2.10.2 yamt }
250 1.2.10.2 yamt entry->sort_value = result;
251 1.2.10.2 yamt entry->max_id = pb.scsiMaxLUN;
252 1.2.10.2 yamt entry->master_id = pb.scsiInitiatorID;
253 1.2.10.2 yamt }
254 1.2.10.2 yamt
255 1.2.10.2 yamt
256 1.2.10.2 yamt int
257 1.2.10.2 yamt bus_entry_compare(const void* a, const void* b)
258 1.2.10.2 yamt {
259 1.2.10.2 yamt long result;
260 1.2.10.2 yamt
261 1.2.10.2 yamt const struct bus_entry *x = (const struct bus_entry *) a;
262 1.2.10.2 yamt const struct bus_entry *y = (const struct bus_entry *) b;
263 1.2.10.2 yamt
264 1.2.10.2 yamt result = x->sort_value - y->sort_value;
265 1.2.10.2 yamt if (result == 0) {
266 1.2.10.2 yamt result = x->bus - y->bus;
267 1.2.10.2 yamt }
268 1.2.10.2 yamt return result;
269 1.2.10.2 yamt }
270 1.2.10.2 yamt
271 1.2.10.2 yamt
272 1.2.10.2 yamt SCSI_MEDIA
273 1.2.10.2 yamt new_scsi_media(void)
274 1.2.10.2 yamt {
275 1.2.10.2 yamt return (SCSI_MEDIA) new_media(sizeof(struct SCSI_media));
276 1.2.10.2 yamt }
277 1.2.10.2 yamt
278 1.2.10.2 yamt
279 1.2.10.2 yamt MEDIA
280 1.2.10.2 yamt open_old_scsi_as_media(long device)
281 1.2.10.2 yamt {
282 1.2.10.2 yamt return open_scsi_as_media(kOriginalSCSIBusAdaptor, device);
283 1.2.10.2 yamt }
284 1.2.10.2 yamt
285 1.2.10.2 yamt
286 1.2.10.2 yamt MEDIA
287 1.2.10.2 yamt open_scsi_as_media(long bus, long device)
288 1.2.10.2 yamt {
289 1.2.10.2 yamt SCSI_MEDIA a;
290 1.2.10.2 yamt UInt32 blockCount;
291 1.2.10.2 yamt UInt32 blockSize;
292 1.2.10.2 yamt
293 1.2.10.2 yamt if (scsi_inited == 0) {
294 1.2.10.2 yamt scsi_init();
295 1.2.10.2 yamt }
296 1.2.10.2 yamt
297 1.2.10.2 yamt if (scsi_mgr.exists == 0) {
298 1.2.10.2 yamt return 0;
299 1.2.10.2 yamt }
300 1.2.10.2 yamt
301 1.2.10.2 yamt a = 0;
302 1.2.10.2 yamt if (DoTestUnitReady(device, bus) > 0) {
303 1.2.10.2 yamt if (DoReadCapacity(device, bus, &blockCount, &blockSize) != 0) {
304 1.2.10.2 yamt a = new_scsi_media();
305 1.2.10.2 yamt if (a != 0) {
306 1.2.10.2 yamt a->m.kind = scsi_mgr.kind;
307 1.2.10.2 yamt a->m.grain = blockSize;
308 1.2.10.2 yamt a->m.size_in_bytes = ((long long)blockCount) * blockSize;
309 1.2.10.2 yamt a->m.do_read = read_scsi_media;
310 1.2.10.2 yamt a->m.do_write = write_scsi_media;
311 1.2.10.2 yamt a->m.do_close = close_scsi_media;
312 1.2.10.2 yamt a->m.do_os_reload = os_reload_scsi_media;
313 1.2.10.2 yamt a->bus = bus;
314 1.2.10.2 yamt a->id = device;
315 1.2.10.2 yamt }
316 1.2.10.2 yamt }
317 1.2.10.2 yamt }
318 1.2.10.2 yamt return (MEDIA) a;
319 1.2.10.2 yamt }
320 1.2.10.2 yamt
321 1.2.10.2 yamt
322 1.2.10.2 yamt long
323 1.2.10.2 yamt read_scsi_media(MEDIA m, long long offset, uint32_t count, void *address)
324 1.2.10.2 yamt {
325 1.2.10.2 yamt SCSI_MEDIA a;
326 1.2.10.2 yamt long rtn_value;
327 1.2.10.2 yamt long block;
328 1.2.10.2 yamt long block_count;
329 1.2.10.2 yamt long block_size;
330 1.2.10.2 yamt uint8_t *buffer;
331 1.2.10.2 yamt int i;
332 1.2.10.2 yamt
333 1.2.10.2 yamt block = (long) offset;
334 1.2.10.2 yamt //printf("scsi %d count %d\n", block, count);
335 1.2.10.2 yamt a = (SCSI_MEDIA) m;
336 1.2.10.2 yamt rtn_value = 0;
337 1.2.10.2 yamt if (a == 0) {
338 1.2.10.2 yamt /* no media */
339 1.2.10.2 yamt } else if (a->m.kind != scsi_mgr.kind) {
340 1.2.10.2 yamt /* wrong kind - XXX need to error here - this is an internal problem */
341 1.2.10.2 yamt } else if (count <= 0 || count % a->m.grain != 0) {
342 1.2.10.2 yamt /* can't handle size */
343 1.2.10.2 yamt } else if (offset < 0 || offset % a->m.grain != 0) {
344 1.2.10.2 yamt /* can't handle offset */
345 1.2.10.2 yamt } else if (offset + count > a->m.size_in_bytes) {
346 1.2.10.2 yamt /* check for offset (and offset+count) too large */
347 1.2.10.2 yamt } else {
348 1.2.10.2 yamt /* XXX do a read on the physical device */
349 1.2.10.2 yamt block_size = a->m.grain;
350 1.2.10.2 yamt block = offset / block_size;
351 1.2.10.2 yamt block_count = count / block_size;
352 1.2.10.2 yamt buffer = address;
353 1.2.10.2 yamt rtn_value = 1;
354 1.2.10.2 yamt for (i = 0; i < block_count; i++) {
355 1.2.10.2 yamt if (SCSI_ReadBlock(a->id, a->bus, block_size, block, buffer) == 0) {
356 1.2.10.2 yamt rtn_value = 0;
357 1.2.10.2 yamt break;
358 1.2.10.2 yamt }
359 1.2.10.2 yamt buffer += block_size;
360 1.2.10.2 yamt block += 1;
361 1.2.10.2 yamt }
362 1.2.10.2 yamt }
363 1.2.10.2 yamt return rtn_value;
364 1.2.10.2 yamt }
365 1.2.10.2 yamt
366 1.2.10.2 yamt
367 1.2.10.2 yamt long
368 1.2.10.2 yamt write_scsi_media(MEDIA m, long long offset, uint32_t count, void *address)
369 1.2.10.2 yamt {
370 1.2.10.2 yamt SCSI_MEDIA a;
371 1.2.10.2 yamt long rtn_value;
372 1.2.10.2 yamt long block;
373 1.2.10.2 yamt long block_count;
374 1.2.10.2 yamt long block_size;
375 1.2.10.2 yamt uint8_t *buffer;
376 1.2.10.2 yamt int i;
377 1.2.10.2 yamt
378 1.2.10.2 yamt a = (SCSI_MEDIA) m;
379 1.2.10.2 yamt rtn_value = 0;
380 1.2.10.2 yamt if (a == 0) {
381 1.2.10.2 yamt /* no media */
382 1.2.10.2 yamt } else if (a->m.kind != scsi_mgr.kind) {
383 1.2.10.2 yamt /* XXX need to error here - this is an internal problem */
384 1.2.10.2 yamt } else if (count <= 0 || count % a->m.grain != 0) {
385 1.2.10.2 yamt /* can't handle size */
386 1.2.10.2 yamt } else if (offset < 0 || offset % a->m.grain != 0) {
387 1.2.10.2 yamt /* can't handle offset */
388 1.2.10.2 yamt } else if (offset + count > a->m.size_in_bytes) {
389 1.2.10.2 yamt /* check for offset (and offset+count) too large */
390 1.2.10.2 yamt } else {
391 1.2.10.2 yamt /* XXX do a write on the physical device */
392 1.2.10.2 yamt block_size = a->m.grain;
393 1.2.10.2 yamt block = offset / block_size;
394 1.2.10.2 yamt block_count = count / block_size;
395 1.2.10.2 yamt buffer = address;
396 1.2.10.2 yamt rtn_value = 1;
397 1.2.10.2 yamt for (i = 0; i < block_count; i++) {
398 1.2.10.2 yamt if (SCSI_WriteBlock(a->id, a->bus, block_size, block, buffer) == 0) {
399 1.2.10.2 yamt rtn_value = 0;
400 1.2.10.2 yamt break;
401 1.2.10.2 yamt }
402 1.2.10.2 yamt buffer += block_size;
403 1.2.10.2 yamt block += 1;
404 1.2.10.2 yamt }
405 1.2.10.2 yamt }
406 1.2.10.2 yamt return rtn_value;
407 1.2.10.2 yamt }
408 1.2.10.2 yamt
409 1.2.10.2 yamt
410 1.2.10.2 yamt long
411 1.2.10.2 yamt close_scsi_media(MEDIA m)
412 1.2.10.2 yamt {
413 1.2.10.2 yamt SCSI_MEDIA a;
414 1.2.10.2 yamt
415 1.2.10.2 yamt a = (SCSI_MEDIA) m;
416 1.2.10.2 yamt if (a == 0) {
417 1.2.10.2 yamt return 0;
418 1.2.10.2 yamt } else if (a->m.kind != scsi_mgr.kind) {
419 1.2.10.2 yamt /* XXX need to error here - this is an internal problem */
420 1.2.10.2 yamt return 0;
421 1.2.10.2 yamt }
422 1.2.10.2 yamt /* XXX nothing to do - I think? */
423 1.2.10.2 yamt return 1;
424 1.2.10.2 yamt }
425 1.2.10.2 yamt
426 1.2.10.2 yamt
427 1.2.10.2 yamt long
428 1.2.10.2 yamt os_reload_scsi_media(MEDIA m)
429 1.2.10.2 yamt {
430 1.2.10.2 yamt printf("Reboot your system so the partition table will be reread.\n");
431 1.2.10.2 yamt return 1;
432 1.2.10.2 yamt }
433 1.2.10.2 yamt
434 1.2.10.2 yamt
435 1.2.10.2 yamt #pragma mark -
436 1.2.10.2 yamt
437 1.2.10.2 yamt
438 1.2.10.2 yamt int
439 1.2.10.2 yamt DoTestUnitReady(UInt8 targetID, int bus)
440 1.2.10.2 yamt {
441 1.2.10.2 yamt OSErr status;
442 1.2.10.2 yamt Str255 errorText;
443 1.2.10.2 yamt char* msg;
444 1.2.10.2 yamt static const SCSI_6_Byte_Command gTestUnitReadyCommand = {
445 1.2.10.2 yamt kScsiCmdTestUnitReady, 0, 0, 0, 0, 0
446 1.2.10.2 yamt };
447 1.2.10.2 yamt SCSI_Sense_Data senseData;
448 1.2.10.2 yamt DeviceIdent scsiDevice;
449 1.2.10.2 yamt int rtn_value;
450 1.2.10.2 yamt
451 1.2.10.2 yamt scsiDevice.diReserved = 0;
452 1.2.10.2 yamt scsiDevice.bus = bus;
453 1.2.10.2 yamt scsiDevice.targetID = targetID;
454 1.2.10.2 yamt scsiDevice.LUN = 0;
455 1.2.10.2 yamt
456 1.2.10.2 yamt status = DoSCSICommand(
457 1.2.10.2 yamt scsiDevice,
458 1.2.10.2 yamt "\pTest Unit Ready",
459 1.2.10.2 yamt (SCSI_CommandPtr) &gTestUnitReadyCommand,
460 1.2.10.2 yamt NULL,
461 1.2.10.2 yamt 0,
462 1.2.10.2 yamt scsiDirectionNone,
463 1.2.10.2 yamt NULL,
464 1.2.10.2 yamt &senseData,
465 1.2.10.2 yamt errorText
466 1.2.10.2 yamt );
467 1.2.10.2 yamt if (status == scsiNonZeroStatus) {
468 1.2.10.2 yamt rtn_value = -1;
469 1.2.10.2 yamt } else if (status != noErr) {
470 1.2.10.2 yamt rtn_value = 0;
471 1.2.10.2 yamt } else {
472 1.2.10.2 yamt rtn_value = 1;
473 1.2.10.2 yamt }
474 1.2.10.2 yamt return rtn_value;
475 1.2.10.2 yamt }
476 1.2.10.2 yamt
477 1.2.10.2 yamt
478 1.2.10.2 yamt int
479 1.2.10.2 yamt SCSI_ReadBlock(UInt32 id, UInt32 bus, UInt32 block_size, UInt32 block, UInt8 *address)
480 1.2.10.2 yamt {
481 1.2.10.2 yamt OSErr status;
482 1.2.10.2 yamt Str255 errorText;
483 1.2.10.2 yamt char* msg;
484 1.2.10.2 yamt static SCSI_10_Byte_Command gReadCommand = {
485 1.2.10.2 yamt kScsiCmdRead10, 0, 0, 0, 0, 0, 0, 0, 0, 0
486 1.2.10.2 yamt };
487 1.2.10.2 yamt SCSI_Sense_Data senseData;
488 1.2.10.2 yamt DeviceIdent scsiDevice;
489 1.2.10.2 yamt int rtn_value;
490 1.2.10.2 yamt long count;
491 1.2.10.2 yamt
492 1.2.10.2 yamt //printf("scsi read %d:%d block %d size %d\n", bus, id, block, block_size);
493 1.2.10.2 yamt scsiDevice.diReserved = 0;
494 1.2.10.2 yamt scsiDevice.bus = bus;
495 1.2.10.2 yamt scsiDevice.targetID = id;
496 1.2.10.2 yamt scsiDevice.LUN = 0;
497 1.2.10.2 yamt
498 1.2.10.2 yamt gReadCommand.lbn4 = (block >> 24) & 0xFF;
499 1.2.10.2 yamt gReadCommand.lbn3 = (block >> 16) & 0xFF;
500 1.2.10.2 yamt gReadCommand.lbn2 = (block >> 8) & 0xFF;
501 1.2.10.2 yamt gReadCommand.lbn1 = block & 0xFF;
502 1.2.10.2 yamt
503 1.2.10.2 yamt count = 1;
504 1.2.10.2 yamt gReadCommand.len2 = (count >> 8) & 0xFF;
505 1.2.10.2 yamt gReadCommand.len1 = count & 0xFF;
506 1.2.10.2 yamt
507 1.2.10.2 yamt status = DoSCSICommand(
508 1.2.10.2 yamt scsiDevice,
509 1.2.10.2 yamt "\pRead",
510 1.2.10.2 yamt (SCSI_CommandPtr) &gReadCommand,
511 1.2.10.2 yamt (Ptr) address,
512 1.2.10.2 yamt count * block_size,
513 1.2.10.2 yamt scsiDirectionIn,
514 1.2.10.2 yamt NULL,
515 1.2.10.2 yamt &senseData,
516 1.2.10.2 yamt errorText
517 1.2.10.2 yamt );
518 1.2.10.2 yamt if (status == noErr) {
519 1.2.10.2 yamt rtn_value = 1;
520 1.2.10.2 yamt } else {
521 1.2.10.2 yamt rtn_value = 0;
522 1.2.10.2 yamt }
523 1.2.10.2 yamt return rtn_value;
524 1.2.10.2 yamt }
525 1.2.10.2 yamt
526 1.2.10.2 yamt
527 1.2.10.2 yamt int
528 1.2.10.2 yamt SCSI_WriteBlock(UInt32 id, UInt32 bus, UInt32 block_size, UInt32 block, UInt8 *address)
529 1.2.10.2 yamt {
530 1.2.10.2 yamt OSErr status;
531 1.2.10.2 yamt Str255 errorText;
532 1.2.10.2 yamt char* msg;
533 1.2.10.2 yamt static SCSI_10_Byte_Command gWriteCommand = {
534 1.2.10.2 yamt kScsiCmdWrite10, 0, 0, 0, 0, 0, 0, 0, 0, 0
535 1.2.10.2 yamt };
536 1.2.10.2 yamt SCSI_Sense_Data senseData;
537 1.2.10.2 yamt DeviceIdent scsiDevice;
538 1.2.10.2 yamt int rtn_value;
539 1.2.10.2 yamt long count;
540 1.2.10.2 yamt
541 1.2.10.2 yamt scsiDevice.diReserved = 0;
542 1.2.10.2 yamt scsiDevice.bus = bus;
543 1.2.10.2 yamt scsiDevice.targetID = id;
544 1.2.10.2 yamt scsiDevice.LUN = 0;
545 1.2.10.2 yamt
546 1.2.10.2 yamt gWriteCommand.lbn4 = (block >> 24) & 0xFF;
547 1.2.10.2 yamt gWriteCommand.lbn3 = (block >> 16) & 0xFF;
548 1.2.10.2 yamt gWriteCommand.lbn2 = (block >> 8) & 0xFF;
549 1.2.10.2 yamt gWriteCommand.lbn1 = block & 0xFF;
550 1.2.10.2 yamt
551 1.2.10.2 yamt count = 1;
552 1.2.10.2 yamt gWriteCommand.len2 = (count >> 8) & 0xFF;
553 1.2.10.2 yamt gWriteCommand.len1 = count & 0xFF;
554 1.2.10.2 yamt
555 1.2.10.2 yamt status = DoSCSICommand(
556 1.2.10.2 yamt scsiDevice,
557 1.2.10.2 yamt "\pWrite",
558 1.2.10.2 yamt (SCSI_CommandPtr) &gWriteCommand,
559 1.2.10.2 yamt (Ptr) address,
560 1.2.10.2 yamt count * block_size,
561 1.2.10.2 yamt scsiDirectionOut,
562 1.2.10.2 yamt NULL,
563 1.2.10.2 yamt &senseData,
564 1.2.10.2 yamt errorText
565 1.2.10.2 yamt );
566 1.2.10.2 yamt if (status == noErr) {
567 1.2.10.2 yamt rtn_value = 1;
568 1.2.10.2 yamt } else {
569 1.2.10.2 yamt rtn_value = 0;
570 1.2.10.2 yamt }
571 1.2.10.2 yamt return rtn_value;
572 1.2.10.2 yamt }
573 1.2.10.2 yamt
574 1.2.10.2 yamt
575 1.2.10.2 yamt int
576 1.2.10.2 yamt DoReadCapacity(UInt32 id, UInt32 bus, UInt32 *blockCount, UInt32 *blockSize)
577 1.2.10.2 yamt {
578 1.2.10.2 yamt OSErr status;
579 1.2.10.2 yamt Str255 errorText;
580 1.2.10.2 yamt static const SCSI_10_Byte_Command gCapacityCommand = {
581 1.2.10.2 yamt kScsiCmdReadCapacity, 0, 0, 0, 0, 0, 0, 0, 0, 0
582 1.2.10.2 yamt };
583 1.2.10.2 yamt SCSI_Sense_Data senseData;
584 1.2.10.2 yamt DeviceIdent scsiDevice;
585 1.2.10.2 yamt SCSI_Capacity_Data capacityData;
586 1.2.10.2 yamt UInt32 temp;
587 1.2.10.2 yamt int rtn_value;
588 1.2.10.2 yamt
589 1.2.10.2 yamt scsiDevice.diReserved = 0;
590 1.2.10.2 yamt scsiDevice.bus = bus;
591 1.2.10.2 yamt scsiDevice.targetID = id;
592 1.2.10.2 yamt scsiDevice.LUN = 0;
593 1.2.10.2 yamt
594 1.2.10.2 yamt CLEAR(capacityData);
595 1.2.10.2 yamt
596 1.2.10.2 yamt status = DoSCSICommand(
597 1.2.10.2 yamt scsiDevice,
598 1.2.10.2 yamt "\pRead Capacity",
599 1.2.10.2 yamt (SCSI_CommandPtr) &gCapacityCommand,
600 1.2.10.2 yamt (Ptr) &capacityData,
601 1.2.10.2 yamt sizeof (SCSI_Capacity_Data),
602 1.2.10.2 yamt scsiDirectionIn,
603 1.2.10.2 yamt NULL,
604 1.2.10.2 yamt &senseData,
605 1.2.10.2 yamt errorText
606 1.2.10.2 yamt );
607 1.2.10.2 yamt
608 1.2.10.2 yamt if (status == noErr) {
609 1.2.10.2 yamt temp = capacityData.lbn4;
610 1.2.10.2 yamt temp = (temp << 8) | capacityData.lbn3;
611 1.2.10.2 yamt temp = (temp << 8) | capacityData.lbn2;
612 1.2.10.2 yamt temp = (temp << 8) | capacityData.lbn1;
613 1.2.10.2 yamt *blockCount = temp;
614 1.2.10.2 yamt
615 1.2.10.2 yamt temp = capacityData.len4;
616 1.2.10.2 yamt temp = (temp << 8) | capacityData.len3;
617 1.2.10.2 yamt temp = (temp << 8) | capacityData.len2;
618 1.2.10.2 yamt temp = (temp << 8) | capacityData.len1;
619 1.2.10.2 yamt *blockSize = temp;
620 1.2.10.2 yamt
621 1.2.10.2 yamt rtn_value = 1;
622 1.2.10.2 yamt } else {
623 1.2.10.2 yamt rtn_value = 0;
624 1.2.10.2 yamt }
625 1.2.10.2 yamt return rtn_value;
626 1.2.10.2 yamt }
627 1.2.10.2 yamt
628 1.2.10.2 yamt
629 1.2.10.2 yamt int
630 1.2.10.2 yamt DoInquiry(UInt32 id, UInt32 bus, UInt32 *devType)
631 1.2.10.2 yamt {
632 1.2.10.2 yamt OSErr status;
633 1.2.10.2 yamt Str255 errorText;
634 1.2.10.2 yamt static const SCSI_6_Byte_Command gInquiryCommand = {
635 1.2.10.2 yamt kScsiCmdInquiry, 0, 0, 0, kRequiredSCSIinquiryLength, 0
636 1.2.10.2 yamt };
637 1.2.10.2 yamt SCSI_Sense_Data senseData;
638 1.2.10.2 yamt DeviceIdent scsiDevice;
639 1.2.10.2 yamt SCSI_Inquiry_Data inquiryData;
640 1.2.10.2 yamt UInt32 temp;
641 1.2.10.2 yamt int rtn_value;
642 1.2.10.2 yamt
643 1.2.10.2 yamt scsiDevice.diReserved = 0;
644 1.2.10.2 yamt scsiDevice.bus = bus;
645 1.2.10.2 yamt scsiDevice.targetID = id;
646 1.2.10.2 yamt scsiDevice.LUN = 0;
647 1.2.10.2 yamt
648 1.2.10.2 yamt CLEAR(inquiryData);
649 1.2.10.2 yamt
650 1.2.10.2 yamt status = DoSCSICommand(
651 1.2.10.2 yamt scsiDevice,
652 1.2.10.2 yamt "\pInquiry",
653 1.2.10.2 yamt (SCSI_CommandPtr) &gInquiryCommand,
654 1.2.10.2 yamt (Ptr) &inquiryData,
655 1.2.10.2 yamt kRequiredSCSIinquiryLength,
656 1.2.10.2 yamt scsiDirectionIn,
657 1.2.10.2 yamt NULL,
658 1.2.10.2 yamt &senseData,
659 1.2.10.2 yamt errorText
660 1.2.10.2 yamt );
661 1.2.10.2 yamt
662 1.2.10.2 yamt if (status == noErr) {
663 1.2.10.2 yamt *devType = inquiryData.devType & kScsiDevTypeMask;
664 1.2.10.2 yamt rtn_value = 1;
665 1.2.10.2 yamt } else {
666 1.2.10.2 yamt rtn_value = 0;
667 1.2.10.2 yamt }
668 1.2.10.2 yamt return rtn_value;
669 1.2.10.2 yamt }
670 1.2.10.2 yamt
671 1.2.10.2 yamt
672 1.2.10.2 yamt MEDIA
673 1.2.10.2 yamt SCSI_FindDevice(long dRefNum)
674 1.2.10.2 yamt {
675 1.2.10.2 yamt SCSIDriverPB pb;
676 1.2.10.2 yamt OSErr status;
677 1.2.10.2 yamt short targetID;
678 1.2.10.2 yamt
679 1.2.10.2 yamt status = nsvErr;
680 1.2.10.2 yamt if (AsyncSCSIPresent()) {
681 1.2.10.2 yamt clear_memory((Ptr) &pb, sizeof pb);
682 1.2.10.2 yamt
683 1.2.10.2 yamt pb.scsiPBLength = sizeof (SCSIDriverPB);
684 1.2.10.2 yamt pb.scsiCompletion = NULL;
685 1.2.10.2 yamt pb.scsiFlags = 0;
686 1.2.10.2 yamt pb.scsiFunctionCode = SCSILookupRefNumXref;
687 1.2.10.2 yamt pb.scsiDevice.bus = kNoDevice; /* was *((long *) &pb.scsiDevice) = 0xFFFFFFFFL; */
688 1.2.10.2 yamt
689 1.2.10.2 yamt do {
690 1.2.10.2 yamt status = SCSIAction((SCSI_PB *) &pb);
691 1.2.10.2 yamt
692 1.2.10.2 yamt if (status != noErr) {
693 1.2.10.2 yamt break;
694 1.2.10.2 yamt } else if (pb.scsiDriver == dRefNum
695 1.2.10.2 yamt && pb.scsiDevice.bus != kNoDevice) {
696 1.2.10.2 yamt return open_scsi_as_media(pb.scsiDevice.bus, pb.scsiDevice.targetID);
697 1.2.10.2 yamt
698 1.2.10.2 yamt } else {
699 1.2.10.2 yamt pb.scsiDevice = pb.scsiNextDevice;
700 1.2.10.2 yamt }
701 1.2.10.2 yamt }
702 1.2.10.2 yamt while (pb.scsiDevice.bus != kNoDevice);
703 1.2.10.2 yamt }
704 1.2.10.2 yamt if (status == nsvErr) {
705 1.2.10.2 yamt /*
706 1.2.10.2 yamt * The asynchronous SCSI Manager is missing or the
707 1.2.10.2 yamt * driver didn't register with the SCSI Manager.*/
708 1.2.10.2 yamt targetID = DriverRefNumToSCSI(dRefNum);
709 1.2.10.2 yamt if (targetID >= 0 && targetID <= 6) {
710 1.2.10.2 yamt return open_old_scsi_as_media(targetID);
711 1.2.10.2 yamt }
712 1.2.10.2 yamt }
713 1.2.10.2 yamt return 0;
714 1.2.10.2 yamt }
715 1.2.10.2 yamt
716 1.2.10.2 yamt
717 1.2.10.2 yamt #pragma mark -
718 1.2.10.2 yamt
719 1.2.10.2 yamt
720 1.2.10.2 yamt SCSI_MEDIA_ITERATOR
721 1.2.10.2 yamt new_scsi_iterator(void)
722 1.2.10.2 yamt {
723 1.2.10.2 yamt return (SCSI_MEDIA_ITERATOR) new_media_iterator(sizeof(struct SCSI_media_iterator));
724 1.2.10.2 yamt }
725 1.2.10.2 yamt
726 1.2.10.2 yamt
727 1.2.10.2 yamt MEDIA_ITERATOR
728 1.2.10.2 yamt create_scsi_iterator(void)
729 1.2.10.2 yamt {
730 1.2.10.2 yamt SCSI_MEDIA_ITERATOR a;
731 1.2.10.2 yamt
732 1.2.10.2 yamt if (scsi_inited == 0) {
733 1.2.10.2 yamt scsi_init();
734 1.2.10.2 yamt }
735 1.2.10.2 yamt
736 1.2.10.2 yamt if (scsi_mgr.exists == 0) {
737 1.2.10.2 yamt return 0;
738 1.2.10.2 yamt }
739 1.2.10.2 yamt
740 1.2.10.2 yamt a = new_scsi_iterator();
741 1.2.10.2 yamt if (a != 0) {
742 1.2.10.2 yamt a->m.kind = scsi_mgr.kind;
743 1.2.10.2 yamt a->m.state = kInit;
744 1.2.10.2 yamt a->m.do_reset = reset_scsi_iterator;
745 1.2.10.2 yamt a->m.do_step = step_scsi_iterator;
746 1.2.10.2 yamt a->m.do_delete = delete_scsi_iterator;
747 1.2.10.2 yamt a->bus_index = 0;
748 1.2.10.2 yamt a->bus = 0;
749 1.2.10.2 yamt a->id = 0;
750 1.2.10.2 yamt }
751 1.2.10.2 yamt
752 1.2.10.2 yamt return (MEDIA_ITERATOR) a;
753 1.2.10.2 yamt }
754 1.2.10.2 yamt
755 1.2.10.2 yamt
756 1.2.10.2 yamt void
757 1.2.10.2 yamt reset_scsi_iterator(MEDIA_ITERATOR m)
758 1.2.10.2 yamt {
759 1.2.10.2 yamt SCSI_MEDIA_ITERATOR a;
760 1.2.10.2 yamt
761 1.2.10.2 yamt a = (SCSI_MEDIA_ITERATOR) m;
762 1.2.10.2 yamt if (a == 0) {
763 1.2.10.2 yamt /* no media */
764 1.2.10.2 yamt } else if (a->m.kind != scsi_mgr.kind) {
765 1.2.10.2 yamt /* wrong kind - XXX need to error here - this is an internal problem */
766 1.2.10.2 yamt } else if (a->m.state != kInit) {
767 1.2.10.2 yamt a->m.state = kReset;
768 1.2.10.2 yamt }
769 1.2.10.2 yamt }
770 1.2.10.2 yamt
771 1.2.10.2 yamt
772 1.2.10.2 yamt char *
773 1.2.10.2 yamt step_scsi_iterator(MEDIA_ITERATOR m)
774 1.2.10.2 yamt {
775 1.2.10.2 yamt SCSI_MEDIA_ITERATOR a;
776 1.2.10.2 yamt char *result;
777 1.2.10.2 yamt
778 1.2.10.2 yamt a = (SCSI_MEDIA_ITERATOR) m;
779 1.2.10.2 yamt if (a == 0) {
780 1.2.10.2 yamt /* no media */
781 1.2.10.2 yamt } else if (a->m.kind != scsi_mgr.kind) {
782 1.2.10.2 yamt /* wrong kind - XXX need to error here - this is an internal problem */
783 1.2.10.2 yamt } else {
784 1.2.10.2 yamt switch (a->m.state) {
785 1.2.10.2 yamt case kInit:
786 1.2.10.2 yamt /* find # of buses - done in AllocatePB() out of scsi_init() */
787 1.2.10.2 yamt a->m.state = kReset;
788 1.2.10.2 yamt /* fall through to reset */
789 1.2.10.2 yamt case kReset:
790 1.2.10.2 yamt a->bus_index = 0 /* first bus id */;
791 1.2.10.2 yamt a->bus = scsi_mgr.bus_list[a->bus_index].bus;
792 1.2.10.2 yamt a->id = 0 /* first device id */;
793 1.2.10.2 yamt a->m.state = kIterating;
794 1.2.10.2 yamt clear_linux_cache();
795 1.2.10.2 yamt /* fall through to iterate */
796 1.2.10.2 yamt case kIterating:
797 1.2.10.2 yamt while (1) {
798 1.2.10.2 yamt if (a->bus_index >= scsi_mgr.bus_count /* max bus id */) {
799 1.2.10.2 yamt break;
800 1.2.10.2 yamt }
801 1.2.10.2 yamt if (a->id == scsi_mgr.bus_list[a->bus_index].master_id) {
802 1.2.10.2 yamt /* next id */
803 1.2.10.2 yamt a->id += 1;
804 1.2.10.2 yamt }
805 1.2.10.2 yamt if (a->id > scsi_mgr.bus_list[a->bus_index].max_id) {
806 1.2.10.2 yamt a->bus_index += 1;
807 1.2.10.2 yamt a->bus = scsi_mgr.bus_list[a->bus_index].bus;
808 1.2.10.2 yamt a->id = 0 /* first device id */;
809 1.2.10.2 yamt continue; /* try again */
810 1.2.10.2 yamt }
811 1.2.10.2 yamt /* generate result */
812 1.2.10.2 yamt result = (char *) malloc(20);
813 1.2.10.2 yamt if (result != NULL) {
814 1.2.10.2 yamt if (a->bus == 0xFF) {
815 1.2.10.2 yamt snprintf(result, 20, "/dev/scsi%c", '0'+a->id);
816 1.2.10.2 yamt probe_scsi_device(a->bus, a->id, 1);
817 1.2.10.2 yamt } else {
818 1.2.10.2 yamt // insure bus number in range
819 1.2.10.2 yamt if (a->bus > 9) {
820 1.2.10.2 yamt free(result);
821 1.2.10.2 yamt result = NULL;
822 1.2.10.2 yamt break;
823 1.2.10.2 yamt }
824 1.2.10.2 yamt snprintf(result, 20, "/dev/scsi%c.%c",
825 1.2.10.2 yamt '0'+a->bus, '0'+a->id);
826 1.2.10.2 yamt /* only probe out of iterate; so always added in order. */
827 1.2.10.2 yamt probe_scsi_device(a->bus, a->id, 0);
828 1.2.10.2 yamt }
829 1.2.10.2 yamt }
830 1.2.10.2 yamt
831 1.2.10.2 yamt a->id += 1; /* next id */
832 1.2.10.2 yamt return result;
833 1.2.10.2 yamt }
834 1.2.10.2 yamt a->m.state = kEnd;
835 1.2.10.2 yamt /* fall through to end */
836 1.2.10.2 yamt case kEnd:
837 1.2.10.2 yamt mark_linux_cache_loaded();
838 1.2.10.2 yamt default:
839 1.2.10.2 yamt break;
840 1.2.10.2 yamt }
841 1.2.10.2 yamt }
842 1.2.10.2 yamt return 0 /* no entry */;
843 1.2.10.2 yamt }
844 1.2.10.2 yamt
845 1.2.10.2 yamt
846 1.2.10.2 yamt void
847 1.2.10.2 yamt delete_scsi_iterator(MEDIA_ITERATOR m)
848 1.2.10.2 yamt {
849 1.2.10.2 yamt return;
850 1.2.10.2 yamt }
851 1.2.10.2 yamt
852 1.2.10.2 yamt
853 1.2.10.2 yamt #pragma mark -
854 1.2.10.2 yamt
855 1.2.10.2 yamt
856 1.2.10.2 yamt MEDIA
857 1.2.10.2 yamt open_linux_scsi_as_media(long index, int is_cdrom)
858 1.2.10.2 yamt {
859 1.2.10.2 yamt MEDIA m;
860 1.2.10.2 yamt long bus;
861 1.2.10.2 yamt long id;
862 1.2.10.2 yamt
863 1.2.10.2 yamt if (lookup_scsi_index(index, is_cdrom, &bus, &id) > 0) {
864 1.2.10.2 yamt m = open_scsi_as_media(bus, id);
865 1.2.10.2 yamt } else {
866 1.2.10.2 yamt m = 0;
867 1.2.10.2 yamt }
868 1.2.10.2 yamt
869 1.2.10.2 yamt return m;
870 1.2.10.2 yamt }
871 1.2.10.2 yamt
872 1.2.10.2 yamt
873 1.2.10.2 yamt char *
874 1.2.10.2 yamt linux_old_scsi_name(long id)
875 1.2.10.2 yamt {
876 1.2.10.2 yamt linux_scsi_name(kOriginalSCSIBusAdaptor, id);
877 1.2.10.2 yamt }
878 1.2.10.2 yamt
879 1.2.10.2 yamt
880 1.2.10.2 yamt char *
881 1.2.10.2 yamt linux_scsi_name(long bus, long id)
882 1.2.10.2 yamt {
883 1.2.10.2 yamt char *result = 0;
884 1.2.10.2 yamt long value;
885 1.2.10.2 yamt int is_cdrom;
886 1.2.10.2 yamt int unsure;
887 1.2.10.2 yamt char *suffix;
888 1.2.10.2 yamt
889 1.2.10.2 yamt /* name is sda, sdb, sdc, ...
890 1.2.10.2 yamt * in order by buses and ids, but only count responding devices ...
891 1.2.10.2 yamt */
892 1.2.10.2 yamt if ((value = lookup_scsi_device(bus, id, &is_cdrom, &unsure)) >= 0) {
893 1.2.10.2 yamt result = (char *) malloc(20);
894 1.2.10.2 yamt if (result != NULL) {
895 1.2.10.2 yamt if (unsure) {
896 1.2.10.2 yamt suffix = " ?";
897 1.2.10.2 yamt } else {
898 1.2.10.2 yamt suffix = "";
899 1.2.10.2 yamt }
900 1.2.10.2 yamt if (is_cdrom) {
901 1.2.10.2 yamt if (value > 9) {
902 1.2.10.2 yamt // too many CD's, give up
903 1.2.10.2 yamt free(result); result = NULL;
904 1.2.10.2 yamt } else {
905 1.2.10.2 yamt snprintf(result, 20, "/dev/scd%c%s", '0' + value, suffix);
906 1.2.10.2 yamt }
907 1.2.10.2 yamt } else {
908 1.2.10.2 yamt if (value < 26) {
909 1.2.10.2 yamt snprintf(result, 20, "/dev/sd%c%s", 'a' + value, suffix);
910 1.2.10.2 yamt } else {
911 1.2.10.2 yamt snprintf(result, 20, "/dev/sd%c%c%s",
912 1.2.10.2 yamt 'a' + value / 26, 'a' + value % 26, suffix);
913 1.2.10.2 yamt }
914 1.2.10.2 yamt }
915 1.2.10.2 yamt }
916 1.2.10.2 yamt }
917 1.2.10.2 yamt return result;
918 1.2.10.2 yamt }
919 1.2.10.2 yamt
920 1.2.10.2 yamt
921 1.2.10.2 yamt void
922 1.2.10.2 yamt probe_all(void)
923 1.2.10.2 yamt {
924 1.2.10.2 yamt MEDIA_ITERATOR iter;
925 1.2.10.2 yamt char *name;
926 1.2.10.2 yamt
927 1.2.10.2 yamt iter = create_scsi_iterator();
928 1.2.10.2 yamt if (iter == 0) {
929 1.2.10.2 yamt return;
930 1.2.10.2 yamt }
931 1.2.10.2 yamt
932 1.2.10.2 yamt printf("finding devices ");
933 1.2.10.2 yamt fflush(stdout);
934 1.2.10.2 yamt while ((name = step_media_iterator(iter)) != 0) {
935 1.2.10.2 yamt /* step does the probe for us */
936 1.2.10.2 yamt printf(".");
937 1.2.10.2 yamt fflush(stdout);
938 1.2.10.2 yamt free(name);
939 1.2.10.2 yamt }
940 1.2.10.2 yamt delete_media_iterator(iter);
941 1.2.10.2 yamt printf("\n");
942 1.2.10.2 yamt fflush(stdout);
943 1.2.10.2 yamt }
944 1.2.10.2 yamt
945 1.2.10.2 yamt
946 1.2.10.2 yamt void
947 1.2.10.2 yamt probe_scsi_device(long bus, long id, int unsure)
948 1.2.10.2 yamt {
949 1.2.10.2 yamt UInt32 devType;
950 1.2.10.2 yamt
951 1.2.10.2 yamt if (DoInquiry(id, bus, &devType)) {
952 1.2.10.2 yamt if (devType == kScsiDevTypeDirect
953 1.2.10.2 yamt || devType == kScsiDevTypeOptical) {
954 1.2.10.2 yamt add_to_cache(bus, id, 0, unsure);
955 1.2.10.2 yamt } else if (devType == kScsiDevTypeCDROM
956 1.2.10.2 yamt || devType == kScsiDevTypeWorm) {
957 1.2.10.2 yamt add_to_cache(bus, id, 1, unsure);
958 1.2.10.2 yamt }
959 1.2.10.2 yamt }
960 1.2.10.2 yamt }
961 1.2.10.2 yamt
962 1.2.10.2 yamt
963 1.2.10.2 yamt long
964 1.2.10.2 yamt lookup_scsi_device(long bus, long id, int *is_cdrom, int *unsure)
965 1.2.10.2 yamt {
966 1.2.10.2 yamt /* walk down list looking for bus and id ?
967 1.2.10.2 yamt *
968 1.2.10.2 yamt * only probe out of iterate (so always add in order)
969 1.2.10.2 yamt * reset list if we reset the iterate
970 1.2.10.2 yamt */
971 1.2.10.2 yamt struct cache_item *item;
972 1.2.10.2 yamt struct cache_item *next;
973 1.2.10.2 yamt long result = -1;
974 1.2.10.2 yamt int count = 0;
975 1.2.10.2 yamt
976 1.2.10.2 yamt if (scsi_inited == 0) {
977 1.2.10.2 yamt scsi_init();
978 1.2.10.2 yamt }
979 1.2.10.2 yamt
980 1.2.10.2 yamt while (1) {
981 1.2.10.2 yamt count++;
982 1.2.10.2 yamt for (item = linux_order.first; item != NULL; item = item->next) {
983 1.2.10.2 yamt if (item->bus == bus && item->id == id) {
984 1.2.10.2 yamt result = item->value;
985 1.2.10.2 yamt *is_cdrom = item->is_cdrom;
986 1.2.10.2 yamt *unsure = item->unsure;
987 1.2.10.2 yamt break;
988 1.2.10.2 yamt }
989 1.2.10.2 yamt }
990 1.2.10.2 yamt if (count < 2 && result < 0) {
991 1.2.10.2 yamt probe_all();
992 1.2.10.2 yamt } else {
993 1.2.10.2 yamt break;
994 1.2.10.2 yamt }
995 1.2.10.2 yamt };
996 1.2.10.2 yamt
997 1.2.10.2 yamt return result;
998 1.2.10.2 yamt }
999 1.2.10.2 yamt
1000 1.2.10.2 yamt
1001 1.2.10.2 yamt /*
1002 1.2.10.2 yamt * This has the same structure as lookup_scsi_device() except we are
1003 1.2.10.2 yamt * matching on the value & type rather than the bus & id.
1004 1.2.10.2 yamt */
1005 1.2.10.2 yamt long
1006 1.2.10.2 yamt lookup_scsi_index(long index, int is_cdrom, long *bus, long *id)
1007 1.2.10.2 yamt {
1008 1.2.10.2 yamt struct cache_item *item;
1009 1.2.10.2 yamt struct cache_item *next;
1010 1.2.10.2 yamt long result = 0;
1011 1.2.10.2 yamt int count = 0;
1012 1.2.10.2 yamt
1013 1.2.10.2 yamt if (scsi_inited == 0) {
1014 1.2.10.2 yamt scsi_init();
1015 1.2.10.2 yamt }
1016 1.2.10.2 yamt
1017 1.2.10.2 yamt while (1) {
1018 1.2.10.2 yamt count++;
1019 1.2.10.2 yamt for (item = linux_order.first; item != NULL; item = item->next) {
1020 1.2.10.2 yamt if (item->value == index && item->is_cdrom == is_cdrom
1021 1.2.10.2 yamt && item->unsure == 0) {
1022 1.2.10.2 yamt result = 1;
1023 1.2.10.2 yamt *bus = item->bus;
1024 1.2.10.2 yamt *id = item->id;
1025 1.2.10.2 yamt break;
1026 1.2.10.2 yamt }
1027 1.2.10.2 yamt }
1028 1.2.10.2 yamt if (count < 2 && result == 0 && !linux_cache_loaded()) {
1029 1.2.10.2 yamt probe_all();
1030 1.2.10.2 yamt } else {
1031 1.2.10.2 yamt break;
1032 1.2.10.2 yamt }
1033 1.2.10.2 yamt };
1034 1.2.10.2 yamt
1035 1.2.10.2 yamt return result;
1036 1.2.10.2 yamt }
1037 1.2.10.2 yamt
1038 1.2.10.2 yamt
1039 1.2.10.2 yamt void
1040 1.2.10.2 yamt add_to_cache(long bus, long id, int is_cdrom, int unsure)
1041 1.2.10.2 yamt {
1042 1.2.10.2 yamt struct cache_item *item;
1043 1.2.10.2 yamt
1044 1.2.10.2 yamt item = malloc(sizeof(struct cache_item));
1045 1.2.10.2 yamt if (item == NULL) {
1046 1.2.10.2 yamt return;
1047 1.2.10.2 yamt } else {
1048 1.2.10.2 yamt item->bus = bus;
1049 1.2.10.2 yamt item->id = id;
1050 1.2.10.2 yamt item->is_cdrom = is_cdrom;
1051 1.2.10.2 yamt item->unsure = unsure;
1052 1.2.10.2 yamt if (is_cdrom) {
1053 1.2.10.2 yamt item->value = linux_order.next_cdrom;
1054 1.2.10.2 yamt linux_order.next_cdrom++;
1055 1.2.10.2 yamt } else {
1056 1.2.10.2 yamt item->value = linux_order.next_disk;
1057 1.2.10.2 yamt linux_order.next_disk++;
1058 1.2.10.2 yamt }
1059 1.2.10.2 yamt item->next = 0;
1060 1.2.10.2 yamt }
1061 1.2.10.2 yamt if (linux_order.first == NULL) {
1062 1.2.10.2 yamt linux_order.first = item;
1063 1.2.10.2 yamt linux_order.last = item;
1064 1.2.10.2 yamt } else {
1065 1.2.10.2 yamt linux_order.last->next = item;
1066 1.2.10.2 yamt linux_order.last = item;
1067 1.2.10.2 yamt }
1068 1.2.10.2 yamt }
1069 1.2.10.2 yamt
1070 1.2.10.2 yamt
1071 1.2.10.2 yamt void
1072 1.2.10.2 yamt init_linux_cache(void)
1073 1.2.10.2 yamt {
1074 1.2.10.2 yamt linux_order.first = NULL;
1075 1.2.10.2 yamt clear_linux_cache();
1076 1.2.10.2 yamt }
1077 1.2.10.2 yamt
1078 1.2.10.2 yamt
1079 1.2.10.2 yamt void
1080 1.2.10.2 yamt clear_linux_cache(void)
1081 1.2.10.2 yamt {
1082 1.2.10.2 yamt struct cache_item *item;
1083 1.2.10.2 yamt struct cache_item *next;
1084 1.2.10.2 yamt
1085 1.2.10.2 yamt for (item = linux_order.first; item != NULL; item = next) {
1086 1.2.10.2 yamt next = item->next;
1087 1.2.10.2 yamt free(item);
1088 1.2.10.2 yamt }
1089 1.2.10.2 yamt /* back to starting value */
1090 1.2.10.2 yamt linux_order.first = NULL;
1091 1.2.10.2 yamt linux_order.last = NULL;
1092 1.2.10.2 yamt linux_order.next_disk = 0;
1093 1.2.10.2 yamt linux_order.next_cdrom = 0;
1094 1.2.10.2 yamt linux_order.loaded = 0;
1095 1.2.10.2 yamt }
1096 1.2.10.2 yamt
1097 1.2.10.2 yamt
1098 1.2.10.2 yamt void
1099 1.2.10.2 yamt mark_linux_cache_loaded(void)
1100 1.2.10.2 yamt {
1101 1.2.10.2 yamt linux_order.loaded = 1;
1102 1.2.10.2 yamt }
1103 1.2.10.2 yamt
1104 1.2.10.2 yamt
1105 1.2.10.2 yamt int
1106 1.2.10.2 yamt linux_cache_loaded(void)
1107 1.2.10.2 yamt {
1108 1.2.10.2 yamt return linux_order.loaded;
1109 1.2.10.2 yamt }
1110