AmendHub

Download

jcs

/

wifi_da

/

scsi.c

 

(View History)

jcs   *: Make some warnings less warny Latest amendment: 22 on 2023-10-25

1 /*
2 * Copyright (c) 2023 joshua stein <jcs@jcs.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <SCSI.h>
18 #include <string.h>
19 #include <stdio.h>
20 #include "wi-fi.h"
21
22 struct scsi_inquiry {
23 unsigned char deviceType;
24 unsigned char deviceQualifier;
25 unsigned char version;
26 unsigned char responseFormat;
27 unsigned char additionalLength;
28 unsigned char vendor;
29 short reserved;
30 unsigned char vendorID[8];
31 unsigned char productID[16];
32 unsigned char revision[4];
33 unsigned char vendor2[20];
34 unsigned char reserved2[42];
35 unsigned char vendor3[158];
36 };
37
38 enum {
39 SCSI_READ,
40 SCSI_WRITE
41 };
42
43 unsigned char scsi_data[2048];
44 struct SCSIInstr tib[2];
45
46 short scsi_io(unsigned short scsi_id, unsigned char *cdb,
47 unsigned long cdb_len, short io_type, unsigned long len);
48
49 short
50 scsi_find_wifi(void)
51 {
52 struct scsi_inquiry inq;
53 short scsi_stat, scsi_msg;
54 unsigned char cdb[16] = { 0 };
55 short i, scsi_id;
56
57 cdb[0] = 0x12; /* inquiry */
58 cdb[4] = 5; /* length */
59
60 tib[0].scOpcode = scNoInc;
61 tib[0].scParam1 = (unsigned long)&inq;
62 tib[0].scParam2 = 5;
63 tib[1].scOpcode = scStop;
64 tib[1].scParam1 = 0;
65 tib[1].scParam2 = 0;
66
67 SCSIReset();
68
69 for (scsi_id = 0; scsi_id <= 7; scsi_id++) {
70 for (i = 0; i <= 1; i++) {
71 if (SCSIGet() != noErr)
72 goto scan_failed;
73
74 if (SCSISelect(scsi_id) != noErr)
75 break;
76
77 if (SCSICmd((Ptr)&cdb, 6) != noErr) {
78 SCSIComplete(&scsi_stat, &scsi_msg, 300);
79 goto scan_failed;
80 }
81
82 memset(&inq, 0, sizeof(inq));
83
84 if (SCSIRead((Ptr)&tib) != noErr) {
85 SCSIComplete(&scsi_stat, &scsi_msg, 300);
86 goto scan_failed;
87 }
88
89 if (i == 0) {
90 cdb[4] += inq.additionalLength;
91 tib[0].scParam2 += inq.additionalLength;
92 }
93
94 if (SCSIComplete(&scsi_stat, &scsi_msg, 300) != noErr)
95 goto scan_failed;
96
97 if (i == 0)
98 /* re-inquire with full length */
99 continue;
100
101 inq.vendorID[sizeof(inq.vendorID) - 1] = '\0';
102 inq.productID[sizeof(inq.productID) - 1] = '\0';
103 DEBUG_LOG(("scsi[%d]: v \"%s\", p \"%s\"", scsi_id,
104 inq.vendorID, inq.productID));
105
106 if (memcmp(inq.vendorID, "Dayna", 5) != 0 ||
107 memcmp(inq.productID, "SCSI/Link", 9) != 0)
108 break;
109
110 if (scsi_wifi_info(scsi_id, NULL))
111 return scsi_id;
112
113 DEBUG_LOG(("scsi[%d]: matched vendor/product but no info",
114 scsi_id));
115 }
116 }
117
118 scan_failed:
119 return WIFI_SCSI_ID_NONE;
120 }
121
122 bool
123 scsi_wifi_scan(short scsi_id)
124 {
125 unsigned char cdb[6];
126
127 memset(wifi_scan_networks, 0, sizeof(wifi_scan_networks));
128
129 memset(cdb, 0, sizeof(cdb));
130 cdb[0] = BLUESCSI_NETWORK_WIFI_CMD;
131 cdb[1] = BLUESCSI_NETWORK_WIFI_CMD_SCAN;
132 cdb[4] = 0x01;
133
134 wifi_scan_started = Time;
135
136 return (scsi_io(scsi_id, cdb, sizeof(cdb), SCSI_READ, 1) != -1);
137 }
138
139 bool
140 scsi_wifi_scan_finished(short scsi_id)
141 {
142 unsigned char cdb[6];
143
144 memset(cdb, 0, sizeof(cdb));
145 cdb[0] = BLUESCSI_NETWORK_WIFI_CMD;
146 cdb[1] = BLUESCSI_NETWORK_WIFI_CMD_COMPLETE;
147 cdb[4] = 0x01;
148
149 if (scsi_io(scsi_id, cdb, sizeof(cdb), SCSI_READ, 1) == -1)
150 return true;
151
152 if (scsi_data[0] == 1)
153 return true;
154
155 return false;
156 }
157
158 short
159 scsi_wifi_scan_results(short scsi_id, struct wifi_network_entry *resp,
160 short count)
161 {
162 unsigned char cdb[6];
163 size_t size, net_count;
164
165 memset(cdb, 0, sizeof(cdb));
166 cdb[0] = BLUESCSI_NETWORK_WIFI_CMD;
167 cdb[1] = BLUESCSI_NETWORK_WIFI_CMD_SCAN_RESULTS;
168 cdb[3] = (sizeof(scsi_data) >> 8) & 0xff;
169 cdb[4] = sizeof(scsi_data) & 0xff;
170
171 if (scsi_io(scsi_id, cdb, sizeof(cdb), SCSI_READ,
172 sizeof(scsi_data)) == -1)
173 return 0;
174
175 size = (scsi_data[0] << 8) | scsi_data[1];
176 net_count = size / sizeof(struct wifi_network_entry);
177 if (net_count > count)
178 net_count = count;
179
180 memset(resp, 0, sizeof(struct wifi_network_entry) * count);
181 memcpy(resp, scsi_data + 2, sizeof(struct wifi_network_entry) * count);
182
183 return net_count;
184 }
185
186 bool
187 scsi_wifi_info(short scsi_id, struct wifi_network_entry *resp)
188 {
189 static struct wifi_network_entry wifi_info;
190 unsigned char cdb[6];
191 short size;
192
193 memset(cdb, 0, sizeof(cdb));
194 cdb[0] = BLUESCSI_NETWORK_WIFI_CMD;
195 cdb[1] = BLUESCSI_NETWORK_WIFI_CMD_INFO;
196
197 size = sizeof(struct wifi_network_entry) + 2;
198 cdb[3] = (size >> 8) & 0xff;
199 cdb[4] = size & 0xff;
200
201 if (scsi_io(scsi_id, cdb, sizeof(cdb), SCSI_READ, size) == -1)
202 return false;
203
204 if (resp != NULL) {
205 memset(resp, 0, sizeof(struct wifi_network_entry));
206 /* skip returned size */
207 memcpy(resp, scsi_data + 2, sizeof(struct wifi_network_entry));
208 }
209
210 return true;
211 }
212
213 bool
214 scsi_wifi_join(short scsi_id, struct wifi_join_request *wjr)
215 {
216 unsigned char cdb[6];
217 unsigned short size;
218 unsigned char n;
219
220 memset(cdb, 0, sizeof(cdb));
221 cdb[0] = BLUESCSI_NETWORK_WIFI_CMD;
222 cdb[1] = BLUESCSI_NETWORK_WIFI_CMD_JOIN;
223
224 size = sizeof(struct wifi_join_request);
225 cdb[3] = (size >> 8) & 0xff;
226 cdb[4] = size & 0xff;
227
228 memcpy(scsi_data, wjr, sizeof(struct wifi_join_request));
229
230 return (scsi_io(scsi_id, cdb, sizeof(cdb), SCSI_WRITE, size) != -1);
231 }
232
233 short
234 scsi_io(unsigned short scsi_id, unsigned char *cdb, unsigned long cdb_len,
235 short io_type, unsigned long len)
236 {
237 short scsi_stat, scsi_msg;
238 short ret, ioret;
239
240 if (SCSIGet() != noErr) {
241 warn("SCSIGet failed");
242 return -1;
243 }
244
245 if (SCSISelect(scsi_id) != noErr) {
246 warn("SCSISelect failed");
247 return -1;
248 }
249
250 if (SCSICmd((Ptr)cdb, cdb_len) != noErr) {
251 SCSIComplete(&scsi_stat, &scsi_msg, 300);
252 warn("SCSICmd failed");
253 return -1;
254 }
255
256 if (len) {
257 switch (io_type) {
258 case SCSI_READ:
259 memset(scsi_data, 0, sizeof(scsi_data));
260
261 tib[0].scOpcode = scNoInc;
262 tib[0].scParam1 = (long)&scsi_data;
263 tib[0].scParam2 = len;
264 tib[1].scOpcode = scStop;
265 tib[1].scParam1 = 0;
266 tib[1].scParam2 = 0;
267
268 ioret = SCSIRead((Ptr)&tib);
269 break;
270 case SCSI_WRITE:
271 tib[0].scOpcode = scNoInc;
272 tib[0].scParam1 = (long)&scsi_data;
273 tib[0].scParam2 = len;
274 tib[1].scOpcode = scStop;
275 tib[1].scParam1 = 0;
276 tib[1].scParam2 = 0;
277
278 ioret = SCSIWrite((Ptr)&tib);
279 break;
280 }
281 } else {
282 tib[0].scOpcode = scStop;
283 tib[0].scParam1 = 0;
284 tib[0].scParam2 = 0;
285
286 ioret = noErr;
287 }
288
289 /* complete and free the bus before responding to the read/write */
290 if (SCSIComplete(&scsi_stat, &scsi_msg, 300 /* 1/60 ticks */) != noErr) {
291 DEBUG_LOG(("SCSIComplete failed"));
292 return -1;
293 }
294
295 if (ioret != noErr && ioret != scPhaseErr)
296 DEBUG_LOG(("SCSIRead/Write failed: %d", ioret));
297
298 if (scsi_stat != noErr)
299 DEBUG_LOG(("SCSIComplete bad status: %d", scsi_stat));
300
301 return len;
302 }