Download
akuker
/scsi_test
/DoListSCSIDevices.c
(View History)
akuker Initial Commit | Latest amendment: 1 on 2022-08-21 |
1 | /* DoListSCSIDevices.c */ |
2 | /* |
3 | * DoListSCSIDevices.c |
4 | * Copyright © 1992-94 Apple Computer Inc. All Rights Reserved. |
5 | * |
6 | * Find all SCSI devices. The alogrithm first asks the SCSI Manager for the |
7 | * number of busses, then loops through each bus for each device and LUN. |
8 | * old SCSI Manager. This is made complex by the flexible SCSI Manager 4.3 |
9 | * architecture: it is possible for the asynchronous SCSI Manager to only |
10 | * be available on a third-party bus interface, for example. Because of this, |
11 | * we must always scan the bus using the original SCSI Manager even if the |
12 | * asynchronous manager is present. |
13 | */ |
14 | //#include "SCSISimpleSample.h" |
15 | |
16 | |
17 | |
18 | |
19 | /* |
20 | * These definitions are only for the code files. |
21 | */ |
22 | #ifndef THINK_C /* MPW includes */ |
23 | #include <Errors.h> |
24 | #include <Script.h> |
25 | #include <Types.h> |
26 | #include <Resources.h> |
27 | #include <QuickDraw.h> |
28 | #include <Fonts.h> |
29 | #include <Events.h> |
30 | #include <Windows.h> |
31 | #include <ToolUtils.h> |
32 | #include <Memory.h> |
33 | #include <Menus.h> |
34 | #include <Lists.h> |
35 | #include <Printing.h> |
36 | #include <Dialogs.h> |
37 | #include <Packages.h> |
38 | #endif |
39 | |
40 | |
41 | |
42 | #include "scsi_test.h" |
43 | #include "MacSCSICommand.h" |
44 | //#include "LogManager.h" |
45 | |
46 | void |
47 | DoListSCSIDevices(void) |
48 | { |
49 | OSErr status; |
50 | unsigned short lastHostBus; |
51 | unsigned short initiatorID; |
52 | unsigned short bus; |
53 | unsigned short targetID; |
54 | unsigned short LUN; |
55 | DeviceIdent scsiDevice; |
56 | SCSIGetVirtualIDInfoPB scsiGetVirtualIDInfo; |
57 | short deviceCount; |
58 | unsigned short maxTarget; |
59 | Boolean useAsynchManager; |
60 | Str255 work; |
61 | |
62 | LOG("\pList all SCSI Devices"); |
63 | deviceCount = 0; |
64 | /* |
65 | * If we have the asynchronous SCSI Manager, find out how many busses |
66 | * are present on this system. If not, force a "single bus" scan, since |
67 | * DoSCSICommandWithSense ignores the hostBus information if it is |
68 | * forced into "old-style" calls. |
69 | */ |
70 | if (gEnableNewSCSIManager) |
71 | status = SCSIGetHighHostBusAdaptor(&lastHostBus); |
72 | else { |
73 | status = noErr; |
74 | lastHostBus = 0; /* Force one bus only */ |
75 | } |
76 | if (status == noErr) { |
77 | for (bus = 0; bus <= lastHostBus; bus++) { |
78 | /* |
79 | * Look at this SCSI bus. This would be a good place to allocate |
80 | * the SCSIExecIO command block. In this sample, however, it's |
81 | * allocated on each call to AsyncSCSI, though this is inefficient. |
82 | * Note that it is possible to have busses with no devices. This |
83 | * is true for Apple Macintosh models with two busses (such as |
84 | * the Quadra 950 and PowerMac 8100). Also, if you install a |
85 | * third-party bus adaptor that supports the asynchronous SCSI |
86 | * Manager on a machine with two busses, it would be assigned |
87 | * bus 2 (with busses 0 and 1 referencing the internal system |
88 | * busses). In this case, a system could have no devices on bus |
89 | * 0 or 1. |
90 | */ |
91 | *((long *) &scsiDevice) = 0; |
92 | scsiDevice.bus = bus; |
93 | /* |
94 | * Check whether we can access this scsi device. SCSIBusAPI will |
95 | * return an error status if this bus is inaccessable (i.e. no bus |
96 | * or other trouble). If it returns noErr, useAsyncManager will |
97 | * be TRUE if the asynchronous SCSI Manager is supported for this |
98 | * bus, and FALSE if it can only be accessed through the original |
99 | * SCSI Manager. This would indicate that a third-party bus |
100 | * interface patched the original SCSI Manager traps (i.e., |
101 | * patched SCSIGet, SCSISelect, etc). |
102 | */ |
103 | status = SCSIBusAPI(scsiDevice, &useAsynchManager); |
104 | if (status == noErr) { |
105 | if (useAsynchManager) |
106 | status = SCSIGetInitiatorID(scsiDevice, &initiatorID); |
107 | else { |
108 | initiatorID = 7; /* Asynch manager is disabled */ |
109 | } |
110 | } |
111 | if (status != noErr) |
112 | continue; |
113 | /* |
114 | * SCSIGetInitiatorID returned the bus ID of the Macintosh. This |
115 | * is almost always seven, but only the SCSI Manager knows for |
116 | * sure. Note that, by getting the Macintosh bus ID dynamically, |
117 | * we prepare the code for a future system that permitted more |
118 | * than one Macintosh on the same SCSI bus. |
119 | */ |
120 | status = SCSIGetMaxTargetID(scsiDevice, &maxTarget); |
121 | for (targetID = 0; targetID <= maxTarget; targetID++) { |
122 | if (targetID != initiatorID) { |
123 | scsiDevice.targetID = targetID; |
124 | for (LUN = 0; LUN <= gMaxLogicalUnit; LUN++) { |
125 | /* |
126 | * Try to send a command to this LUN. If it fails, |
127 | * don't try for higher-valued LUNs. |
128 | * SCSICheckForDevicePresent looks, carefully, at the |
129 | * returned error to distinguish between missing |
130 | * devices and devices that are present, but unable to |
131 | * respond, such as CD-ROM players with no disk |
132 | * inserted. This call to SCSICheckForDevicePresent |
133 | * will use the asynchronous SCSI Manager if it can. |
134 | * |
135 | * Note that, if the asynchronous manager is not |
136 | * available, we can still check for non-zero LUNs by |
137 | * using the old method of stuffing the LUN into the |
138 | * command block, however this is not supported in |
139 | * this example. |
140 | */ |
141 | scsiDevice.LUN = LUN; |
142 | if (SCSICheckForDevicePresent( |
143 | scsiDevice, useAsynchManager) == FALSE) |
144 | break; /* Don't look for LUNs */ |
145 | else { |
146 | ++deviceCount; /* Found a device */ |
147 | DoGetDriveInfo(scsiDevice, TRUE, useAsynchManager); |
148 | } /* Check status */ |
149 | } /* LUN loop */ |
150 | } /* Not the initiator id */ |
151 | } /* Target loop */ |
152 | } /* Bus loop */ |
153 | /* |
154 | * Now, we need to look at the hard-wired SCSI drive addresses and |
155 | * check whether a third-party hardware interface that does not use |
156 | * the asynchronous SCSI Manager recognizes this address. If |
157 | * gEnableNewSCSIManager is FALSE, the above loop called the original |
158 | * SCSI Manager, so we don't have to try it again. In this sequence, |
159 | * we hard-wire the initiator ID to seven, as there is no supported |
160 | * way to determine it from the SCSI Manager or operating system. |
161 | */ |
162 | if (gEnableNewSCSIManager) { |
163 | scsiDevice.bus = 0; |
164 | for (targetID = 0; targetID <= 6; targetID++) { |
165 | CLEAR(scsiGetVirtualIDInfo); |
166 | scsiGetVirtualIDInfo.scsiPBLength = sizeof scsiGetVirtualIDInfo; |
167 | scsiGetVirtualIDInfo.scsiOldCallID = targetID; |
168 | status = SCSIAction((SCSI_PB *) &scsiGetVirtualIDInfo); |
169 | if (status != noErr) { |
170 | /* |
171 | * The asynchronous SCSI Manager does not know about this |
172 | * target ID. Check whether it exists (forcing the request |
173 | * to use the original SCSI Manager). |
174 | */ |
175 | scsiDevice.targetID = targetID; |
176 | for (LUN = 0; LUN <= gMaxLogicalUnit; LUN++) { |
177 | scsiDevice.LUN = LUN; |
178 | if (SCSICheckForDevicePresent(scsiDevice, FALSE) == FALSE) |
179 | break; /* Don't look for LUNs */ |
180 | else { |
181 | ++deviceCount; /* Found a device */ |
182 | DoGetDriveInfo(scsiDevice, TRUE, FALSE); |
183 | } /* Check status */ |
184 | } |
185 | } |
186 | } |
187 | } |
188 | } /* Found a host adaptor */ |
189 | NumToString(deviceCount, work); |
190 | AppendPascalString(work, "\p SCSI Devices"); |
191 | LOG(work); |
192 | } |